From 57c06f1e5bd65da525f3e3c09da3c15578c9094f Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 28 Mar 2025 16:44:44 +0530 Subject: [PATCH 001/343] update: use buttons instead of links for inner-base template. --- app/config/locale/templates/email-inner-base.tpl | 2 +- app/config/locale/translations/en.json | 3 +++ app/controllers/api/account.php | 2 ++ app/controllers/api/projects.php | 1 + app/controllers/api/teams.php | 1 + 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/config/locale/templates/email-inner-base.tpl b/app/config/locale/templates/email-inner-base.tpl index 8cef391d2f..c17e37ab8a 100644 --- a/app/config/locale/templates/email-inner-base.tpl +++ b/app/config/locale/templates/email-inner-base.tpl @@ -1,6 +1,6 @@

{{hello}}

{{body}}

-

{{redirect}}

+

{{buttonText}}

{{footer}}

{{thanks}} diff --git a/app/config/locale/translations/en.json b/app/config/locale/translations/en.json index d9dfddb017..dbfa2e1be8 100644 --- a/app/config/locale/translations/en.json +++ b/app/config/locale/translations/en.json @@ -8,6 +8,7 @@ "emails.verification.body": "Follow this link to verify your email address to your {{b}}{{project}}{{/b}} account.", "emails.verification.footer": "If you didn’t ask to verify this address, you can ignore this message.", "emails.verification.thanks": "Thanks,", + "emails.verification.buttonText": "Confirm email address", "emails.verification.signature": "{{project}} team", "emails.magicSession.subject": "{{project}} Login", "emails.magicSession.hello": "Hello {{user}},", @@ -45,12 +46,14 @@ "emails.recovery.body": "Follow this link to reset your {{b}}{{project}}{{/b}} password.", "emails.recovery.footer": "If you didn't ask to reset your password, you can ignore this message.", "emails.recovery.thanks": "Thanks,", + "emails.recovery.buttonText": "Reset password", "emails.recovery.signature": "{{project}} team", "emails.invitation.subject": "Invitation to %s Team at %s", "emails.invitation.hello": "Hello {{user}},", "emails.invitation.body": "This mail was sent to you because {{b}}{{owner}}{{/b}} wanted to invite you to become a member of the {{b}}{{team}}{{/b}} team at {{b}}{{project}}{{/b}}.", "emails.invitation.footer": "If you are not interested, you can ignore this message.", "emails.invitation.thanks": "Thanks,", + "emails.invitation.buttonText": "Accept invite to {{team}}", "emails.invitation.signature": "{{project}} team", "emails.certificate.subject": "Certificate failure for %s", "emails.certificate.hello": "Hello,", diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 20f64496ac..b2ae5068fa 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -3235,6 +3235,7 @@ App::post('/v1/account/recovery') ->setParam('{{hello}}', $locale->getText("emails.recovery.hello")) ->setParam('{{footer}}', $locale->getText("emails.recovery.footer")) ->setParam('{{thanks}}', $locale->getText("emails.recovery.thanks")) + ->setParam('{{buttonText}}', $locale->getText("emails.recovery.buttonText")) ->setParam('{{signature}}', $locale->getText("emails.recovery.signature")); $body = $message->render(); @@ -3497,6 +3498,7 @@ App::post('/v1/account/verification') ->setParam('{{hello}}', $locale->getText("emails.verification.hello")) ->setParam('{{footer}}', $locale->getText("emails.verification.footer")) ->setParam('{{thanks}}', $locale->getText("emails.verification.thanks")) + ->setParam('{{buttonText}}', $locale->getText("emails.verification.buttonText")) ->setParam('{{signature}}', $locale->getText("emails.verification.signature")); $body = $message->render(); diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 48d20cd17f..9f2654bf95 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -2209,6 +2209,7 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale') ->setParam('{{footer}}', $localeObj->getText("emails.{$type}.footer")) ->setParam('{{body}}', $localeObj->getText('emails.' . $type . '.body'), escapeHtml: false) ->setParam('{{thanks}}', $localeObj->getText("emails.{$type}.thanks")) + ->setParam('{{buttonText}}', $localeObj->getText("emails.{$type}.buttonText")) ->setParam('{{signature}}', $localeObj->getText("emails.{$type}.signature")) ->setParam('{{direction}}', $localeObj->getText('settings.direction')); $message = $message->render(); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index b45c9fd3b9..53cf5ed007 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -652,6 +652,7 @@ App::post('/v1/teams/:teamId/memberships') ->setParam('{{hello}}', $locale->getText("emails.invitation.hello")) ->setParam('{{footer}}', $locale->getText("emails.invitation.footer")) ->setParam('{{thanks}}', $locale->getText("emails.invitation.thanks")) + ->setParam('{{buttonText}}', $locale->getText("emails.invitation.buttonText")) ->setParam('{{signature}}', $locale->getText("emails.invitation.signature")); $body = $message->render(); From 0071f0e72888c41efebcb36da16a5a23405872ad Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 28 Mar 2025 19:40:56 +0530 Subject: [PATCH 002/343] update: languages; will update the rest later ;) Note: have cross referenced with GPT, Google Translator and various other regional translators. --- app/config/locale/translations/af.json | 3 +++ app/config/locale/translations/ar-ma.json | 3 +++ app/config/locale/translations/ar.json | 3 +++ app/config/locale/translations/as.json | 3 +++ app/config/locale/translations/az.json | 3 +++ app/config/locale/translations/be.json | 3 +++ app/config/locale/translations/bh.json | 3 +++ app/config/locale/translations/bn.json | 3 +++ app/config/locale/translations/ca.json | 3 +++ app/config/locale/translations/da.json | 3 +++ app/config/locale/translations/de.json | 3 +++ app/config/locale/translations/el.json | 3 +++ app/config/locale/translations/eo.json | 3 +++ app/config/locale/translations/es.json | 3 +++ app/config/locale/translations/fa.json | 3 +++ app/config/locale/translations/fr.json | 3 +++ app/config/locale/translations/ga.json | 3 +++ app/config/locale/translations/gu.json | 3 +++ app/config/locale/translations/he.json | 3 +++ 19 files changed, 57 insertions(+) diff --git a/app/config/locale/translations/af.json b/app/config/locale/translations/af.json index e68fda2c75..9b313ac92a 100644 --- a/app/config/locale/translations/af.json +++ b/app/config/locale/translations/af.json @@ -8,6 +8,7 @@ "emails.verification.body": "Volg hierdie skakel om u e-pos adres te bevestig.", "emails.verification.footer": "Ignoreer gerus hierdie boodskap as u nie die versoek gestuur het om u adres te bevestig nie.", "emails.verification.thanks": "Baie dankie,", + "emails.verification.buttonText": "Bevestig e-posadres", "emails.verification.signature": "Die {{project}} span", "emails.magicSession.subject": "Teken aan", "emails.magicSession.hello": "Goeie dag,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Volg hierdie skakel om u {{project}} wagwoord te herstel.", "emails.recovery.footer": "Ignoreer gerus hierdie boodskap as u nie die versoek gestuur het om u wagwoord te herstel nie.", "emails.recovery.thanks": "Baie dankie,", + "emails.recovery.buttonText": "Stel wagwoord terug", "emails.recovery.signature": "Die {{project}} span", "emails.invitation.subject": "Uitnodiging om by die %s span aan te sluit by %s", "emails.invitation.hello": "Goeie dag,", "emails.invitation.body": "Hierdie boodskap is aan u gestuur omdat {{owner}} u uitnooi om 'n lid van die {{team}} groep by die {{project}} projek te wees.", "emails.invitation.footer": "As u nie belang stel nie, kan u gerus hierdie boodskap ignoreer.", "emails.invitation.thanks": "Baie dankie,", + "emails.invitation.buttonText": "Aanvaar uitnodiging na {{team}}", "emails.invitation.signature": "Die {{project}} span", "locale.country.unknown": "Onbekend", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/ar-ma.json b/app/config/locale/translations/ar-ma.json index efd2e95c31..e4b5b1f558 100644 --- a/app/config/locale/translations/ar-ma.json +++ b/app/config/locale/translations/ar-ma.json @@ -8,6 +8,7 @@ "emails.verification.body": "تبّع هاد الوصلة باش تيقّن لادريسة تاع ليميل ديالك.", "emails.verification.footer": "إلا ماشي نتا اللي طلبتي تيقّن هاد لادريسة تاع ليميل، ممكن تنخّل هاد البرية.", "emails.verification.thanks": "شكرا،", + "emails.verification.buttonText": "تأكيد عنوان البريد الإلكتروني", "emails.verification.signature": "فرقة {{project}}", "emails.magicSession.subject": "تكونيكطا", "emails.magicSession.hello": "السلام،", @@ -20,12 +21,14 @@ "emails.recovery.body": "تبّع هاد الوصلة باش تبدّل كلمة السر تاع {{project}}.", "emails.recovery.footer": "إلا ماشي نتا اللي طلبتي تبدّل كلمة السر، ممكن تنخّل هاد البرية.", "emails.recovery.thanks": "شكرا،", + "emails.recovery.buttonText": "إعادة تعيين كلمة السر", "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.buttonText": "اقبل الدعوة إلى {{team}}", "emails.invitation.signature": "فرقة {{project}}", "emails.certificate.subject": "السرتافيكة فشلات ل %s", "emails.certificate.hello": "السلام،", diff --git a/app/config/locale/translations/ar.json b/app/config/locale/translations/ar.json index 1d67c2ecf7..eda0652fbe 100644 --- a/app/config/locale/translations/ar.json +++ b/app/config/locale/translations/ar.json @@ -8,6 +8,7 @@ "emails.verification.body": "برجاء اتباع الرابط التالي لتأكيد بريدك الإلكتروني", "emails.verification.footer": "لو لم تطلب تأكيد هذا البريد الإلكتروني، يمكنك تجاهل هذه الرسالة", "emails.verification.thanks": "شكرا،", + "emails.verification.buttonText": "تأكيد عنوان البريد الإلكتروني", "emails.verification.signature": "فريق {{project}}", "emails.magicSession.subject": "تسجيل الدخول", "emails.magicSession.hello": "أهلا،", @@ -20,12 +21,14 @@ "emails.recovery.body": "برجاء اتباع الراط التالي لتغيير كلمة السر الخاصة بـ{{project}}", "emails.recovery.footer": "لولم تطلب تغيير كلمة السر، يمكنك تجاهل هذه الرسالة", "emails.recovery.thanks": "شكرا،", + "emails.recovery.buttonText": "إعادة تعيين كلمة المرور", "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.buttonText": "قبول الدعوة إلى {{team}}", "emails.invitation.signature": "فريق {{project}}", "locale.country.unknown": "مجهول", "countries.af": "أفغانستان", diff --git a/app/config/locale/translations/as.json b/app/config/locale/translations/as.json index 572ed80f1a..60e385a8ac 100644 --- a/app/config/locale/translations/as.json +++ b/app/config/locale/translations/as.json @@ -8,6 +8,7 @@ "emails.verification.body": "আপোনাৰ ইমেইল ঠিকনা প্ৰমাণিত কৰিবলৈ এই লিংকটো অনুসৰণ কৰক।", "emails.verification.footer": "যদি আপুনি এই ঠিকনাটো সত্যাপিত কৰিবলৈ কোৱা নাই, আপুনি এই বাৰ্তাটো উপেক্ষা কৰিব পাৰে।", "emails.verification.thanks": "ধন্যবাদ,", + "emails.verification.buttonText": "ইমেইল ঠিকনা নিশ্চিত কৰক", "emails.verification.signature": "{{project}} দল", "emails.magicSession.subject": "লগইন", "emails.magicSession.hello": "নমস্কাৰ,", @@ -20,12 +21,14 @@ "emails.recovery.body": "আপোনাৰ {{project}} পাছৱৰ্ড ৰিছেট কৰিবলৈ এই লিংকটো অনুসৰণ কৰক।.", "emails.recovery.footer": "যদি আপুনি আপোনাৰ পাছৱৰ্ড ৰিছেট কৰিবলৈ কোৱা নাছিল, আপুনি এই বাৰ্তাটো উপেক্ষা কৰিব পাৰে।", "emails.recovery.thanks": "ধন্যবাদ,", + "emails.recovery.buttonText": "পাছৱৰ্ড ৰিছেট কৰক", "emails.recovery.signature": "{{project}} দল", "emails.invitation.subject": "%s বছৰত %s দললৈ নিমন্ত্ৰণ", "emails.invitation.hello": "নমস্কাৰ,", "emails.invitation.body": "এই মেইলটো আপোনালৈ প্ৰেৰণ কৰা হৈছিল কাৰণ {{owner}} জনে আপোনাক {{project}} বছৰবয়সত {{team}} দলৰ সদস্য হ'বলৈ আমন্ত্ৰণ জনাব বিচাৰিছিল।", "emails.invitation.footer": "যদি আপুনি আগ্ৰহী নহয়, আপুনি এই বাৰ্তাটো উপেক্ষা কৰিব পাৰে।", "emails.invitation.thanks": "ধন্যবাদ,", + "emails.invitation.buttonText": "{{team}}-লৈ নিমন্ত্ৰণ গ্ৰহণ কৰক", "emails.invitation.signature": "{{project}} দল", "locale.country.unknown": "অজ্ঞাত ", "countries.af": "আফগানিস্তান ", diff --git a/app/config/locale/translations/az.json b/app/config/locale/translations/az.json index 5988c51786..63e442f7c5 100644 --- a/app/config/locale/translations/az.json +++ b/app/config/locale/translations/az.json @@ -8,6 +8,7 @@ "emails.verification.body": "E-poçt ünvanınızı təsdiq etmək üçün bu linki izləyin.", "emails.verification.footer": "Bu ünvanı doğrulamağı xahiş etməmisinizsə, bu mesajı gözardı edə bilərsiniz.", "emails.verification.thanks": "Təşəkkürlər,", + "emails.verification.buttonText": "E-poçt ünvanını təsdiqlə", "emails.verification.signature": "{{project}} komandası", "emails.magicSession.subject": "Daxil Olmaq", "emails.magicSession.hello": "Salam,", @@ -20,12 +21,14 @@ "emails.recovery.body": "{{project}} şifrənizi sıfırlamaq üçün bu linki izləyin.", "emails.recovery.footer": "Şifrənizi sıfırlamağı xahiş etməmisinizsə, bu mesajı gözardı edə bilərsiniz.", "emails.recovery.thanks": "Təşəkkürlər,", + "emails.recovery.buttonText": "Şifrəni sıfırla", "emails.recovery.signature": "{{project}} komandası", "emails.invitation.subject": "%s Komandasına Dəvət %sdə", "emails.invitation.hello": "Salam,", "emails.invitation.body": "{{owner}}, {{project}}də {{team}} komandasına üzv olmağa dəvət etmək istədiyi üçün bu məktub sizə göndərildi.", "emails.invitation.footer": "Əgər maraqlanmırsınızsa, bu mesajı gözardı edə bilərsiniz.", "emails.invitation.thanks": "Təşəkkürlər,", + "emails.invitation.buttonText": "{{team}} dəvətini qəbul et", "emails.invitation.signature": "{{project}} komandası", "locale.country.unknown": "Naməlum", "countries.af": "Əfqanıstan", diff --git a/app/config/locale/translations/be.json b/app/config/locale/translations/be.json index f03a9d5bef..b4ae0827c3 100644 --- a/app/config/locale/translations/be.json +++ b/app/config/locale/translations/be.json @@ -8,6 +8,7 @@ "emails.verification.body": "Перайдзіце па гэтай спасылцы, каб пацвердзіць свой адрас электроннай пошты", "emails.verification.footer": "Калі вы не запытвалі пацвярджэнне гэтага адрасу, праігнаруйце гэтае паведамленне.", "emails.verification.thanks": "Дзякуем,", + "emails.verification.buttonText": "Пацвердзіць адрас электроннай пошты", "emails.verification.signature": "каманда {{project}}", "emails.magicSession.subject": "Лагін", "emails.magicSession.hello": "Прывітанне,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Перайдзіце па гэтай спасылцы, каб скінуць пароль для праекта {{project}}.", "emails.recovery.footer": "Калі вы не прасілі скінуць пароль, вы можаце праігнараваць гэта паведамленне.", "emails.recovery.thanks": "Дзякуем,", + "emails.recovery.buttonText": "Аднавіць пароль", "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.buttonText": "Прыняць запрашэнне ў {{team}}", "emails.invitation.signature": "каманда {{project}}", "locale.country.unknown": "Невядомы", "countries.af": "Афганістан", diff --git a/app/config/locale/translations/bh.json b/app/config/locale/translations/bh.json index 5cf06bd1dd..7d2b469ed5 100644 --- a/app/config/locale/translations/bh.json +++ b/app/config/locale/translations/bh.json @@ -8,6 +8,7 @@ "emails.verification.body": "ईमेल प्रमाणिकरण करे क लेल दिहल गइल लिंक फॉलो करें|", "emails.verification.footer": "अगर ई पता को सत्यापित करे के लिए ना कहाले, तो आप ई संदेश क अनदेखा कर सकत अछि।", "emails.verification.thanks": "धन्यवाद,", + "emails.verification.buttonText": "ईमेल पता के पुष्टि करीं", "emails.verification.signature": "{{project}} टीम", "emails.magicSession.subject": "लॉग इन करीं|", "emails.magicSession.hello": "प्रणाम,", @@ -20,12 +21,14 @@ "emails.recovery.body": "पासवर्ड बदल क लेल दिहल गइल लिंक फॉलो करें|", "emails.recovery.footer": "अगर पासवर्ड बदल क लेल ना कहाले, तो आप ई संदेश क अनदेखा कर सकत अछि।", "emails.recovery.thanks": "धन्यवाद,", + "emails.recovery.buttonText": "पासवर्ड रीसेट करीं", "emails.recovery.signature": "{{project}} टीम", "emails.invitation.subject": "%s टीम क %s पे न्योता देवे क लेल|", "emails.invitation.hello": "प्रणाम,", "emails.invitation.body": "ई मेल आपके एही लेल भेजल गईल रहल काहे क {{owner}} आपके {{project}} क {{team}} टीम का सदस्य बनावे चाहित रहे|", "emails.invitation.footer": "अगर आवे क इच्छा ना होवत, तो आप ई संदेश क अनदेखा कर सकत अछि।", "emails.invitation.thanks": "धन्यवाद,", + "emails.invitation.buttonText": "{{team}} में नेवता स्वीकार करीं", "emails.invitation.signature": "{{project}} टीम", "locale.country.unknown": "अनजान", "countries.af": "अफ़ग़ानिस्तान", diff --git a/app/config/locale/translations/bn.json b/app/config/locale/translations/bn.json index 495f56e012..1157d5cc0f 100644 --- a/app/config/locale/translations/bn.json +++ b/app/config/locale/translations/bn.json @@ -8,6 +8,7 @@ "emails.verification.body": "এই লিঙ্কের মাধ্যমে ইমেইল যাচাই করুন।", "emails.verification.footer": "আপনি যদি এই ঠিকানা যাচাই করতে না বলেন, তাহলে আপনি এই বার্তাটি উপেক্ষা করতে পারেন।", "emails.verification.thanks": "ধন্যবাদ,", + "emails.verification.buttonText": "ইমেইল ঠিকানা নিশ্চিত করুন", "emails.verification.signature": "{{project}} টীম", "emails.magicSession.subject": "লগ ইন", "emails.magicSession.hello": "নমস্কার,", @@ -20,12 +21,14 @@ "emails.recovery.body": "এই লিঙ্কের মাধ্যমে আপনার {{project}} পাসওয়ার্ড পুনরায় সেট করুন।", "emails.recovery.footer": "আপনি যদি আপনার পাসওয়ার্ড পুনরায় সেট করতে না বলেন, তাহলে আপনি এই বার্তাটি উপেক্ষা করতে পারেন।", "emails.recovery.thanks": "ধন্যবাদ,", + "emails.recovery.buttonText": "পাসওয়ার্ড রিসেট করুন", "emails.recovery.signature": "{{project}} টীম", "emails.invitation.subject": "%s টিমকে %s তে আমন্ত্রণ জানান", "emails.invitation.hello": "নমস্কার,", "emails.invitation.body": "এই মেইলটি আপনাকে পাঠানো হয়েছে কারণ {{owner}} আপনাকে {{project}} এর সাথে যুক্ত {{team}} টিমের সদস্য হওয়ার জন্য আমন্ত্রণ জানাতে চেয়েছিলেন।", "emails.invitation.footer": "যদি এটি আপনার জন্য প্রয়োজনীয় না হয়, আপনি এই বার্তাটি উপেক্ষা করতে পারেন।", "emails.invitation.thanks": "ধন্যবাদ,", + "emails.invitation.buttonText": "{{team}}-এর আমন্ত্রণ গ্রহণ করুন", "emails.invitation.signature": "{{project}} টীম", "locale.country.unknown": "অজানা", "countries.af": "আফগানিস্তান", diff --git a/app/config/locale/translations/ca.json b/app/config/locale/translations/ca.json index 98940a4a48..ec5112f075 100644 --- a/app/config/locale/translations/ca.json +++ b/app/config/locale/translations/ca.json @@ -8,6 +8,7 @@ "emails.verification.body": "Accedeix a aquest enllaç per tal de verificar la teva adreça electrònica.", "emails.verification.footer": "Si no has sol·licitat la verificació d'aquesta adreça electrònica, pots ignorar aquest missatge.", "emails.verification.thanks": "Gràcies,", + "emails.verification.buttonText": "Confirma l'adreça electrònica", "emails.verification.signature": "Equip {{project}}", "emails.magicSession.subject": "Entrar", "emails.magicSession.hello": "Hola,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Accedeix a aquest enllaç per a reinicialitzar la teva contrasenya de {{project}}.", "emails.recovery.footer": "Si no has sol·licitat reinicialitzar la teva contrasenya, pots ignorar aquest missatge.", "emails.recovery.thanks": "Gràcies,", + "emails.recovery.buttonText": "Restableix la contrasenya", "emails.recovery.signature": "Equip {{project}}", "emails.invitation.subject": "Invitació a l'equip %s a s%", "emails.invitation.hello": "Hola,", "emails.invitation.body": "Aquest correu se t'ha enviat perquè {{owner}} vol convidar-te a formar part de l'equip {{team}} al {{project}}.", "emails.invitation.footer": "Si no és del teu interès, pots ignorar aquest missatge.", "emails.invitation.thanks": "Gràcies,", + "emails.invitation.buttonText": "Accepta la invitació a {{team}}", "emails.invitation.signature": "Equip {{project}}", "locale.country.unknown": "Desconegut", "countries.af": "Afganistan", diff --git a/app/config/locale/translations/da.json b/app/config/locale/translations/da.json index 9cec74dbed..ae93b3c3b5 100644 --- a/app/config/locale/translations/da.json +++ b/app/config/locale/translations/da.json @@ -8,6 +8,7 @@ "emails.verification.body": "Følg dette link, for at verificere din email adresse.", "emails.verification.footer": "Hvis du ikke har bedt om at verificere denne adresse, ignorer venligst denne besked.", "emails.verification.thanks": "Tak,", + "emails.verification.buttonText": "Bekræft e-mailadresse", "emails.verification.signature": "{{project}} team", "emails.magicSession.subject": "Login", "emails.magicSession.hello": "Hej,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Følg dette link for at nulstille koden til {{project}}.", "emails.recovery.footer": "Hvis du ikke har bedt om at nulstille dit password, ignorer venligst denne besked.", "emails.recovery.thanks": "Tak,", + "emails.recovery.buttonText": "Nulstil adgangskode", "emails.recovery.signature": "{{project}} team", "emails.invitation.subject": "Invitation til %s Team på %s", "emails.invitation.hello": "Hej,", "emails.invitation.body": "Denne mail blev sendt til dig, fordi {{owner}} vil invitere dig til at blive medlem af {{team}} teamet på {{project}}.", "emails.invitation.footer": "Hvis du ikke er interesseret, ignorer venligst denne besked.", "emails.invitation.thanks": "Tak,", + "emails.invitation.buttonText": "Accepter invitation til {{team}}", "emails.invitation.signature": "{{project}} team", "locale.country.unknown": "Ukendt", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/de.json b/app/config/locale/translations/de.json index 38b1e46870..a5a2f0ba43 100644 --- a/app/config/locale/translations/de.json +++ b/app/config/locale/translations/de.json @@ -8,6 +8,7 @@ "emails.verification.body": "Folge diesem Link, um deine E-Mail-Adresse zu bestätigen.", "emails.verification.footer": "Solltest du keine Verifizierung dieser E-Mail-Adresse angefordert haben, kannst du diese Nachricht ignorieren.", "emails.verification.thanks": "Danke,", + "emails.verification.buttonText": "E-Mail-Adresse bestätigen", "emails.verification.signature": "{{project}}-Team", "emails.magicSession.subject": "Login", "emails.magicSession.hello": "Hey,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Folge diesem Link, um dein {{project}}-Kennwort zurückzusetzen.", "emails.recovery.footer": "Solltest du keine Kennwort-Zurücksetzung angefordert haben, kannst du diese Nachricht ignorieren.", "emails.recovery.thanks": "Danke,", + "emails.recovery.buttonText": "Passwort zurücksetzen", "emails.recovery.signature": "{{project}}-Team", "emails.invitation.subject": "Einladung zum %s-Team auf %s", "emails.invitation.hello": "Hello,", "emails.invitation.body": "Du erhälst diese E-Mail, weil {{owner}} dich in das Team {{team}} auf {{project}} eingeladen hat.", "emails.invitation.footer": "Wenn du nicht interessiert bist, kannst du diese Nachricht ignorieren.", "emails.invitation.thanks": "Danke,", + "emails.invitation.buttonText": "Einladung zu {{team}} annehmen", "emails.invitation.signature": "{{project}}-Team", "locale.country.unknown": "Unbekannt", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/el.json b/app/config/locale/translations/el.json index 1ef9cd30df..3576ffb865 100644 --- a/app/config/locale/translations/el.json +++ b/app/config/locale/translations/el.json @@ -8,6 +8,7 @@ "emails.verification.body": "Ακολουθήστε αυτό το link για να επαληθεύσετε τη δ/νση του email σας", "emails.verification.footer": "Εάν δεν ζητήσατε επαλήθευση αυτής της δ/νσης email, μπορείτε να αγνοήσετε αυτό το μήνυμα", "emails.verification.thanks": "Ευχαριστούμε,", + "emails.verification.buttonText": "Επιβεβαιώστε διεύθυνση email", "emails.verification.signature": "Η ομάδα του {{project}}", "emails.magicSession.subject": "Είσοδος", "emails.magicSession.hello": "Γεια σου,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Ακολουθήστε αυτό το link για να αλλάξετε τον {{project}} κωδικό σας", "emails.recovery.footer": "Εάν δεν ζητήσατε αλλαγή του κωδικού σας πρόσβασης, μπορείτε να αγνοήσετε αυτό το μήνυμα", "emails.recovery.thanks": "Ευχαριστούμε,", + "emails.recovery.buttonText": "Επαναφορά κωδικού πρόσβασης", "emails.recovery.signature": "Η ομάδα του {{project}}", "emails.invitation.subject": "Πρόσκληση στην %s Ομάδα στον %s", "emails.invitation.hello": "Γεια σου,", "emails.invitation.body": "Αυτό το email στάλθηκε επειδή ο/η {{owner}} θέλει να σας προσκαλέσει να γίνετε μέλος της ομάδας {{team}} του {{project}}.", "emails.invitation.footer": "Εάν δεν ενδιαφέρεστε, μπορείτε να αγνοήσετε αυτό το μήνυμα.", "emails.invitation.thanks": "Ευχαριστούμε,", + "emails.invitation.buttonText": "Αποδεχόμενος την πρόσκληση στην {{team}}", "emails.invitation.signature": "Η ομάδα του {{project}}", "locale.country.unknown": "Άγνωστο", "countries.af": "Αφγανιστάν", diff --git a/app/config/locale/translations/eo.json b/app/config/locale/translations/eo.json index ba80bc602d..8aba49098b 100644 --- a/app/config/locale/translations/eo.json +++ b/app/config/locale/translations/eo.json @@ -7,6 +7,7 @@ "emails.verification.body": "Alklaku ĉi tiun ligon por kontroli vian retpoŝtan adreson.", "emails.verification.footer": "Se vi ne petis ĉi tiun konfirmon de ĉi tiu retpoŝto, vi povas ignori ĉi tiun mesaĝon.", "emails.verification.thanks": "Dankegon.,", + "emails.verification.buttonText": "Konfirmi retadreson", "emails.verification.signature": "Teamo {{project}}", "emails.magicSession.subject": "Login", "emails.magicSession.hello": "Saluton,", @@ -19,12 +20,14 @@ "emails.recovery.body": "Alklaku ĉi tiun ligon por reagordi vian pasvorton. {{project}}", "emails.recovery.footer": "Se vi ne petis reagordi vian pasvorton, vi povas ignori ĉi tiun mesaĝon.", "emails.recovery.thanks": "Dankegon,", + "emails.recovery.buttonText": "Pasvorton restarigi", "emails.recovery.signature": "Teamo {{project}}", "emails.invitation.subject": "Invito al la Teamo %s em %s", "emails.invitation.hello": "Dankegon,", "emails.invitation.body": "Ĉi tiu retpoŝto estis sendita ĉar la {{owner}} volas inviti vin fariĝi membro de la Teamo {{team}} en {{project}}.", "emails.invitation.footer": "Se vi ne interesiĝas, vi povas ignori ĉi tiun mesaĝon.", "emails.invitation.thanks": "Dankegon,", + "emails.invitation.buttonText": "Akcepti inviton al {{team}}", "emails.invitation.signature": "Teamo {{project}}", "locale.country.unknown": "Unknown", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/es.json b/app/config/locale/translations/es.json index ff98fd28c7..e986b15f3c 100644 --- a/app/config/locale/translations/es.json +++ b/app/config/locale/translations/es.json @@ -8,6 +8,7 @@ "emails.verification.body": "Haz clic en este enlace para verificar tu correo:", "emails.verification.footer": "Si no has solicitado verificar este correo, puedes ignorar este mensaje.", "emails.verification.thanks": "Gracias.,", + "emails.verification.buttonText": "Confirmar dirección de correo", "emails.verification.signature": "El equipo de {{project}}.", "emails.magicSession.subject": "Inicio de sesión", "emails.magicSession.hello": "Hola,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Haz clic en este enlace para restablecer la contraseña de {{project}}:", "emails.recovery.footer": "Si no has solicitado restablecer la contraseña, puedes ignorar este mensaje.", "emails.recovery.thanks": "Gracias.,", + "emails.recovery.buttonText": "Restablecer contraseña", "emails.recovery.signature": "El equipo de {{project}}", "emails.invitation.subject": "Invitación al equipo %s en %s", "emails.invitation.hello": "Hola,", "emails.invitation.body": "Este correo ha sido enviado a petición de {{owner}} quién quiere invitarte a formar parte del equipo {{team}} en {{project}}.", "emails.invitation.footer": "Si no estás interesado, puedes ignorar este mensaje.", "emails.invitation.thanks": "Gracias.,", + "emails.invitation.buttonText": "Aceptar invitación a {{team}}", "emails.invitation.signature": "El equipo de {{project}}", "locale.country.unknown": "Desconocido", "countries.af": "Afganistán", diff --git a/app/config/locale/translations/fa.json b/app/config/locale/translations/fa.json index f826a75118..9434b9ff03 100644 --- a/app/config/locale/translations/fa.json +++ b/app/config/locale/translations/fa.json @@ -8,6 +8,7 @@ "emails.verification.body": "برای تأیید ایمیل‌تان پیوند زیر را دنبال کنید.", "emails.verification.footer": "اگر شما درخواست تأیید حساب نداده‌اید، می‌توانید این پیام را نادیده بگیرید.", "emails.verification.thanks": "سپاس فراوان،", + "emails.verification.buttonText": "آدرس ایمیل را تایید کنید", "emails.verification.signature": "تیم {{user}}", "emails.magicSession.subject": "ورود به حساب کاربری", "emails.magicSession.hello": "سلام،", @@ -20,12 +21,14 @@ "emails.recovery.body": "برای بازیابی گذرواژه‌تان پیوند زیر را دنبال کنید.", "emails.recovery.footer": "اگر شما درخواست بازیابی گذرواژه نداده‌اید، می‌توانید این پیام را نادیده بگیرید.", "emails.recovery.thanks": "سپاس فراوان،", + "emails.recovery.buttonText": "بازنشانی رمز عبور", "emails.recovery.signature": "تیم {{user}}", "emails.invitation.subject": "دعوت به تیم %s در %s", "emails.invitation.hello": "سلام،", "emails.invitation.body": "این ایمیل برای شما فرستاده شده‌است زیرا {{owner}} می‌خواهد شما را به تیم {{team}} در پروژه‌ی {{project}} بیفزاید.", "emails.invitation.footer": "اگر علاقه ندارید، می‌توانید این پیام را نادیده بگیرید.", "emails.invitation.thanks": "سپاس فراوان،", + "emails.invitation.buttonText": "دعوت را به {{team}} بپذیرید", "emails.invitation.signature": "تیم {{user}}", "locale.country.unknown": "ناشناخته", "countries.af": "افغانستان", diff --git a/app/config/locale/translations/fr.json b/app/config/locale/translations/fr.json index 1b60cb1910..3af7193764 100644 --- a/app/config/locale/translations/fr.json +++ b/app/config/locale/translations/fr.json @@ -8,6 +8,7 @@ "emails.verification.body": "Suivez ce lien pour vérifier votre adresse e-mail.", "emails.verification.footer": "Si vous n'avez pas demandé à vérifier cette adresse, vous pouvez ignorer ce message.", "emails.verification.thanks": "Merci,", + "emails.verification.buttonText": "Confirmez l'adresse e-mail", "emails.verification.signature": "Équipe {{project}}", "emails.magicSession.subject": "Connexion", "emails.magicSession.hello": "Bonjour,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Suivez ce lien pour réinitialiser votre mot de passe pour {{project}}.", "emails.recovery.footer": "Si vous n'avez pas demandé à réinitialiser votre mot de passe, vous pouvez ignorer ce message.", "emails.recovery.thanks": "Merci,", + "emails.recovery.buttonText": "Réinitialisation du mot de passe", "emails.recovery.signature": "L'équipe {{project}}", "emails.invitation.subject": "Invitation à l'équipe %s de %s", "emails.invitation.hello": "Bonjour,", "emails.invitation.body": "Cet e-mail vous a été envoyé parce que {{owner}} souhaite vous inviter à devenir membre de l'équipe {{team}} pour {{project}}.", "emails.invitation.footer": "Si vous n'êtes pas intéressé, vous pouvez ignorer ce message.", "emails.invitation.thanks": "Merci,", + "emails.invitation.buttonText": "Accepter l'invitation à {{team}}", "emails.invitation.signature": "L'équipe {{project}}", "locale.country.unknown": "Inconnu", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/ga.json b/app/config/locale/translations/ga.json index 3ed68ad8c3..c486e77126 100644 --- a/app/config/locale/translations/ga.json +++ b/app/config/locale/translations/ga.json @@ -8,6 +8,7 @@ "emails.verification.body": "Lean an nasc seo chun do ríomhphost a fhíorú.", "emails.verification.footer": "Mura ndearna tú iarratas an seoladh seo a fhíoru, déan neamhaird den teachtaireacht seo.", "emails.verification.thanks": "Go raibh maith agat,", + "emails.verification.buttonText": "Deimhnigh seoladh ríomhphoist", "emails.verification.signature": "{{project}} foireann", "emails.magicSession.subject": "Logáil isteach", "emails.magicSession.hello": "Haigh,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Lean an nasc seo chun do pasfhocal {{project}} a athshocrú.", "emails.recovery.footer": "Mura ndearna tú iarratas do pasfhocal a athshocrú, déan neamhaird den teachtaireacht seo.", "emails.recovery.thanks": "Go raibh maith agat,", + "emails.recovery.buttonText": "Athshocraigh focal faire", "emails.recovery.signature": "{{project}} foireann", "emails.invitation.subject": "Cuireadh do %s foireann ag %s", "emails.invitation.hello": "Haigh,", "emails.invitation.body": "Seoladh an ríomhphost seo chugat mar ba mhaith le {{owner}} cuireadh a thabhairt duit bheith mar bhall den fhoireann {{team}} ag obair ar {{project}}.", "emails.invitation.footer": "Is cuma leat? Déan neamhaird den teachtaireacht seo.", "emails.invitation.thanks": "Go raibh maith agat,", + "emails.invitation.buttonText": "Glac le cuireadh chuig {{team}}", "emails.invitation.signature": "{{project}} foireann", "locale.country.unknown": "Neamhaithnid", "countries.af": "An Afganastáin", diff --git a/app/config/locale/translations/gu.json b/app/config/locale/translations/gu.json index 54378caa9e..8d5d2fb8d6 100644 --- a/app/config/locale/translations/gu.json +++ b/app/config/locale/translations/gu.json @@ -8,6 +8,7 @@ "emails.verification.body": "તમારું ઇમેઇલ સરનામું ચકાસવા માટે આ લિંકને અનુસરો.", "emails.verification.footer": "જો તમે આ સરનામાંની ચકાસણી કરવાનું ન કહ્યું હોય, તો તમે આ સંદેશને અવગણી શકો છો.", "emails.verification.thanks": "આભાર,", + "emails.verification.buttonText": "ઇમેઇલ સરનામું ખાતરી કરો", "emails.verification.signature": "{{project}} ટીમ", "emails.magicSession.subject": "પ્રવેશ કરો", "emails.magicSession.hello": "નમસ્કાર,", @@ -20,12 +21,14 @@ "emails.recovery.body": "તમારો {{project}} પાસવર્ડ ફરીથી સેટ કરવા માટે આ લિંકને અનુસરો.", "emails.recovery.footer": "જો તમે તમારો પાસવર્ડ ફરીથી સેટ કરવાનું ન કહ્યું હોય, તો તમે આ સંદેશને અવગણી શકો છો.", "emails.recovery.thanks": "આભાર,", + "emails.recovery.buttonText": "પાસવર્ડ રીસેટ કરો", "emails.recovery.signature": "{{project}} ટીમ", "emails.invitation.subject": "%s ટીમને %s પર આમંત્રણ", "emails.invitation.hello": "નમસ્કાર,", "emails.invitation.body": "આ મેઇલ તમને મોકલવામાં આવ્યો હતો કારણ કે {{owner}} તમને {{project}} માં {{team}} ટીમના સભ્ય બનવા માટે આમંત્રિત કરવા માંગતા હતો.", "emails.invitation.footer": "જો તમને રસ નથી, તો તમે આ સંદેશને અવગણી શકો છો.", "emails.invitation.thanks": "આભાર,", + "emails.invitation.buttonText": "{{team}} નું આમંત્રણ સ્વીકારો", "emails.invitation.signature": "{{project}} ટીમ", "locale.country.unknown": "અજાણ", "countries.af": "અફઘાનિસ્તાન", diff --git a/app/config/locale/translations/he.json b/app/config/locale/translations/he.json index b3d4dea2a8..8e5279e5e4 100644 --- a/app/config/locale/translations/he.json +++ b/app/config/locale/translations/he.json @@ -8,6 +8,7 @@ "emails.verification.body": "לחץ על קישור זה כדי לאמת את כתובת הדוא\"ל שלך.", "emails.verification.footer": "אם לא ביקשת לאמת כתובת זו, תוכל להתעלם מהודעה זו.", "emails.verification.thanks": "תודה,", + "emails.verification.buttonText": "אשר כתובת דוא\"ל", "emails.verification.signature": "צוות {{project}}", "emails.magicSession.subject": "כניסה למערכת", "emails.magicSession.hello": "שלום,", @@ -20,12 +21,14 @@ "emails.recovery.body": "עקוב אחר קישור זה כדי לאפס את סיסמתך ב-{{project}}.", "emails.recovery.footer": "אם לא ביקשת לאפס את הסיסמה, תוכל להתעלם מהודעה זו.", "emails.recovery.thanks": "תודה,", + "emails.recovery.buttonText": "סיסמא איפוס", "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.buttonText": "אשר הזמנה ל-{{team}}", "emails.invitation.signature": "צוות {{project}}", "locale.country.unknown": "לא ידוע", "countries.af": "אפגניסטן", From e4311de73564edd352ca73c8696fb7cb6473e723 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 29 Mar 2025 12:52:55 +0530 Subject: [PATCH 003/343] update: languages; --- app/config/locale/translations/hi.json | 3 +++ app/config/locale/translations/hr.json | 3 +++ app/config/locale/translations/hu.json | 3 +++ app/config/locale/translations/id.json | 3 +++ app/config/locale/translations/it.json | 3 +++ app/config/locale/translations/ja.json | 3 +++ app/config/locale/translations/jv.json | 3 +++ app/config/locale/translations/kn.json | 3 +++ app/config/locale/translations/ko.json | 3 +++ app/config/locale/translations/la.json | 3 +++ app/config/locale/translations/lb.json | 3 +++ app/config/locale/translations/lt.json | 3 +++ app/config/locale/translations/lv.json | 3 +++ app/config/locale/translations/ml.json | 3 +++ app/config/locale/translations/mr.json | 3 +++ app/config/locale/translations/ms.json | 3 +++ 16 files changed, 48 insertions(+) diff --git a/app/config/locale/translations/hi.json b/app/config/locale/translations/hi.json index 1c4d531d60..ef71e287cd 100644 --- a/app/config/locale/translations/hi.json +++ b/app/config/locale/translations/hi.json @@ -8,6 +8,7 @@ "emails.verification.body": "इस लिंक के माध्यम से अपने ईमेल को सत्यापित कीजिये।", "emails.verification.footer": "यदि आप इस पते को सत्यापित नहीं करना चाहते हैं, तो आप इस संदेश को नज़रअंदाज़ कर सकते हैं।", "emails.verification.thanks": "धन्यवाद,", + "emails.verification.buttonText": "ईमेल पता सत्यापित करें", "emails.verification.signature": "{{project}} टीम", "emails.magicSession.subject": "लॉग इन", "emails.magicSession.hello": "नमस्ते,", @@ -20,12 +21,14 @@ "emails.recovery.body": "इस लिंक के माध्यम से अपना {{project}} पासवर्ड रीसेट करें।", "emails.recovery.footer": "यदि आप अपना पासवर्ड रीसेट नहीं करना चाहते हैं, तो आप इस संदेश को नज़रअंदाज़ कर सकते हैं।", "emails.recovery.thanks": "धन्यवाद,", + "emails.recovery.buttonText": "पासवर्ड रीसेट करें", "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.buttonText": "{{team}} का निमंत्रण स्वीकार करें", "emails.invitation.signature": "{{project}} टीम", "locale.country.unknown": "अज्ञात", "countries.af": "अफ़ग़ानिस्तान", diff --git a/app/config/locale/translations/hr.json b/app/config/locale/translations/hr.json index e5bf4719a9..8331d67422 100644 --- a/app/config/locale/translations/hr.json +++ b/app/config/locale/translations/hr.json @@ -8,6 +8,7 @@ "emails.verification.body": "Slijedite ovu poveznicu da biste potvrdili svoju adresu e-pošte.", "emails.verification.footer": "Ukoliko niste zatražili potvrdu ove adrese, možete zanemariti ovu poruku.", "emails.verification.thanks": "Hvala,", + "emails.verification.buttonText": "Potvrdi adresu e-pošte", "emails.verification.signature": "{{project}} tim", "emails.magicSession.subject": "Prijavite se", "emails.magicSession.hello": "Pozdrav,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Slijedite ovu poveznicu za ponovno postavljanje {{project}} lozinke.", "emails.recovery.footer": "Ako niste zatražili ponovno postavljanje Vaše lozinke, možete zanemariti ovu poruku.", "emails.recovery.thanks": "Hvala,", + "emails.recovery.buttonText": "Resetiraj lozinku", "emails.recovery.signature": "{{project}} tim", "emails.invitation.subject": "Pozivnica za %s tim na %s", "emails.invitation.hello": "Pozdrav,", "emails.invitation.body": "Ova poruka Vam je poslana jer Vas je {{owner}} htio pozvati da postanete član {{team}} tima na {{project}}.", "emails.invitation.footer": "Ukoliko niste zainteresirani, možete zanemariti ovu poruku.", "emails.invitation.thanks": "Hvala,", + "emails.invitation.buttonText": "Prihvati pozivnicu za {{team}}", "emails.invitation.signature": "{{project}} tim", "locale.country.unknown": "Nepoznato", "countries.af": "Afganistan", diff --git a/app/config/locale/translations/hu.json b/app/config/locale/translations/hu.json index 589cb61859..c21701a509 100644 --- a/app/config/locale/translations/hu.json +++ b/app/config/locale/translations/hu.json @@ -8,6 +8,7 @@ "emails.verification.body": "Kattints a linkre, hogy megerősítsd az email címedet.", "emails.verification.footer": "Ha nem te kérted a címed megerősítését, akkor nyugodtan hagyd figyelmen kívül ezt az üzenetet.", "emails.verification.thanks": "Köszönettel,", + "emails.verification.buttonText": "E-mail-cím megerősítése", "emails.verification.signature": "a {{project}} csapat", "emails.magicSession.subject": "Bejelentkezés", "emails.magicSession.hello": "Szia,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Kattints a linkre a {{project}} jelszavad visszaállításához.", "emails.recovery.footer": "Ha nem te kezdeményezted a jelszavad visszaállítását, akkor nyugodtan hagyd figyelmen kívül ezt az üzenetet.", "emails.recovery.thanks": "Köszönettel,", + "emails.recovery.buttonText": "Jelszó visszaállítása", "emails.recovery.signature": "a {{project}} csapat", "emails.invitation.subject": "Meghívó a(z) %s csapatba, a(z) %s projektbe", "emails.invitation.hello": "Szia,", "emails.invitation.body": "Ezt a levelet azért kaptad, mert {{owner}} meghívott, hogy légy a {{team}} csapat tagja a {{project}} projektben.", "emails.invitation.footer": "Ha nem érdekel a lehetőség, nyugodtan hagyd figyelmen kívül ezt az üzenetet.", "emails.invitation.thanks": "Köszönettel,", + "emails.invitation.buttonText": "Elfogadni meghívást a {{team}-re", "emails.invitation.signature": "a {{project}} csapat", "locale.country.unknown": "Ismeretlen", "countries.af": "Afganisztán", diff --git a/app/config/locale/translations/id.json b/app/config/locale/translations/id.json index c28b15f15d..836941f79a 100644 --- a/app/config/locale/translations/id.json +++ b/app/config/locale/translations/id.json @@ -8,6 +8,7 @@ "emails.verification.body": "Ikuti tautan ini untuk memverifikasi alamat email Anda.", "emails.verification.footer": "Jika Anda tidak meminta untuk memverifikasi alamat email ini, Anda dapat mengabaikan pesan ini.", "emails.verification.thanks": "Terima kasih,", + "emails.verification.buttonText": "Konfirmasi alamat email", "emails.verification.signature": "Tim {{project}}", "emails.magicSession.subject": "Masuk", "emails.magicSession.hello": "Hai,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Ikuti tautan ini untuk menyetel ulang kata sandi {{project}} Anda.", "emails.recovery.footer": "Jika Anda tidak meminta untuk menyetel ulang kata sandi, Anda dapat mengabaikan pesan ini.", "emails.recovery.thanks": "Terima kasih,", + "emails.recovery.buttonText": "Atur ulang kata sandi", "emails.recovery.signature": "Tim {{project}}", "emails.invitation.subject": "Undangan ke Tim %s di %s", "emails.invitation.hello": "Halo,", "emails.invitation.body": "Email ini dikirimkan kepada Anda karena {{owner}} ingin mengundang Anda untuk menjadi anggota tim {{team}} di {{project}}.", "emails.invitation.footer": "Jika Anda tidak tertarik, Anda dapat mengabaikan pesan ini.", "emails.invitation.thanks": "Terima kasih,", + "emails.invitation.buttonText": "Terima undangan ke {{team}}", "emails.invitation.signature": "Tim {{project}}", "locale.country.unknown": "Tidak diketahui", "countries.af": "Afganistan", diff --git a/app/config/locale/translations/it.json b/app/config/locale/translations/it.json index 8d45de9903..65a9961529 100644 --- a/app/config/locale/translations/it.json +++ b/app/config/locale/translations/it.json @@ -8,6 +8,7 @@ "emails.verification.body": "Clicca questo link per verificare il tuo indirizzo email.", "emails.verification.footer": "Se non hai richiesto la verifica dell’indirizzo email, puoi ignorare questo messaggio.", "emails.verification.thanks": "Grazie,", + "emails.verification.buttonText": "Confermare l'indirizzo email", "emails.verification.signature": "Il team {{project}}", "emails.magicSession.subject": "Login", "emails.magicSession.hello": "Ciao,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Clicca questo link per reimpostare la tua password di {{project}}.", "emails.recovery.footer": "Se non hai richiesto la reimpostazione della password, puoi ignorare questo messaggio.", "emails.recovery.thanks": "Grazie,", + "emails.recovery.buttonText": "Reimposta password", "emails.recovery.signature": "Il team {{project}}", "emails.invitation.subject": "Invito al Team %s per %s", "emails.invitation.hello": "Ciao,", "emails.invitation.body": "Hai ricevuto questa email perché {{owner}} ti ha invitato a diventare un membro del team {{team}} di {{project}}.", "emails.invitation.footer": "Ignora questo messaggio se non sei interessatə.", "emails.invitation.thanks": "Grazie,", + "emails.invitation.buttonText": "Accetta invito a {{team}", "emails.invitation.signature": "Il team {{project}}", "locale.country.unknown": "Sconosciuto", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/ja.json b/app/config/locale/translations/ja.json index 76d9a0cb1f..f3ad8fe1ed 100644 --- a/app/config/locale/translations/ja.json +++ b/app/config/locale/translations/ja.json @@ -8,6 +8,7 @@ "emails.verification.body": "メールアドレスを有効化するためには下記リンクをクリックして下さい。", "emails.verification.footer": "このメールに心当たりが無い場合は破棄をお願いいたします。", "emails.verification.thanks": "ご利用いただきありがとうございます。、", + "emails.verification.buttonText": "メールアドレスを確認する", "emails.verification.signature": "{{project}}チーム", "emails.magicSession.subject": "ログイン", "emails.magicSession.hello": "こんにちは、", @@ -20,12 +21,14 @@ "emails.recovery.body": "パスワードをリセットするためには下記リンクをクリックしてください。", "emails.recovery.footer": "このメールに心当たりが無い場合は破棄をお願いいたします。", "emails.recovery.thanks": "ご利用いただきありがとうございます。、", + "emails.recovery.buttonText": "パスワードをリセット", "emails.recovery.signature": "{{project}}チーム", "emails.invitation.subject": "%sチームへの招待が%sから来ました。", "emails.invitation.hello": "こんにちは、", "emails.invitation.body": "{{owner}}さんが{{project}}の{{team}}チームにあなたを招待しています。", "emails.invitation.footer": "このメールに心当たりが無い場合は破棄をお願いいたします。", "emails.invitation.thanks": "ご利用いただきありがとうございます。、", + "emails.invitation.buttonText": "{{team}}への招待を承諾する", "emails.invitation.signature": "{{project}}チーム", "locale.country.unknown": "不明", "countries.af": "アフガニスタン", diff --git a/app/config/locale/translations/jv.json b/app/config/locale/translations/jv.json index 889e968b4d..71d4f4b24a 100644 --- a/app/config/locale/translations/jv.json +++ b/app/config/locale/translations/jv.json @@ -8,6 +8,7 @@ "emails.verification.body": "Klik link iki kanggo verifikasi alamat email sampeyan.", "emails.verification.footer": "Yen sampeyan ora njaluk verifikasi alamat iki, sampeyan iso nglirwakake pesen iki.", "emails.verification.thanks": "Matur nuwun,", + "emails.verification.buttonText": "Konfirmasi alamat email", "emails.verification.signature": "Tim {{project}}", "emails.magicSession.subject": "Masuk", "emails.magicSession.hello": "Hai,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Klik link iki kanggo setel ulang sandi {{project}}.", "emails.recovery.footer": "Yen sampeyan ora njaluk setel ulang sandi, sampeyan iso nglirwakake pesen iki.", "emails.recovery.thanks": "Matur nuwun,", + "emails.recovery.buttonText": "Reset sandhi", "emails.recovery.signature": "Tim {{project}}", "emails.invitation.subject": "Undangan ke Tim %s di %s", "emails.invitation.hello": "Halo,", "emails.invitation.body": "Email iki dikirim menyang sampeyan amarga {{owner}} pengin ngajak sampeyan dadi anggota tim {{team}} di {{project}}.", "emails.invitation.footer": "Yen sampeyan ora tertarik, sampeyan iso nglirwakake pesen iki.", "emails.invitation.thanks": "Matur nuwun,", + "emails.invitation.buttonText": "Tampa undhangan menyang {{team}}", "emails.invitation.signature": "Tim {{project}}", "locale.country.unknown": "Ora dingerteni", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/kn.json b/app/config/locale/translations/kn.json index ba57c21155..ed35a7947f 100644 --- a/app/config/locale/translations/kn.json +++ b/app/config/locale/translations/kn.json @@ -8,6 +8,7 @@ "emails.verification.body": "ನಿಮ್ಮ ಇಮೇಲ್ ವಿಳಾಸ ಪರಿಶೀಲನೆಗೆ ಈ ಲಿಂಕನ್ನು ಅನುಸರಿಸಿ", "emails.verification.footer": "ನೀವು ಇಮೇಲ್ ವಿಳಾಸ ಪರಿಶೀಲನೆಗೆ ಕೇಳದಿದ್ದರೆ, ಈ ಸಂದೇಶವನ್ನು ನಿರ್ಲಕ್ಷಿಸಿ", "emails.verification.thanks": "ಧನ್ಯವಾದಗಳು,", + "emails.verification.buttonText": "ಇಮೇಲ್ ವಿಳಾಸವನ್ನು ದೃಢೀಕರಿಸಿ", "emails.verification.signature": "{{project}} ತಂಡ", "emails.magicSession.subject": "ಲಾಗಿನ್", "emails.magicSession.hello": "ನಮಸ್ಕಾರ,", @@ -20,12 +21,14 @@ "emails.recovery.body": "ನಿಮ್ಮ {{project}} ಗುಪ್ತಪದವನ್ನು ಮರುಹೊಂದಿಸಲು ಈ ಲಿಂಕನ್ನು ಅನುಸರಿಸಿ", "emails.recovery.footer": "ನೀವು ಗುಪ್ತಪದವನ್ನು ಮರುಹೊಂದಿಸಲು ಕೇಳದಿದ್ದರೆ, ಈ ಸಂದೇಶವನ್ನು ನಿರ್ಲಕ್ಷಿಸಿ", "emails.recovery.thanks": "ಧನ್ಯವಾದಗಳು,", + "emails.recovery.buttonText": "ಗುಪ್ತಪದವನ್ನು ಮರುಸೆಟ್ ಮಾಡಿ", "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.buttonText": "{{team}} ಗೆ ಆಹ್ವಾನವನ್ನು ಸ್ವೀಕರಿಸಿ", "emails.invitation.signature": "{{project}} ತಂಡ", "locale.country.unknown": "Unknown", "countries.af": "ಅಫ್ಘಾನಿಸ್ತಾನ", diff --git a/app/config/locale/translations/ko.json b/app/config/locale/translations/ko.json index c33c961130..0bc425aeae 100644 --- a/app/config/locale/translations/ko.json +++ b/app/config/locale/translations/ko.json @@ -8,6 +8,7 @@ "emails.verification.body": "이메일 인증을 위해 링크를 클릭하여주세요.", "emails.verification.footer": "이메일 인증을 부탁하지 않으셨다면 이 메시지를 무시하여주세요.", "emails.verification.thanks": "감사합니다、", + "emails.verification.buttonText": "이메일 주소를 확인합니다", "emails.verification.signature": "{{project}} 팀", "emails.magicSession.subject": "로그인", "emails.magicSession.hello": "안녕하세요、", @@ -20,12 +21,14 @@ "emails.recovery.body": "{{project}}의 비밀번호 재설정을 위해 링크를 클릭하여주세요.", "emails.recovery.footer": "비밀번호 재설정 신청을 하지 않으셨다면 이 메세지를 무시하여주세요.", "emails.recovery.thanks": "감사합니다、", + "emails.recovery.buttonText": "비밀번호 재설정", "emails.recovery.signature": "{{project}} 팀", "emails.invitation.subject": "초대장 %s 팀 - %s", "emails.invitation.hello": "안녕하세요、", "emails.invitation.body": "{{owner}}님이 귀하를 {{project}}의 {{team}} 팀으로 초대합니다.", "emails.invitation.footer": "팀에 합류할 의사가 없으시면 이 메세지를 무시하여주세요.", "emails.invitation.thanks": "감사합니다、", + "emails.invitation.buttonText": "{{team}} 초대를 수락하기", "emails.invitation.signature": "{{project}} 팀", "locale.country.unknown": "알려지지 않은", "countries.af": "아프가니스탄", diff --git a/app/config/locale/translations/la.json b/app/config/locale/translations/la.json index bebef26854..fe3e7930e2 100644 --- a/app/config/locale/translations/la.json +++ b/app/config/locale/translations/la.json @@ -8,6 +8,7 @@ "emails.verification.body": "Sequere hanc nexum ut quin inscriptionem tuum.", "emails.verification.footer": "Si verificationem huius inscriptionis non postulasti, nuntium hunc ignorare potes.", "emails.verification.thanks": "Gratias,", + "emails.verification.buttonText": "Confirma inscriptionem electronicam", "emails.verification.signature": "{{project}} Team", "emails.magicSession.subject": "Log in", "emails.magicSession.hello": "Salve ibi,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Sequere hanc conjunctionem ut recipias project password {{project}}", "emails.recovery.footer": "Si tesseram tuam recuperare non petis, nuntium hunc ignorare potes", "emails.recovery.thanks": "Gratias,", + "emails.recovery.buttonText": "Reset password", "emails.recovery.signature": "{{project}} team", "emails.invitation.subject": "Invitatio pro %s in quadrigis %s", "emails.invitation.hello": "Salve ibi,", "emails.invitation.body": "Haec inscriptio ad te missa est quia dominus incepto {{owner}} te invitare vult ut membrum {{team}} quadrigis fias ad {{project}}", "emails.invitation.footer": "Si non quaero, potes hunc nuntium ignorare", "emails.invitation.thanks": "Gratias,", + "emails.invitation.buttonText": "Accipe invitare ad {{team}}", "emails.invitation.signature": "{{project}} team", "locale.country.unknown": "Ignotum", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/lb.json b/app/config/locale/translations/lb.json index 91b52e4a18..8fe4b346e7 100644 --- a/app/config/locale/translations/lb.json +++ b/app/config/locale/translations/lb.json @@ -8,6 +8,7 @@ "emails.verification.body": "Follegt dëse Link fir Är E -Mail Adress z'iwwerpréiwen.", "emails.verification.footer": "Wann Dir net gefrot hutt dës Adress z'iwwerpréiwen, kënnt Dir dëse Message ignoréieren.", "emails.verification.thanks": "Merci,", + "emails.verification.buttonText": "E-Mail-Adress bestätegen", "emails.verification.signature": "{{project}} équipe", "emails.magicSession.subject": "Login", "emails.magicSession.hello": "Hey,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Follegt dëse Link fir Äert {{project}} Passwuert zréckzesetzen.", "emails.recovery.footer": "Wann Dir net gefrot hutt Äert Passwuert zréckzesetzen, kënnt Dir dëse Message ignoréieren.", "emails.recovery.thanks": "Merci,", + "emails.recovery.buttonText": "Passwuert zrécksetzen", "emails.recovery.signature": "{{project}} équipe", "emails.invitation.subject": "Invitatioun un %s équipe bei %s", "emails.invitation.hello": "Hallo,", "emails.invitation.body": "Dës E -Mail gouf un Iech geschéckt well {{owner}} Iech invitéiere wëllt fir Member vum {{team}} Team bei {{project}} ze ginn.", "emails.invitation.footer": "Wann Dir net interesséiert sidd, kënnt Dir dëse Message ignoréieren.", "emails.invitation.thanks": "Merci,", + "emails.invitation.buttonText": "Invitatioun bei {{team}} akzeptéieren", "emails.invitation.signature": "{{project}} équipe", "locale.country.unknown": "Onbekannt", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/lt.json b/app/config/locale/translations/lt.json index 94c874ce82..2439428b02 100644 --- a/app/config/locale/translations/lt.json +++ b/app/config/locale/translations/lt.json @@ -8,6 +8,7 @@ "emails.verification.body": "Spauskite šią nuorodą, kad patvirtintumėte savo el. paštą.", "emails.verification.footer": "Jei neprašėte patvirtinti šio el. pašto, galite ignoruoti šį pranešimą.", "emails.verification.thanks": "Ačiū,", + "emails.verification.buttonText": "Patvirtinti el. pašto adresą", "emails.verification.signature": "{{project}} komanda", "emails.magicSession.subject": "Prisijungti", "emails.magicSession.hello": "Labas,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Spauskite šią nuorodą, kad atkurtumėte projekto {{project}} slaptažodį.", "emails.recovery.footer": "Jei neprašėte atkurti savo slaptažodzio, galite ignoruoti šį pranešimą.", "emails.recovery.thanks": "Ačiū,", + "emails.recovery.buttonText": "Atstatyti slaptažodį", "emails.recovery.signature": "{{project}} komanda", "emails.invitation.subject": "Pakvietimas į %s komandą %s projekte", "emails.invitation.hello": "Labas,", "emails.invitation.body": "Šis el. laiškas buvo atsiųstas jums, nes {{owner}} norėjo jus pakviesti tapti projekto {{project}} dalimi {{team}} komandoje.", "emails.invitation.footer": "Jei jūsų tai nedomina, galite ignoruoti šį pranešimą.", "emails.invitation.thanks": "Ačiū,", + "emails.invitation.buttonText": "Priimti kvietimą į {{team}}", "emails.invitation.signature": "{{project}} komanda", "locale.country.unknown": "Nežinoma", "countries.af": "Afganistanas", diff --git a/app/config/locale/translations/lv.json b/app/config/locale/translations/lv.json index b4a396367c..59edfce7a6 100644 --- a/app/config/locale/translations/lv.json +++ b/app/config/locale/translations/lv.json @@ -8,6 +8,7 @@ "emails.verification.body": "Sekojiet saitei, lai apstiprinātu savu e-pasta adresi.", "emails.verification.footer": "Ja Jūs nepieprasījāt šīs adreses apstiprinājumu, lūdzu, ignorējiet šo ziņu.", "emails.verification.thanks": "Paldies,", + "emails.verification.buttonText": "Apstiprināt e-pasta adresi", "emails.verification.signature": "{{project}} komanda", "emails.magicSession.subject": "Ieiet", "emails.magicSession.hello": "Sveicināti,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Sekojiet saitei, lai atjauninātu {{project}} paroli.", "emails.recovery.footer": "Ja Jūs nepieprasījāt paroles atjaunināšanu, lūdzu, ignorējiet šo ziņu.", "emails.recovery.thanks": "Paldies,", + "emails.recovery.buttonText": "Atiestatīt paroli", "emails.recovery.signature": "{{project}} komanda", "emails.invitation.subject": "Ielūgums piebiedroties %s komandai %s projektā.", "emails.invitation.hello": "Labdien,", "emails.invitation.body": "Šis e-pasts tika nosūtīts Jums, jo {{owner}} vēlējās Jūs ielūgt kļūt par {{team}} komandas biedru {{project}} projektā.", "emails.invitation.footer": "Ja Jūs neesat ieinteresēts, lūdzu, ignorējiet šo ziņu.", "emails.invitation.thanks": "Paldies,", + "emails.invitation.buttonText": "Pieņemt ielūgumu uz {{team}}", "emails.invitation.signature": "{{project}} komanda", "locale.country.unknown": "Nav zināms", "countries.af": "Afganistāna", diff --git a/app/config/locale/translations/ml.json b/app/config/locale/translations/ml.json index 1b57d87865..bd13f92fa8 100644 --- a/app/config/locale/translations/ml.json +++ b/app/config/locale/translations/ml.json @@ -8,6 +8,7 @@ "emails.verification.body": "നിങ്ങളുടെ ഇമെയിൽ വിലാസം സ്ഥിരീകരിക്കുന്നതിനായി ഈ ലിങ്ക് പിന്തുടരുക.", "emails.verification.footer": "ഈ വിലാസം സ്ഥിരീകരിക്കാന്‍ നിങ്ങൾ ആവശ്യപ്പെട്ടില്ലെങ്കിൽ, നിങ്ങൾക്ക് ഈ സന്ദേശം അവഗണിക്കാവുന്നതാണ്.", "emails.verification.thanks": "നന്ദി,", + "emails.verification.buttonText": "ഇമെയിൽ വിലാസം സ്ഥിരീകരിക്കുക", "emails.verification.signature": "{{project}} ടീം", "emails.magicSession.subject": "ലോഗിൻ", "emails.magicSession.hello": "നമസ്കാരം,", @@ -20,12 +21,14 @@ "emails.recovery.body": "നിങ്ങളുടെ {{Project}} രഹസ്യവാക്ക് പുനക്രമീകരിക്കുന്നതിന് ഈ ലിങ്ക് പിന്തുടരുക.", "emails.recovery.footer": "നിങ്ങളുടെ രഹസ്യവാക്ക് പുനക്രമീകരിക്കാന്‍ നിങ്ങൾ ആവശ്യപ്പെട്ടില്ലെങ്കിൽ, ഈ സന്ദേശം അവഗണിക്കാവുന്നതാണ്.", "emails.recovery.thanks": "നന്ദി,", + "emails.recovery.buttonText": "പാസ്‌വേഡ് റീസെറ്റ് ചെയ്യുക", "emails.recovery.signature": "{{project}} ടീം", "emails.invitation.subject": "%s -ലെ %s ടീമിലേക്കുള്ള ക്ഷണം", "emails.invitation.hello": "നമസ്കാരം,", "emails.invitation.body": "നിങ്ങളെ {{project}} -ലെ {{team}} ടീമിലെ അംഗമാകുവാന്‍ ക്ഷണിക്കാൻ {{owner}} ആഗ്രഹിക്കുന്നതിനാലാണ് ഈ മെയിൽ നിങ്ങൾക്ക് അയക്കുന്നത്.", "emails.invitation.footer": "നിങ്ങൾക്ക് താൽപ്പര്യമില്ലെങ്കിൽ, ഈ സന്ദേശം അവഗണിക്കാവുന്നതാണ്.", "emails.invitation.thanks": "നന്ദി,", + "emails.invitation.buttonText": "{{team}} ലേക്കുള്ള ക്ഷണം സ്വീകരിക്കുക", "emails.invitation.signature": "{{project}} ടീം", "locale.country.unknown": "Unknown", "countries.af": "അഫ്ഗാനിസ്ഥാൻ", diff --git a/app/config/locale/translations/mr.json b/app/config/locale/translations/mr.json index 6550d1c1ba..881afdfe71 100644 --- a/app/config/locale/translations/mr.json +++ b/app/config/locale/translations/mr.json @@ -8,6 +8,7 @@ "emails.verification.body": "आपला ईमेल पत्ता सत्यापित करण्यासाठी या दुव्याचे अनुसरण करा.", "emails.verification.footer": "आपण या पत्त्याची पडताळणी करण्यास सांगितले नसल्यास, आपण या संदेशाकडे दुर्लक्ष करू शकता.", "emails.verification.thanks": "धन्यवाद,", + "emails.verification.buttonText": "ईमेल पत्ता सत्यापित करा", "emails.verification.signature": "{{project}} संघ", "emails.magicSession.subject": "लॉगिन करा", "emails.magicSession.hello": "नमस्कार ,", @@ -20,12 +21,14 @@ "emails.recovery.body": "आपला {{project}}चे पासवर्ड रीसेट करण्यासाठी या लिंकचे अनुसरण करा", "emails.recovery.footer": "आपण आपला पासवर्ड रीसेट करण्यास सांगितले नसल्यास, आपण या संदेशाकडे दुर्लक्ष करू शकता.", "emails.recovery.thanks": "धन्यवाद,", + "emails.recovery.buttonText": "पासवर्ड रीसेट करा", "emails.recovery.signature": "{{project}} संघ", "emails.invitation.subject": "%s संघ %s येथे सामील होण्यासाठी आमंत्रण", "emails.invitation.hello": "नमस्कार,", "emails.invitation.body": "हा मेल तुम्हाला पाठवला होता कारण {{owner}} तुम्हाला {{project}} येथे {{team}} टीमचे सदस्य होण्यासाठी आमंत्रित करू इच्छित होते.", "emails.invitation.footer": "आपल्याला स्वारस्य नसल्यास, आपण या संदेशाकडे दुर्लक्ष करू शकता.", "emails.invitation.thanks": "धन्यवाद,", + "emails.invitation.buttonText": "{{team}} साठी आमंत्रण स्वीकारा", "emails.invitation.signature": "{{project}} संघ", "locale.country.unknown": "अज्ञात", "countries.af": "अफगानिस्तान", diff --git a/app/config/locale/translations/ms.json b/app/config/locale/translations/ms.json index a02c36b075..448307550e 100644 --- a/app/config/locale/translations/ms.json +++ b/app/config/locale/translations/ms.json @@ -8,6 +8,7 @@ "emails.verification.body": "Tekan pautan ini untuk mengesahkan alamat email anda.", "emails.verification.footer": "Sekiranya anda tidak membuat permintaan untuk mengesahkan email ini, sila abaikan mesej ini.", "emails.verification.thanks": "Terima kasih,", + "emails.verification.buttonText": "Sahkan alamat email", "emails.verification.signature": "{{project}} team", "emails.magicSession.subject": "Log masuk", "emails.magicSession.hello": "Hey,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Tekan pautan ini untuk menetapkan semula kata laluan {{project}}.", "emails.recovery.footer": "Sekiranya anda tidak membuat permintaan menetap semula kata laluan, sila abaikan mesej ini.", "emails.recovery.thanks": "Terima kasih,", + "emails.recovery.buttonText": "Tetapkan semula kata laluan", "emails.recovery.signature": "{{project}} team", "emails.invitation.subject": "Jemputan ke pasukan %s di %s", "emails.invitation.hello": "Hello,", "emails.invitation.body": "Anda menerima mel ini kerana {{owner}} ingin menjemput anda untuk menjadi ahli pasukan {{team}} di {{project}}.", "emails.invitation.footer": "Sekiranya anda tidak berminat, sila abaikan mesej ini.", "emails.invitation.thanks": "Terima kasih,", + "emails.invitation.buttonText": "Terima jemputan ke {{team}}", "emails.invitation.signature": "{{project}} team", "locale.country.unknown": "Tidak Diketahui", "countries.af": "Afghanistan", From 734fa7dc77a73e0ed82d5535471b1804211624cd Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 29 Mar 2025 14:31:01 +0530 Subject: [PATCH 004/343] update: languages; --- app/config/locale/translations/nb.json | 3 +++ app/config/locale/translations/ne.json | 3 +++ app/config/locale/translations/nl.json | 3 +++ app/config/locale/translations/nn.json | 3 +++ app/config/locale/translations/or.json | 3 +++ app/config/locale/translations/pl.json | 3 +++ app/config/locale/translations/pt-br.json | 3 +++ app/config/locale/translations/pt-pt.json | 3 +++ app/config/locale/translations/ro.json | 3 +++ app/config/locale/translations/ru.json | 3 +++ app/config/locale/translations/sa.json | 3 +++ app/config/locale/translations/sd.json | 3 +++ app/config/locale/translations/si.json | 3 +++ app/config/locale/translations/sk.json | 3 +++ app/config/locale/translations/sn.json | 3 +++ app/config/locale/translations/sv.json | 3 +++ app/config/locale/translations/ta.json | 3 +++ app/config/locale/translations/te.json | 3 +++ app/config/locale/translations/th.json | 3 +++ app/config/locale/translations/tl.json | 3 +++ app/config/locale/translations/tr.json | 3 +++ app/config/locale/translations/uk.json | 3 +++ app/config/locale/translations/ur.json | 3 +++ app/config/locale/translations/vi.json | 3 +++ app/config/locale/translations/zh-cn.json | 3 +++ app/config/locale/translations/zh-tw.json | 3 +++ 26 files changed, 78 insertions(+) diff --git a/app/config/locale/translations/nb.json b/app/config/locale/translations/nb.json index daf18abc1c..cc95bacf9e 100644 --- a/app/config/locale/translations/nb.json +++ b/app/config/locale/translations/nb.json @@ -8,6 +8,7 @@ "emails.verification.body": "Følg denne lenken for å bekrefte din e-postadresse.", "emails.verification.footer": "Dersom du ikke ba om å bekrefte e-postadressen, kan du se bort fra denne meldingen.", "emails.verification.thanks": "Takk,", + "emails.verification.buttonText": "Bekreft e-postadresse", "emails.verification.signature": "{{project}} team", "emails.magicSession.subject": "Pålogging", "emails.magicSession.hello": "Hei,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Følg denne lenken for å nullstille ditt {{project}} passord.", "emails.recovery.footer": "Dersom du ikke ba om å nullstille passordet ditt, kan du se bort fra denne meldingen.", "emails.recovery.thanks": "Takk,", + "emails.recovery.buttonText": "Tilbakestill passord", "emails.recovery.signature": "{{project}} team", "emails.invitation.subject": "Invitasjon til %s Team ved %s", "emails.invitation.hello": "Hei,", "emails.invitation.body": "Denne meldingen ble sendt til deg fordi {{owner}} ønsket å invitere deg til å bli medlem av {{team}} team ved {{project}}.", "emails.invitation.footer": "Dersom du ikke er interessert, kan du se bort fra denne meldingen.", "emails.invitation.thanks": "Takk,", + "emails.invitation.buttonText": "Godta invitasjon til {{team}}", "emails.invitation.signature": "{{project}} team", "locale.country.unknown": "Ukjent", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/ne.json b/app/config/locale/translations/ne.json index 4f05a9b5ba..f1ba841fed 100644 --- a/app/config/locale/translations/ne.json +++ b/app/config/locale/translations/ne.json @@ -8,6 +8,7 @@ "emails.verification.body": "इमेल ठेगाना प्रमाणित गर्नको लागी यो लिंकमा जानुहोस।", "emails.verification.footer": "यदि तपाइँले आफ्नो खाता प्रमाणित गर्न सोध्नु भएको छैन भने तपाइँले यो सन्देश लाई बेवास्ता गर्न सक्नुहुन्छ।", "emails.verification.thanks": "धन्यवाद,", + "emails.verification.buttonText": "इमेल ठेगाना पुष्टि गर्नुहोस्", "emails.verification.signature": "{{project}} समूह", "emails.magicSession.subject": "लगइन", "emails.magicSession.hello": "नमस्ते,", @@ -20,12 +21,14 @@ "emails.recovery.body": "{{project}}को पासवर्ड रिसेट गर्नको लागी यो लिंकमा जानुहोस।", "emails.recovery.footer": "यदि तपाइँले आफ्नो पासवर्ड रिसेट गर्न सोध्नु भएको छैन भने तपाइँले यो सन्देश लाई बेवास्ता गर्न सक्नुहुन्छ।", "emails.recovery.thanks": "धन्यवाद,", + "emails.recovery.buttonText": "रिसेट पासवर्ड", "emails.recovery.signature": "{{project}} समूह", "emails.invitation.subject": "%s समूहको लागि %s मा निमन्त्रणा", "emails.invitation.hello": "नमस्ते,", "emails.invitation.body": "{{owner}}ले तपाइँलाई {{project}}मा {{team}}को सदस्य बन्न आमन्त्रित गर्न चाहनु भएको छ। त्येसैले तपाइँलाई यो सन्देश पठाइएको हो।", "emails.invitation.footer": "यदि तपाइँ इच्छुक हुनुहुन्न भने, तपाइँले यो सन्देशलाई बेवास्ता गर्न सक्नुहुन्छ।", "emails.invitation.thanks": "धन्यवाद,", + "emails.invitation.buttonText": "{{team}} मा निमन्त्रणा स्वीकार गर्नुहोस्", "emails.invitation.signature": "{{project}} समूह", "locale.country.unknown": "अज्ञात", "countries.af": "अफगानिस्तान", diff --git a/app/config/locale/translations/nl.json b/app/config/locale/translations/nl.json index cae82a9a37..4f71f67199 100644 --- a/app/config/locale/translations/nl.json +++ b/app/config/locale/translations/nl.json @@ -8,6 +8,7 @@ "emails.verification.body": "Volg deze link om uw e-mail te verifieren", "emails.verification.footer": "Als u geen aanvraag voor verificatie heeft gemaakt, kan u deze mail negeren", "emails.verification.thanks": "Bedankt,", + "emails.verification.buttonText": "Bevestig e-mailadres", "emails.verification.signature": "{{project}} team", "emails.magicSession.subject": "Login", "emails.magicSession.hello": "Hoi,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Volg deze link om het wachtwoord van uw project {{project}} te wijzigen", "emails.recovery.footer": "Als u geen aanvraag heeft gemaakt om uw wachtwoord te wijzigen, kan u deze mail negeren", "emails.recovery.thanks": "Bedankt,", + "emails.recovery.buttonText": "Wachtwoord opnieuw instellen", "emails.recovery.signature": "{{project}} team", "emails.invitation.subject": "Uitnodiging van %s Team uit %s", "emails.invitation.hello": "Hallo,", "emails.invitation.body": "U ontvangt deze mail want u was uitgenodig door {{owner}} om lid van het {{team}} team te worden in {{project}} ", "emails.invitation.footer": "Als u niet geintereseerd bent, kan u deze mail negeren.", "emails.invitation.thanks": "Bedankt,", + "emails.invitation.buttonText": "Uitnodiging voor {{team}} accepteren", "emails.invitation.signature": "{{project}} team", "locale.country.unknown": "Onbekend", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/nn.json b/app/config/locale/translations/nn.json index 44be0f9845..646a57904c 100644 --- a/app/config/locale/translations/nn.json +++ b/app/config/locale/translations/nn.json @@ -8,6 +8,7 @@ "emails.verification.body": "Følg denne lenkja for å bekrefta din e-postadresse.", "emails.verification.footer": "Om du ikkje bad om å bekrefta e-postadressa, kan du ignorera denne meldinga.", "emails.verification.thanks": "Takk,", + "emails.verification.buttonText": "Stadfest e-postadresse", "emails.verification.signature": "{{project}} team", "emails.magicSession.subject": "Pålogging", "emails.magicSession.hello": "Hei,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Følg denne lenkja for å nullstilla ditt {{project}} passord.", "emails.recovery.footer": "Om du ikkje ba om å nullstilla passordet ditt, kan du ignorera denne meldinga.", "emails.recovery.thanks": "Takk,", + "emails.recovery.buttonText": "Nullstill passord", "emails.recovery.signature": "{{project}} team", "emails.invitation.subject": "Innbyding til %s Team ved %s", "emails.invitation.hello": "Hallo,", "emails.invitation.body": "Denne meldinga ble sendt til deg fordi {{owner}} ynskja å invitera deg til å bli medlem av {{team}} team i {{project}}.", "emails.invitation.footer": "Om du ikkje er interessert, kan du ignorera denne meldinga.", "emails.invitation.thanks": "Takk,", + "emails.invitation.buttonText": "Godta invitasjon til {{team}}", "emails.invitation.signature": "{{project}} team", "locale.country.unknown": "Ukjend", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/or.json b/app/config/locale/translations/or.json index efd516f23a..a8e08b8043 100644 --- a/app/config/locale/translations/or.json +++ b/app/config/locale/translations/or.json @@ -8,6 +8,7 @@ "emails.verification.body": "ଆପଣଙ୍କର ଇମେଲ୍ ଠିକଣା ଯାଞ୍ଚ କରିବାକୁ ଏହି ଲିଙ୍କ୍ ଅନୁସରଣ କରନ୍ତୁ |", "emails.verification.footer": "ଯଦି ଆପଣ ଏହି ଠିକଣା ଯାଞ୍ଚ କରିବାକୁ କହି ନାହାଁନ୍ତି, ତେବେ ଆପଣ ଏହି ସନ୍ଦେଶକୁ ଉପେକ୍ଷା କରିପାରିବେ |", "emails.verification.thanks": "ଧନ୍ୟବାଦ,", + "emails.verification.buttonText": "ଇମେଲ ଠିକଣା ନିଶ୍ଚିତ କରନ୍ତୁ", "emails.verification.signature": "{{project}} ଦଳ", "emails.magicSession.subject": "ଲଗଇନ୍ କରନ୍ତୁ", "emails.magicSession.hello": "ନମସ୍କାର,", @@ -20,12 +21,14 @@ "emails.recovery.body": "ଆପଣଙ୍କର {{project}} ପାସୱାର୍ଡ ପୁନଃ ସେଟ୍ କରିବାକୁ ଏହି ଲିଙ୍କକୁ ଅନୁସରଣ କରନ୍ତୁ |", "emails.recovery.footer": "ଯଦି ଆପଣ ଆପଣଙ୍କର ପାସୱାର୍ଡ ପୁନଃ ସେଟ୍ କରିବାକୁ କହି ନାହାଁନ୍ତି, ତେବେ ଆପଣ ଏହି ସନ୍ଦେଶକୁ ଉପେକ୍ଷା କରିପାରିବେ |", "emails.recovery.thanks": "ଧନ୍ୟବାଦ,", + "emails.recovery.buttonText": "ପାସୱାର୍ଡ ପୁନଃସେଟ୍ କରନ୍ତୁ", "emails.recovery.signature": "{{project}} ଦଳ", "emails.invitation.subject": "%s ରେ %s ଦଳକୁ ନିମନ୍ତ୍ରଣ |", "emails.invitation.hello": "ନମସ୍କାର,", "emails.invitation.body": "ଏହି ମେଲ୍ ଆପଣଙ୍କୁ ପଠାଯାଇଥିଲା କାରଣ {{owner}} ଆପଣଙ୍କୁ {{project} ରେ {{team}} ଦଳର ସଦସ୍ୟ ହେବାକୁ ଆମନ୍ତ୍ରଣ କରିବାକୁ ଚାହୁଁଥିଲେ |", "emails.invitation.footer": "ଯଦି ଆପଣ ଆଗ୍ରହୀ ନୁହଁନ୍ତି, ଆପଣ ଏହି ସନ୍ଦେଶକୁ ଅଣଦେଖା କରିପାରିବେ |", "emails.invitation.thanks": "ଧନ୍ୟବାଦ,", + "emails.invitation.buttonText": "{{team}} ପାଇଁ ଆମନ୍ତ୍ରଣ ଗ୍ରହଣ କରନ୍ତୁ", "emails.invitation.signature": "{{project}} ଦଳ", "locale.country.unknown": "ଅଜ୍ଞାତ", "countries.af": "ଆଫଗାନିସ୍ତାନ", diff --git a/app/config/locale/translations/pl.json b/app/config/locale/translations/pl.json index ee5811fb59..75bc3a24f9 100644 --- a/app/config/locale/translations/pl.json +++ b/app/config/locale/translations/pl.json @@ -8,6 +8,7 @@ "emails.verification.body": "Przejdź do tego linku, aby zweryfikować swój adres e-mail.", "emails.verification.footer": "Jeśli to nie Ty prosiłeś o zweryfikowanie tego adresu, zignoruj tę wiadomość.", "emails.verification.thanks": "Dziękujemy,", + "emails.verification.buttonText": "Potwierdź adres e-mail", "emails.verification.signature": "Zespół {{project}}", "emails.magicSession.subject": "Logowanie", "emails.magicSession.hello": "Cześć,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Przejdź do tego linku, aby zresetować hasło dla {{project}}.", "emails.recovery.footer": "Jeśli to nie Ty prosiłeś o zresetowanie swojego hasła, zignoruj tę wiadomość.", "emails.recovery.thanks": "Dziękujemy,", + "emails.recovery.buttonText": "Zresetuj hasło", "emails.recovery.signature": "Zespół {{project}}", "emails.invitation.subject": "Zaproszenie do zespołu %s w %s", "emails.invitation.hello": "Cześć,", "emails.invitation.body": "Otrzymujesz tę wiadomość, ponieważ {{owner}} zaprasza Cię do grona członków zespołu {{team}} w projekcie {{project}}.", "emails.invitation.footer": "Jeśli nie jesteś zainteresowany, zignoruj tę wiadomość.", "emails.invitation.thanks": "Dziękujemy,", + "emails.invitation.buttonText": "Zaakceptuj zaproszenie do {{team}}", "emails.invitation.signature": "Zespół {{project}}", "locale.country.unknown": "Nieznany", "countries.af": "Afganistan", diff --git a/app/config/locale/translations/pt-br.json b/app/config/locale/translations/pt-br.json index a53ca79813..7e3af1d3f1 100644 --- a/app/config/locale/translations/pt-br.json +++ b/app/config/locale/translations/pt-br.json @@ -8,6 +8,7 @@ "emails.verification.body": "Clique neste link para verificar o seu endereço de e-mail.", "emails.verification.footer": "Se você não solicitou a verificação deste e-mail, ignore essa mensagem.", "emails.verification.thanks": "Muito obrigado,", + "emails.verification.buttonText": "Confirmar endereço de e-mail", "emails.verification.signature": "Time {{project}}", "emails.magicSession.subject": "Login", "emails.magicSession.hello": "Olá,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Clique neste link para redefinir sua senha do {{project}}.", "emails.recovery.footer": "Se você não solicitou a redefinição da sua senha, você pode ignorar essa mensagem.", "emails.recovery.thanks": "Muito obrigado,", + "emails.recovery.buttonText": "Redefinir senha", "emails.recovery.signature": "Time {{project}}", "emails.invitation.subject": "Convite para o Time %s em %s", "emails.invitation.hello": "Olá,", "emails.invitation.body": "Este e-mail foi enviado porque {{owner}} deseja convidar você a se tornar membro do Time {{team}} em {{project}}.", "emails.invitation.footer": "Caso não tenha interesse, ignore essa mensagem.", "emails.invitation.thanks": "Muito obrigado,", + "emails.invitation.buttonText": "Aceitar convite para {{team}}", "emails.invitation.signature": "Time {{project}}", "locale.country.unknown": "Desconhecido", "countries.af": "Afeganistão", diff --git a/app/config/locale/translations/pt-pt.json b/app/config/locale/translations/pt-pt.json index d85dca9300..c13ce558bf 100644 --- a/app/config/locale/translations/pt-pt.json +++ b/app/config/locale/translations/pt-pt.json @@ -8,6 +8,7 @@ "emails.verification.body": "Siga esta ligação para verificar o seu endereço de correio electrónico.", "emails.verification.footer": "Se não pediu para verificar este endereço, pode ignorar esta mensagem.", "emails.verification.thanks": "Obrigado,", + "emails.verification.buttonText": "Confirmar endereço de email", "emails.verification.signature": "Equipa {{project}}", "emails.magicSession.subject": "Login", "emails.magicSession.hello": "Olá ,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Utilize este link para redefinir a palavra-passe do seu projecto {{project}}", "emails.recovery.footer": "Se não pediu para redefinir a sua palavra-passe, pode ignorar esta mensagem.", "emails.recovery.thanks": "Obrigado,", + "emails.recovery.buttonText": "Repor palavra-passe", "emails.recovery.signature": "Equipa {{project}}", "emails.invitation.subject": "Convite à equipa de %s às %s", "emails.invitation.hello": "Olá,", "emails.invitation.body": "Este correio foi-lhe enviado porque {{owner}} queria convidá-lo a tornar-se membro da equipa {{team}} da {{project}}.", "emails.invitation.footer": "Se não estiver interessado, pode ignorar esta mensagem.", "emails.invitation.thanks": "Obrigado,", + "emails.invitation.buttonText": "Aceitar convite para o {{team}}", "emails.invitation.signature": "Equipa {{project}}", "locale.country.unknown": "Desconhecido", "countries.af": "Afeganistão", diff --git a/app/config/locale/translations/ro.json b/app/config/locale/translations/ro.json index 04cb22dd6b..88499ce3f6 100644 --- a/app/config/locale/translations/ro.json +++ b/app/config/locale/translations/ro.json @@ -8,6 +8,7 @@ "emails.verification.body": "Click pe acest link pentru a valida adresa de email.", "emails.verification.footer": "Dacă nu ai cerut validarea adresei de email, poți ignora acest mesaj.", "emails.verification.thanks": "Mulțumim,", + "emails.verification.buttonText": "Confirmă adresa de email", "emails.verification.signature": "Echipa {{project}}", "emails.magicSession.subject": "Login", "emails.magicSession.hello": "Bună ziua,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Click aici pentru a reseta parola pentru {{project}}", "emails.recovery.footer": "Dacă nu ai cerut să îți schimbi parola, ignoră acest mesaj.", "emails.recovery.thanks": "Mulțumim,", + "emails.recovery.buttonText": "Resetează parola", "emails.recovery.signature": "Echipa {{project}}", "emails.invitation.subject": "Invitatie catre %s Echipa la %s", "emails.invitation.hello": "Bună ziua,", "emails.invitation.body": "Acest email a fost trimis pentru că {{owner}} a vrut ca tu să devii membru al echipei {{team}} la {{project}}.", "emails.invitation.footer": "Dacă nu esti interesat, poți ignora acest email.", "emails.invitation.thanks": "Mulțumim,", + "emails.invitation.buttonText": "Acceptă invitația la {{team}}", "emails.invitation.signature": "Echipa {{project}}", "locale.country.unknown": "Necunoscut", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/ru.json b/app/config/locale/translations/ru.json index 029aa06ee7..f61337de80 100644 --- a/app/config/locale/translations/ru.json +++ b/app/config/locale/translations/ru.json @@ -8,6 +8,7 @@ "emails.verification.body": "Перейдите по ссылке, чтобы подтвердить свой адрес электронной почты.", "emails.verification.footer": "Если вы не запрашивали подтверждение этого адреса, проигнорируйте это сообщение.", "emails.verification.thanks": "Спасибо,", + "emails.verification.buttonText": "Подтвердить адрес электронной почты", "emails.verification.signature": "команда {{project}}", "emails.magicSession.subject": "Логин", "emails.magicSession.hello": "Здравствуйте,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Перейдите по этой ссылке для того чтобы сбросить свой пароль для проекта {{project}}", "emails.recovery.footer": "Если вы не запрашивали сброс пароля, проигнорируйте это сообщение.", "emails.recovery.thanks": "Спасибо,", + "emails.recovery.buttonText": "Сбросить пароль", "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.buttonText": "Принять приглашение в {{team}}", "emails.invitation.signature": "команда {{project}}", "locale.country.unknown": "Неизвестно", "countries.af": "Афганистан", diff --git a/app/config/locale/translations/sa.json b/app/config/locale/translations/sa.json index 7aa8c90d77..b3326110d1 100644 --- a/app/config/locale/translations/sa.json +++ b/app/config/locale/translations/sa.json @@ -8,6 +8,7 @@ "emails.verification.body": "ई-पत्रनिर्णायनार्थमिदं संयोगसूत्रमनुसरतु।", "emails.verification.footer": "यदि अस्य संकेतस्य निर्णायनं नेष्यते तर्हि वात्र्तामिमामुपेक्षताम्‌।", "emails.verification.thanks": "धन्यवादः,", + "emails.verification.buttonText": "ईमेल-पत्त्रं सुनिश्चित करें", "emails.verification.signature": "{{project}} गणः", "emails.magicSession.subject": "संप्रवेशः", "emails.magicSession.hello": "अयि,", @@ -20,12 +21,14 @@ "emails.recovery.body": "{{project}} कूटशब्दपुनयाेजनाय संयोगमेनमनुसरतु।", "emails.recovery.footer": "यदि कूटशब्दस्य पुनयाेजनं नेष्यते तर्हि वात्र्तामिमामुपेक्षताम्‌।", "emails.recovery.thanks": "धन्यवादः,", + "emails.recovery.buttonText": "गुप्तशब्दं पुनः स्थापित करें", "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.buttonText": "{{team}} निमन्त्रणं स्वीकुरुत", "emails.invitation.signature": "{{project}} गणः", "locale.country.unknown": "अज्ञातम्‌ ", "countries.af": "आफगानिस्थानम्‌", diff --git a/app/config/locale/translations/sd.json b/app/config/locale/translations/sd.json index 3f1f7678db..26c89a1770 100644 --- a/app/config/locale/translations/sd.json +++ b/app/config/locale/translations/sd.json @@ -8,6 +8,7 @@ "emails.verification.body": "پنھنجي اي ميل ايڊريس جي تصديق ڪرڻ لاءِ ھن لنڪ تي عمل ڪريو.", "emails.verification.footer": "جيڪڏھن توھان نه پ askيا ھئا ھن ايڊريس جي تصديق ڪرڻ لاءِ ، توھان نظر انداز ڪري سگھوٿا ھن پيغام کي.", "emails.verification.thanks": "مهرباني,", + "emails.verification.buttonText": "اي ميل پتو تصديق ڪريو", "emails.verification.signature": "{{project}} ٽيم", "emails.magicSession.subject": "لاگ ان", "emails.magicSession.hello": "هي ,", @@ -20,12 +21,14 @@ "emails.recovery.body": "ھن لنڪ تي عمل ڪريو پنھنجو {{project}} پاسورڊ ري سيٽ ڪرڻ لاءِ.", "emails.recovery.footer": "جيڪڏھن توھان نه پ پيو ھو پنھنجي پاسورڊ کي ري سيٽ ڪرڻ لاءِ ، توھان نظر انداز ڪري سگھوٿا ھن پيغام کي.", "emails.recovery.thanks": "مهرباني,", + "emails.recovery.buttonText": "پاسورڊ ري سيٽ ڪريو", "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.buttonText": "{{team}} جي دعوت قبول ڪريو", "emails.invitation.signature": "{{project}} ٽيم", "locale.country.unknown": "نامعلوم", "countries.af": "افغانستان", diff --git a/app/config/locale/translations/si.json b/app/config/locale/translations/si.json index 536e8d3604..e2053407ea 100644 --- a/app/config/locale/translations/si.json +++ b/app/config/locale/translations/si.json @@ -8,6 +8,7 @@ "emails.verification.body": "ඔබගේ විද්‍යුත් තැපැල් ලිපිනය සත්‍යාපනය කිරීමට මෙම සම්බන්ධකය අනුගමනය කරන්න.", "emails.verification.footer": "මෙම ලිපිනය සත්‍යාපනය කරන ලෙස ඔබ ඉල්ලුවේ නැත්නම්, ඔබට මෙම පණිවිඩය නොසලකා හැරිය හැක.", "emails.verification.thanks": "ස්තුතියි,", + "emails.verification.buttonText": "ඊමේල් ලිපිනය තහවුරු කරන්න", "emails.verification.signature": "{{project}} කණ්ඩායම", "emails.magicSession.subject": "ප්‍රවේශ වන්න", "emails.magicSession.hello": "හේයි,", @@ -20,12 +21,14 @@ "emails.recovery.body": "ඔබගේ {{project}} මුරපදය නැවත සැකසීමට මෙම සම්බන්ධකය අනුගමනය කරන්න.", "emails.recovery.footer": "ඔබගේ මුරපදය නැවත සකසන ලෙස ඔබ ඉල්ලුවේ නැත්නම්, ඔබට මෙම පණිවිඩය නොසලකා හැරිය හැක.", "emails.recovery.thanks": "ස්තුතියි,", + "emails.recovery.buttonText": "මුරපදය යළි පිහිටුවන්න", "emails.recovery.signature": "{{project}} කණ්ඩායම", "emails.invitation.subject": "%s කණ්ඩායමට ආරාධනා %s හි", "emails.invitation.hello": "ආයුබෝවන්,", "emails.invitation.body": "මෙම තැපැල් ඔබට එව්වේ, {{owner}} හට {{project}} හි {{team}} කණ්ඩායමේ සාමාජිකයෙකු වීමට ඔබට ආරාධනා කිරීමට අවශ්‍ය වූ බැවිනි.", "emails.invitation.footer": "ඔබ උනන්දුවක් නොදක්වන්නේ නම්, ඔබට මෙම පණිවිඩය නොසලකා හැරිය හැක.", "emails.invitation.thanks": "ස්තුතියි,", + "emails.invitation.buttonText": "{{team}} සඳහා ආරාධනය පිළිගෙනින්න", "emails.invitation.signature": "{{project}} කණ්ඩායම", "locale.country.unknown": "නොදන්නා", "countries.af": "ඇෆ්ගනිස්ථානය", diff --git a/app/config/locale/translations/sk.json b/app/config/locale/translations/sk.json index 93c12c0881..1b41d8031d 100644 --- a/app/config/locale/translations/sk.json +++ b/app/config/locale/translations/sk.json @@ -8,6 +8,7 @@ "emails.verification.body": "Použi tento link pre overenie svojej emailovej adresy.", "emails.verification.footer": "Ak si nepožiadal o overenie tejto adresy, môžeš túto správu ignorovať.", "emails.verification.thanks": "Ďakujeme.,", + "emails.verification.buttonText": "Potvrďte e-mailovú adresu", "emails.verification.signature": "{{project}} tím", "emails.magicSession.subject": "Prihlásenie", "emails.magicSession.hello": "Ahoj,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Použi tento link pre obnovenie svojho {{project}} hesla.", "emails.recovery.footer": "Ak si nepožiadal o obnovu svojho hesla, túto správu môžeš ignorovať.", "emails.recovery.thanks": "Ďakujeme,", + "emails.recovery.buttonText": "Obnoviť heslo", "emails.recovery.signature": "{{project}} tím", "emails.invitation.subject": "Pozvánka do %s Tímu v %s", "emails.invitation.hello": "Ahoj,", "emails.invitation.body": "Tento email ti bol zaslaný, pretože {{owner}} ťa pozval, aby si sa stal členom {{team}} tímu v projekte {{project}}.", "emails.invitation.footer": "Ak nemáš záujem, môžeš túto správu ignorovať.", "emails.invitation.thanks": "Ďakujeme,", + "emails.invitation.buttonText": "Prijať pozvánku do {{team}}", "emails.invitation.signature": "{{project}} tím", "locale.country.unknown": "Neznámy", "countries.af": "Afganistan", diff --git a/app/config/locale/translations/sn.json b/app/config/locale/translations/sn.json index d17a98ff42..9fcadfaa82 100644 --- a/app/config/locale/translations/sn.json +++ b/app/config/locale/translations/sn.json @@ -8,6 +8,7 @@ "emails.verification.body": "Tevedza chinongedzo ichi kuti uratidze kuti kero iyi ndeyako.", "emails.verification.footer": "Kana usina kukumbira kuti uratidze kuti kero iyi ndeyako, unogona kufuratira meseji iyi.", "emails.verification.thanks": "Ndatenda,", + "emails.verification.buttonText": "Simbisa kero yeemail", "emails.verification.signature": "Chikwata che{{project}}", "emails.magicSession.subject": "Pinda", "emails.magicSession.hello": "Hesi,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Baya chinongedzo ichi kuti uchinje pasiwedhi yako ye{{project}}.", "emails.recovery.footer": "Kana usina kukumbira kuchinja pasiwedhi yako, unogona kufuratira meseji iyi.", "emails.recovery.thanks": "Ndatenda,", + "emails.recovery.buttonText": "Gadzirisa password", "emails.recovery.signature": "Chikwata che{{project}}", "emails.invitation.subject": "Kukokwa kuchikwata che%s ku%s", "emails.invitation.hello": "Mhoro,", "emails.invitation.body": "Tsamba iyi yatumirwa kwauri nekuti {{owner}} anga achida kuti uve nhengo yechikwata che{{team}} pachirongwa che{{project}}.", "emails.invitation.footer": "Kana usiri kufarira kuve nhengo yechikwata ichi, unogona kufuratira meseji iyi.", "emails.invitation.thanks": "Ndatenda,", + "emails.invitation.buttonText": "Gamuchira kukokwa ku {{team}}", "emails.invitation.signature": "Chikwata che{{project}}", "locale.country.unknown": "Haizivikanwe", "countries.af": "Afuganisitani", diff --git a/app/config/locale/translations/sv.json b/app/config/locale/translations/sv.json index 8997fd53f8..9bff513f0c 100644 --- a/app/config/locale/translations/sv.json +++ b/app/config/locale/translations/sv.json @@ -8,6 +8,7 @@ "emails.verification.body": "Klicka på denna länk för att verifiera din email", "emails.verification.footer": "Om du inte bad om att verifiera den här e-postadressen kan du ignorera detta mail.", "emails.verification.thanks": "Tack,", + "emails.verification.buttonText": "Bekräfta e-postadress", "emails.verification.signature": "{{project}} teamet", "emails.magicSession.subject": "Logga in", "emails.magicSession.hello": "Hej,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Klicka på denna länk för att återställa lösenordet på {{project}}", "emails.recovery.footer": "Om du inte bad om att återställa ditt lösenord kan du ignorera detta mail.", "emails.recovery.thanks": "Tack,", + "emails.recovery.buttonText": "Återställ lösenord", "emails.recovery.signature": "{{project}} teamet", "emails.invitation.subject": "Inbjudan till %s teamet på %s", "emails.invitation.hello": "Hej,", "emails.invitation.body": "Detta mail skickades till dig eftersom {{owner}} ville bjuda in dig att bli medlem i teamet {{team}} på {{project}}.", "emails.invitation.footer": "Om du inte är intresserad kan du ignorera detta mail.", "emails.invitation.thanks": "Tack,", + "emails.invitation.buttonText": "Acceptera inbjudan till {{team}}", "emails.invitation.signature": "{{project}} teamet", "locale.country.unknown": "Okänt", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/ta.json b/app/config/locale/translations/ta.json index f0695867a9..4afcbe9b63 100644 --- a/app/config/locale/translations/ta.json +++ b/app/config/locale/translations/ta.json @@ -8,6 +8,7 @@ "emails.verification.body": "உங்கள் மின்னஞ்சல் முகவரியைச் சரிபார்க்க இந்த இணைப்பைப் பின்தொடரவும்.", "emails.verification.footer": "இந்த முகவரியைச் சரிபார்க்கும்படி உங்களிடம் கேட்கப்படவில்லை என்றால், இந்தச் செய்தியை நீங்கள் புறக்கணிக்கலாம்.", "emails.verification.thanks": "நன்றி,", + "emails.verification.buttonText": "மின்னஞ்சல் முகவரியை உறுதிப்படுத்தவும்", "emails.verification.signature": "{{project}} குழு ", "emails.magicSession.subject": "உள்நுழைய", "emails.magicSession.hello": "ஏய்,", @@ -20,12 +21,14 @@ "emails.recovery.body": "மீட்டமைக்க இந்த இணைப்பைப் பின்தொடரவும் {{project}} கடவுச்சொல்.", "emails.recovery.footer": "உங்கள் கடவுச்சொல்லை மீட்டமைக்கும்படி உங்களிடம் கேட்கப்படவில்லை என்றால், இந்தச் செய்தியை நீங்கள் புறக்கணிக்கலாம்.", "emails.recovery.thanks": "நன்றி,", + "emails.recovery.buttonText": "கடவுச்சொல்லை மீட்டமைக்கவும்", "emails.recovery.signature": "{{project}} குழு", "emails.invitation.subject": "அழைப்பிதழ் %s குழு %s ", "emails.invitation.hello": "வணக்கம்,", "emails.invitation.body": "{{project}} இல் {{team}} குழுவில் உறுப்பினராக உங்களை {{owner}} அழைக்க விரும்புவதால், இந்த அஞ்சல் உங்களுக்கு அனுப்பப்பட்டது.", "emails.invitation.footer": "உங்களுக்கு ஆர்வம் இல்லை என்றால், இந்த செய்தியை நீங்கள் புறக்கணிக்கலாம்.", "emails.invitation.thanks": "நன்றி,", + "emails.invitation.buttonText": "{{team}} அழைப்பை ஏற்கவும்", "emails.invitation.signature": "{{project}} குழு", "locale.country.unknown": "அறியவில்லை", "countries.af": "ஆப்கானித்தான்", diff --git a/app/config/locale/translations/te.json b/app/config/locale/translations/te.json index 870b0b82a2..4073fc72d9 100644 --- a/app/config/locale/translations/te.json +++ b/app/config/locale/translations/te.json @@ -8,6 +8,7 @@ "emails.verification.body": "ఈ లింక్ ద్వారా ఇమెయిల్ ని ధృవీకరించండి", "emails.verification.footer": "మీరు ఈ చిరునామాను ధృవీకరించమని అడగనట్లయితే, మీరు ఈ సందేశాన్ని విస్మరించవచ్చు", "emails.verification.thanks": "ధన్యవాదాలు,", + "emails.verification.buttonText": "ఇమెయిల్ చిరునామాను నిర్ధారించండి", "emails.verification.signature": "{{project}} జట్", "emails.magicSession.subject": "లాగిన్", "emails.magicSession.hello": "నమస్కారము,", @@ -20,12 +21,14 @@ "emails.recovery.body": "మీ {{project}} పాస్వర్డ్ ని రీసెట్ చేయడానికి ఈ లింక్ ని అనుసరించండి", "emails.recovery.footer": "మీరు మీ పాస్వర్డ్ ని రీసెట్ చేయమని అడగనట్లయితే, మీరు ఈ సందేశాన్ని విస్మరించవచ్చు", "emails.recovery.thanks": "ధన్యవాదాల,", + "emails.recovery.buttonText": "పాస్‌వర్డ్‌ను రీసెట్ చేయండి", "emails.recovery.signature": "{{project}} జట్", "emails.invitation.subject": "%s వద్ద %s బృందానికి ఆహ్వానం", "emails.invitation.hello": "నమస్కారమ,", "emails.invitation.body": "{{owner}} మిమ్మల్ని {{project}} లో {{team}} బృందంలో సభ్యునిగా ఉండమని ఆహ్వానించాలనుకుంటున్నందున ఈ మెయిల్ మీకు పంపబడింది.", "emails.invitation.footer": "మీకు ఆసక్తి లేకుంటే, మీరు ఈ సందేశాన్ని విస్మరించవచ్చు.", "emails.invitation.thanks": "ధన్యవాదాల,", + "emails.invitation.buttonText": "{{team}} కు ఆహ్వానాన్ని ఆమోదించండి", "emails.invitation.signature": "{{project}} జట్", "locale.country.unknown": "తెలియని", "countries.af": "ఆఫ్ఘనిస్తాన్", diff --git a/app/config/locale/translations/th.json b/app/config/locale/translations/th.json index 5a53b16055..4003ece666 100644 --- a/app/config/locale/translations/th.json +++ b/app/config/locale/translations/th.json @@ -8,6 +8,7 @@ "emails.verification.body": "กดเข้าไปที่ลิงก์นี้เพื่อยืนยันอีเมลของท่าน", "emails.verification.footer": "หากท่านไม่ได้ต้องการที่จะยืนยันอีเมลนี้ ท่านสามารถเพิกเฉยข้อความนี้ได้", "emails.verification.thanks": "ขอบคุณ", + "emails.verification.buttonText": "ยืนยันที่อยู่อีเมล", "emails.verification.signature": "ทีม {{project}}", "emails.magicSession.subject": "เข้าสู่ระบบ", "emails.magicSession.hello": "เรียนผู้ใช้งาน", @@ -20,12 +21,14 @@ "emails.recovery.body": "กดเข้าไปที่ลิงก์นี้เพื่อรีเซ็ตรหัสผ่านสำหรับโปรเจกต์ {{project}} ของท่าน", "emails.recovery.footer": "หากท่านไม่ได้ต้องการที่จะรีเซ็ตรหัสผ่านของท่าน ท่านสามารถเพิกเฉยข้อความนี้ได้", "emails.recovery.thanks": "ขอบคุณ", + "emails.recovery.buttonText": "รีเซ็ตรหัสผ่าน", "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.buttonText": "ยอมรับคำเชิญเข้าร่วม {{team}}", "emails.invitation.signature": "ทีม {{project}}", "locale.country.unknown": "ไม่ทราบ", "countries.af": "อัฟกานิสถาน", diff --git a/app/config/locale/translations/tl.json b/app/config/locale/translations/tl.json index 6d0be01095..27ea6c088f 100644 --- a/app/config/locale/translations/tl.json +++ b/app/config/locale/translations/tl.json @@ -8,6 +8,7 @@ "emails.verification.body": "Sundin ang link na ito upang ma-verify ang iyong email address.", "emails.verification.footer": "Kung hindi mo hiningi na i-verify ang address na ito, maaari mong balewalain ang mensahe na ito.", "emails.verification.thanks": "Salamat,", + "emails.verification.buttonText": "Kumpirmahin ang email address", "emails.verification.signature": "Pangkat ng {{project}}", "emails.magicSession.subject": "Mag log in", "emails.magicSession.hello": "Kamusta ,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Sundin ang link na ito upang i-reset ang password ng iyong {{project}}.", "emails.recovery.footer": "Kung hindi mo hiningi na i-reset ang iyong password, maaari mong balewalain ang mensahe na ito.", "emails.recovery.thanks": "Salamat,", + "emails.recovery.buttonText": "I-reset ang password", "emails.recovery.signature": "Pangkat ng {{project}}", "emails.invitation.subject": "Imbitasyon para sa Pangkat %s sa %s", "emails.invitation.hello": "Kamusta,", "emails.invitation.body": "Ipinadala sa iyo ang mail na ito dahil gusto kang imbitahan ni {{owner}} na maging miyembro ng Pangkat {{team}} sa ilalim ng proyektong {{project}}.", "emails.invitation.footer": "Kung ikaw ay hindi interesado, maaari mong balewalain ang mensaheng ito.", "emails.invitation.thanks": "Salamat,", + "emails.invitation.buttonText": "Tanggapin ang paanyaya sa {{team}}", "emails.invitation.signature": "Pangkat ng {{project}}", "locale.country.unknown": "Hindi kilala", "countries.af": "Apganistan", diff --git a/app/config/locale/translations/tr.json b/app/config/locale/translations/tr.json index 115050c2e2..a7183152b6 100644 --- a/app/config/locale/translations/tr.json +++ b/app/config/locale/translations/tr.json @@ -8,6 +8,7 @@ "emails.verification.body": "Eposta adresini doğrulamak için bu bağlantıyı kullanın.", "emails.verification.footer": "Eğer bu eposta adresini doğrulamak isteyen siz değilseniz devam etmeyin.", "emails.verification.thanks": "Teşekkürler,", + "emails.verification.buttonText": "E-posta adresini doğrula", "emails.verification.signature": "{{project}} takımı", "emails.magicSession.subject": "Giriş", "emails.magicSession.hello": "Merhaba,", @@ -20,12 +21,14 @@ "emails.recovery.body": "{{project}} şifrenizi sıfırlamak için bu bağlantıyı kullanın.", "emails.recovery.footer": "Eğer şifre sıfırlama talebinde bulunmadıysanız devam etmeyin.", "emails.recovery.thanks": "Teşekkürler,", + "emails.recovery.buttonText": "Şifreyi sıfırla", "emails.recovery.signature": "{{project}} takımı", "emails.invitation.subject": "%s üzerinde %s Takımına Davet", "emails.invitation.hello": "Merhaba,", "emails.invitation.body": "Bu epostayı aldınız, çünkü {{owner}} sizi {{project}} üzerinde {{team}} takımının üyesi olmaya davet etti.", "emails.invitation.footer": "Eğer ilgilenmiyorsanız devam etmeyin.", "emails.invitation.thanks": "Teşekkürler,", + "emails.invitation.buttonText": "{{team}}'e daveti kabul et", "emails.invitation.signature": "{{project}} takımı", "locale.country.unknown": "Bilinmeyen", "countries.af": "Afganistan", diff --git a/app/config/locale/translations/uk.json b/app/config/locale/translations/uk.json index 3f66bd1c58..daa003754d 100644 --- a/app/config/locale/translations/uk.json +++ b/app/config/locale/translations/uk.json @@ -8,6 +8,7 @@ "emails.verification.body": "Перейдіть за цим посиланням, щоб підтвердити свою електронну адресу.", "emails.verification.footer": "Якщо ви не запитували підтвердження цієї адреси, ви можете ігнорувати це повідомлення.", "emails.verification.thanks": "Дякуємо,", + "emails.verification.buttonText": "Підтвердити адресу електронної пошти", "emails.verification.signature": "команда {{project}}", "emails.magicSession.subject": "Логін", "emails.magicSession.hello": "Вітаємо,", @@ -20,12 +21,14 @@ "emails.recovery.body": "Перейдіть за цим посиланням для того щоб скинути свій пароль для проекту {{project}}", "emails.recovery.footer": "Якщо ви не запитували скидання паролю, проігноруйте це повідомлення.", "emails.recovery.thanks": "Дякуємо,", + "emails.recovery.buttonText": "Скинути пароль", "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.buttonText": "Прийняти запрошення до {{team}}", "emails.invitation.signature": "команда {{project}}", "locale.country.unknown": "Невідомо", "countries.af": "Афганістан", diff --git a/app/config/locale/translations/ur.json b/app/config/locale/translations/ur.json index 9d6aa47762..4c93f36b51 100644 --- a/app/config/locale/translations/ur.json +++ b/app/config/locale/translations/ur.json @@ -8,6 +8,7 @@ "emails.verification.body": "براہ کرم اپنے ای میل کی تصدیق کے لیے درج ذیل لنک پر عمل کریں۔", "emails.verification.footer": "اگر آپ نے اس پتے کی تصدیق کے لیے نہیں کہا تو آپ اس پیغام کو نظر انداز کر سکتے ہیں۔", "emails.verification.thanks": "شکریہ،", + "emails.verification.buttonText": "ای میل پتہ کی تصدیق کریں", "emails.verification.signature": "ٹیم۔ {{project}}", "emails.magicSession.subject": "اگ ان کریں", "emails.magicSession.hello": "خوش آمدید،", @@ -20,12 +21,14 @@ "emails.recovery.body": "{{project}} کا پاس ورڈ تبدیل کرنے کے لیے درج ذیل لنک پر عمل کریں", "emails.recovery.footer": "اگر آپ نے اپنا پاس ورڈ دوبارہ ترتیب دینے کے لیے نہیں کہا تو آپ اس پیغام کو نظر انداز کر سکتے ہیں۔", "emails.recovery.thanks": "شکریہ،", + "emails.recovery.buttonText": "پاس ورڈ ری سیٹ کریں", "emails.recovery.signature": "ٹیم۔ {{project}}", "emails.invitation.subject": "%s پر %s ٹیم کو دعوت", "emails.invitation.hello": "خوش آمدید،", "emails.invitation.body": "یہ پیغام آپ کو اس لیے بھیجا گیا تھا کہ {{owner}} نے آپ کو {{project}} میں {{team}} ٹیم کا رکن بننے کی دعوت بھیجی", "emails.invitation.footer": "اگر آپ دلچسپی نہیں رکھتے تو آپ اس پیغام کو نظر انداز کر سکتے ہیں۔", "emails.invitation.thanks": "شکریہ،", + "emails.invitation.buttonText": "{{team}} کی دعوت قبول کریں", "emails.invitation.signature": "ٹیم۔ {{project}", "locale.country.unknown": "نامعلوم", "countries.af": "افغانستان", diff --git a/app/config/locale/translations/vi.json b/app/config/locale/translations/vi.json index 76a545a1d4..e9168d9ab8 100644 --- a/app/config/locale/translations/vi.json +++ b/app/config/locale/translations/vi.json @@ -8,6 +8,7 @@ "emails.verification.body": "Nhấn vào đường dẫn sau để xác minh địa chỉ email của bạn.", "emails.verification.footer": "Nếu bạn không yêu cầu xác minh tài khoản, bạn có thể bỏ qua email này.", "emails.verification.thanks": "Cảm ơn", + "emails.verification.buttonText": "Xác nhận địa chỉ email", "emails.verification.signature": "Nhóm {{project}}", "emails.magicSession.subject": "Đăng nhập", "emails.magicSession.hello": "Chào", @@ -20,12 +21,14 @@ "emails.recovery.body": "Nhấn vào đường dẫn sau để thiết lập lại mật khẩu {{project}} của bạn.", "emails.recovery.footer": "Nếu bạn không yêu cầu thiết lập lại mật khẩu, bạn có thể bỏ qua email này.", "emails.recovery.thanks": "Cảm ơn", + "emails.recovery.buttonText": "Đặt lại mật khẩu", "emails.recovery.signature": "Nhóm {{project}}", "emails.invitation.subject": "Lời mời tham gia nhóm %s tại %s", "emails.invitation.hello": "Xin chào", "emails.invitation.body": "Email này được gửi cho bạn vì {{owner}} muốn mời bạn trở thành một thành viên của nhóm {{team}} tại {{project}}.", "emails.invitation.footer": "Nếu bạn không quan tâm, bạn có thể bỏ qua email này.", "emails.invitation.thanks": "Cảm ơn", + "emails.invitation.buttonText": "Chấp nhận lời mời vào {{team}}", "emails.invitation.signature": "Nhóm {{project}}", "locale.country.unknown": "Không xác định", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/zh-cn.json b/app/config/locale/translations/zh-cn.json index 5e35a89bfe..554b506e9e 100644 --- a/app/config/locale/translations/zh-cn.json +++ b/app/config/locale/translations/zh-cn.json @@ -8,6 +8,7 @@ "emails.verification.body": "点此链接验证您的电子邮件地址。", "emails.verification.footer": "如果您没有要求验证此地址,则可忽略此消息。", "emails.verification.thanks": "谢谢、", + "emails.verification.buttonText": "确认邮箱地址", "emails.verification.signature": "{{project}} 团队", "emails.magicSession.subject": "登录", "emails.magicSession.hello": "你好、", @@ -20,12 +21,14 @@ "emails.recovery.body": "点此链接重置您的 {{project}} 密码。", "emails.recovery.footer": "如果您没有要求重置密码,则可以忽略此消息。", "emails.recovery.thanks": "谢谢、", + "emails.recovery.buttonText": "重置密码", "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.buttonText": "接受加入 {{team}} 的邀请", "emails.invitation.signature": "{{project}} 团队", "locale.country.unknown": "未知", "countries.af": "阿富汗", diff --git a/app/config/locale/translations/zh-tw.json b/app/config/locale/translations/zh-tw.json index 146dd0a401..bb9868d679 100644 --- a/app/config/locale/translations/zh-tw.json +++ b/app/config/locale/translations/zh-tw.json @@ -8,6 +8,7 @@ "emails.verification.body": "按照此連結驗證您的電子郵件地址。", "emails.verification.footer": "如果您沒有要求驗證此地址,則可以忽略此消息。", "emails.verification.thanks": "謝謝、", + "emails.verification.buttonText": "確認電子郵件地址", "emails.verification.signature": "{{project}} 團隊", "emails.magicSession.subject": "登入", "emails.magicSession.hello": "嗨、", @@ -20,12 +21,14 @@ "emails.recovery.body": "按照此連結重置您的 {{project}} 密碼。", "emails.recovery.footer": "如果您沒有要求重置密碼,則可以忽略此消息。", "emails.recovery.thanks": "謝謝、", + "emails.recovery.buttonText": "重設密碼", "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.buttonText": "接受加入 {{team}} 的邀請", "emails.invitation.signature": "{{project}} 團隊", "locale.country.unknown": "未知", "countries.af": "阿富汗", From 6f501e27771ebc0b89b08a818672a1a049454281 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 29 Mar 2025 17:19:46 +0530 Subject: [PATCH 005/343] fix: teams test. --- tests/e2e/Scopes/Scope.php | 23 ++++++++++++ tests/e2e/Services/Teams/TeamsBaseClient.php | 36 +++++++++++-------- .../Services/Teams/TeamsCustomClientTest.php | 6 +++- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index 3213ff4c5d..d18be77a5f 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -43,6 +43,29 @@ abstract class Scope extends TestCase return []; } + protected function extractFromJoinLink(string $html): array + { + $linkStart = strpos($html, '/join-us?'); + $linkEnd = strpos($html, '#title', $linkStart); + $link = substr($html, $linkStart, $linkEnd - $linkStart); + + // Extract the query part only + $queryStart = strpos($link, '?') + 1; + $queryString = substr($link, $queryStart); + + // Parse the query string + parse_str(str_replace('&', '&', $queryString), $queryParams); + + return [ + 'userId' => $queryParams['userId'] ?? null, + 'secret' => $queryParams['secret'] ?? null, + 'teamId' => $queryParams['teamId'] ?? null, + 'teamName' => $queryParams['teamName'] ?? null, + 'membershipId' => $queryParams['membershipId'] ?? null, + ]; + } + + protected function getLastRequest(): array { sleep(2); diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index 3fcd9c043d..78354bd6b8 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -223,8 +223,10 @@ trait TeamsBaseClient $this->assertEquals($email, $lastEmail['to'][0]['address']); $this->assertEquals($name, $lastEmail['to'][0]['name']); $this->assertEquals('Invitation to ' . $teamName . ' Team at ' . $this->getProject()['name'], $lastEmail['subject']); - $this->assertEquals($response['body']['teamId'], substr($lastEmail['text'], strpos($lastEmail['text'], '&teamId=', 0) + 8, 20)); - $this->assertEquals($teamName, substr($lastEmail['text'], strpos($lastEmail['text'], '&teamName=', 0) + 10, 7)); + + $tokens = $this->extractFromJoinLink($lastEmail['html']); + $this->assertEquals($teamName, $tokens['teamName']); + $this->assertEquals($response['body']['teamId'], $tokens['teamId']); /** * Test with UserId @@ -288,8 +290,10 @@ trait TeamsBaseClient $this->assertEquals($secondEmail, $lastEmail['to'][0]['address']); $this->assertEquals($secondName, $lastEmail['to'][0]['name']); $this->assertEquals('Invitation to ' . $teamName . ' Team at ' . $this->getProject()['name'], $lastEmail['subject']); - $this->assertEquals($response['body']['teamId'], substr($lastEmail['text'], strpos($lastEmail['text'], '&teamId=', 0) + 8, 20)); - $this->assertEquals($teamName, substr($lastEmail['text'], strpos($lastEmail['text'], '&teamName=', 0) + 10, 7)); + + $tokens = $this->extractFromJoinLink($lastEmail['html']); + $this->assertEquals($teamName, $tokens['teamName']); + $this->assertEquals($response['body']['teamId'], $tokens['teamId']); // test for resending invitation $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ @@ -305,9 +309,10 @@ trait TeamsBaseClient $this->assertEquals(201, $response['headers']['status-code']); $lastEmail = $this->getLastEmail(); - $membershipUid = substr($lastEmail['text'], strpos($lastEmail['text'], '?membershipId=', 0) + 14, 20); - $userUid = substr($lastEmail['text'], strpos($lastEmail['text'], '&userId=', 0) + 8, 20); - $secret = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); + $tokens = $this->extractFromJoinLink($lastEmail['html']); + $membershipUid = $tokens['membershipId']; + $userUid = $tokens['userId']; + $secret = $tokens['secret']; /** * Test for FAILURE @@ -350,11 +355,11 @@ trait TeamsBaseClient $this->assertEquals(400, $response['headers']['status-code']); return [ - 'teamUid' => $teamUid, - 'teamName' => $teamName, - 'secret' => $secret, - 'membershipUid' => $membershipUid, - 'userUid' => $userUid, + 'teamUid' => $tokens['teamId'], + 'teamName' => $tokens['teamName'], + 'secret' => $tokens['secret'], + 'membershipUid' => $tokens['membershipId'], + 'userUid' => $tokens['userId'], 'email' => $email, 'name' => $name ]; @@ -612,10 +617,11 @@ trait TeamsBaseClient $this->assertEquals(201, $response['headers']['status-code']); $lastEmail = $this->getLastEmail(); + $tokens = $this->extractFromJoinLink($lastEmail['html']); - $secret = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); - $membershipUid = substr($lastEmail['text'], strpos($lastEmail['text'], '?membershipId=', 0) + 14, 20); - $userUid = substr($lastEmail['text'], strpos($lastEmail['text'], '&userId=', 0) + 8, 20); + $secret = $tokens['secret']; + $membershipUid = $tokens['membershipId']; + $userUid = $tokens['userId']; $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', [ 'origin' => 'http://localhost', diff --git a/tests/e2e/Services/Teams/TeamsCustomClientTest.php b/tests/e2e/Services/Teams/TeamsCustomClientTest.php index 7286bb0827..e30dacac74 100644 --- a/tests/e2e/Services/Teams/TeamsCustomClientTest.php +++ b/tests/e2e/Services/Teams/TeamsCustomClientTest.php @@ -6,6 +6,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; +use Utopia\CLI\Console; class TeamsCustomClientTest extends Scope { @@ -152,11 +153,14 @@ class TeamsCustomClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $email = $this->getLastEmail(); + Console::log(json_encode([ + 'testTeamsInviteHTMLInjection' => $email + ], JSON_PRETTY_PRINT)); + $encoded = 'http://localhost:5000/join-us\"></a><h1>INJECTED</h1>?'; $this->assertStringNotContainsString('

INJECTED

', $email['html']); $this->assertStringContainsString($encoded, $email['html']); - $this->assertStringContainsString($encoded, $email['text']); $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/'.$response['body']['$id'], array_merge([ 'content-type' => 'application/json', From b1c67e6f7472ddab4a583e4b677a1e4bdbe02ed1 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 29 Mar 2025 18:21:25 +0530 Subject: [PATCH 006/343] fix: other remaining tests. --- tests/e2e/Scopes/Scope.php | 43 +++++++++------- .../Account/AccountCustomClientTest.php | 49 +++++++++++-------- tests/e2e/Services/Webhooks/WebhooksBase.php | 3 +- .../Webhooks/WebhooksCustomClientTest.php | 10 ++-- 4 files changed, 60 insertions(+), 45 deletions(-) diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index d18be77a5f..9ae1efd1cb 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -35,8 +35,7 @@ abstract class Scope extends TestCase if ($limit === 1) { return end($emails); } else { - $lastEmails = array_slice($emails, -1 * $limit); - return $lastEmails; + return array_slice($emails, -1 * $limit); } } @@ -45,27 +44,35 @@ abstract class Scope extends TestCase protected function extractFromJoinLink(string $html): array { - $linkStart = strpos($html, '/join-us?'); - $linkEnd = strpos($html, '#title', $linkStart); - $link = substr($html, $linkStart, $linkEnd - $linkStart); + foreach (['/join-us?', '/verification?', '/recovery?'] as $prefix) { + $linkStart = strpos($html, $prefix); + if ($linkStart !== false) { + $hrefStart = strrpos(substr($html, 0, $linkStart), 'href="'); + if ($hrefStart === false) { + continue; + } - // Extract the query part only - $queryStart = strpos($link, '?') + 1; - $queryString = substr($link, $queryStart); + $hrefStart += 6; + $hrefEnd = strpos($html, '"', $hrefStart); + if ($hrefEnd === false || $hrefStart >= $hrefEnd) { + continue; + } - // Parse the query string - parse_str(str_replace('&', '&', $queryString), $queryParams); + $link = substr($html, $hrefStart, $hrefEnd - $hrefStart); + $queryStart = strpos($link, '?'); + if ($queryStart === false) { + continue; + } - return [ - 'userId' => $queryParams['userId'] ?? null, - 'secret' => $queryParams['secret'] ?? null, - 'teamId' => $queryParams['teamId'] ?? null, - 'teamName' => $queryParams['teamName'] ?? null, - 'membershipId' => $queryParams['membershipId'] ?? null, - ]; + $queryString = substr($link, $queryStart + 1); + parse_str(html_entity_decode($queryString), $queryParams); + return $queryParams; + } + } + + return []; } - protected function getLastRequest(): array { sleep(2); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index daa5bcbff8..51057ada2c 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -779,17 +779,18 @@ class AccountCustomClientTest extends Scope $this->assertEquals($name, $lastEmail['to'][0]['name']); $this->assertEquals('Account Verification', $lastEmail['subject']); - $verification = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); - $expireTime = strpos($lastEmail['text'], 'expire=' . urlencode(DateTime::format(new \DateTime($response['body']['expire']))), 0); - $this->assertNotFalse($expireTime); + $tokens = $this->extractFromJoinLink($lastEmail['html']); + $verification = $tokens['secret']; + $expectedExpire = DateTime::format(new \DateTime($response['body']['expire'])); + $this->assertEquals($expectedExpire, $tokens['expire']); - $secretTest = strpos($lastEmail['text'], 'secret=' . $response['body']['secret'], 0); + // Secret check + $this->assertArrayHasKey('secret', $tokens); + $this->assertNotEmpty($tokens['secret']); - $this->assertNotFalse($secretTest); - - $userIDTest = strpos($lastEmail['text'], 'userId=' . $response['body']['userId'], 0); - - $this->assertNotFalse($userIDTest); + // User ID check + $this->assertArrayHasKey('userId', $tokens); + $this->assertNotEmpty($tokens['userId']); /** * Test for FAILURE @@ -1081,19 +1082,25 @@ class AccountCustomClientTest extends Scope $this->assertEquals($name, $lastEmail['to'][0]['name']); $this->assertEquals('Password Reset', $lastEmail['subject']); - $recovery = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); + $tokens = $this->extractFromJoinLink($lastEmail['html']); - $expireTime = strpos($lastEmail['text'], 'expire=' . urlencode(DateTime::format(new \DateTime($response['body']['expire']))), 0); + // Secret check + $this->assertArrayHasKey('secret', $tokens); + $this->assertNotEmpty($tokens['secret']); + $this->assertNotFalse($response['body']['secret']); - $this->assertNotFalse($expireTime); + // User ID check + $this->assertArrayHasKey('userId', $tokens); + $this->assertNotEmpty($tokens['userId']); + $this->assertNotFalse($response['body']['userId']); - $secretTest = strpos($lastEmail['text'], 'secret=' . $response['body']['secret'], 0); - - $this->assertNotFalse($secretTest); - - $userIDTest = strpos($lastEmail['text'], 'userId=' . $response['body']['userId'], 0); - - $this->assertNotFalse($userIDTest); + // Expire check + $this->assertArrayHasKey('expire', $tokens); + $this->assertNotEmpty($tokens['expire']); + $this->assertEquals( + DateTime::format(new \DateTime($response['body']['expire'])), + $tokens['expire'] + ); /** * Test for FAILURE @@ -1131,7 +1138,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals(404, $response['headers']['status-code']); - $data['recovery'] = $recovery; + $data['recovery'] = $tokens['secret']; return $data; } @@ -1285,7 +1292,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals('otpuser2@appwrite.io', $lastEmail['to'][0]['address']); $this->assertEquals('OTP for ' . $this->getProject()['name'] . ' Login', $lastEmail['subject']); - // FInd 6 concurrent digits in email text - OTP + // Find 6 concurrent digits in email text - OTP preg_match_all("/\b\d{6}\b/", $lastEmail['text'], $matches); $code = ($matches[0] ?? [])[0] ?? ''; diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index c743810feb..05c74bf7da 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -920,8 +920,9 @@ trait WebhooksBase $this->assertNotEmpty($team['body']['$id']); $lastEmail = $this->getLastEmail(); + $tokens = $this->extractFromJoinLink($lastEmail['html']); - $secret = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); + $secret = $tokens['secret']; $membershipId = $team['body']['$id']; $webhook = $this->getLastRequest(); diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php index a170492551..bcc4ede30a 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php @@ -894,9 +894,9 @@ class WebhooksCustomClientTest extends Scope $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); $this->assertStringContainsString('teams.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('teams.*.memberships.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('teams.*.memberships.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -919,8 +919,8 @@ class WebhooksCustomClientTest extends Scope $this->assertNotEmpty($webhook['data']['userId']); $this->assertNotEmpty($webhook['data']['teamId']); $this->assertCount(2, $webhook['data']['roles']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['joined'])); - $this->assertEquals(true, $webhook['data']['confirm']); + $this->assertTrue((new DatetimeValidator())->isValid($webhook['data']['joined'])); + $this->assertTrue($webhook['data']['confirm']); /** * Test for FAILURE From 736078203afa7e80f204f2332972425482080083 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 29 Mar 2025 18:22:59 +0530 Subject: [PATCH 007/343] update: change method name. --- tests/e2e/Scopes/Scope.php | 2 +- tests/e2e/Services/Account/AccountCustomClientTest.php | 4 ++-- tests/e2e/Services/Teams/TeamsBaseClient.php | 8 ++++---- tests/e2e/Services/Webhooks/WebhooksBase.php | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index 9ae1efd1cb..54c68bb65f 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -42,7 +42,7 @@ abstract class Scope extends TestCase return []; } - protected function extractFromJoinLink(string $html): array + protected function extractQueryParamsFromEmailLink(string $html): array { foreach (['/join-us?', '/verification?', '/recovery?'] as $prefix) { $linkStart = strpos($html, $prefix); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 51057ada2c..d23980ed1f 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -779,7 +779,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals($name, $lastEmail['to'][0]['name']); $this->assertEquals('Account Verification', $lastEmail['subject']); - $tokens = $this->extractFromJoinLink($lastEmail['html']); + $tokens = $this->extractQueryParamsFromEmailLink($lastEmail['html']); $verification = $tokens['secret']; $expectedExpire = DateTime::format(new \DateTime($response['body']['expire'])); $this->assertEquals($expectedExpire, $tokens['expire']); @@ -1082,7 +1082,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals($name, $lastEmail['to'][0]['name']); $this->assertEquals('Password Reset', $lastEmail['subject']); - $tokens = $this->extractFromJoinLink($lastEmail['html']); + $tokens = $this->extractQueryParamsFromEmailLink($lastEmail['html']); // Secret check $this->assertArrayHasKey('secret', $tokens); diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index 78354bd6b8..7952d6dd04 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -224,7 +224,7 @@ trait TeamsBaseClient $this->assertEquals($name, $lastEmail['to'][0]['name']); $this->assertEquals('Invitation to ' . $teamName . ' Team at ' . $this->getProject()['name'], $lastEmail['subject']); - $tokens = $this->extractFromJoinLink($lastEmail['html']); + $tokens = $this->extractQueryParamsFromEmailLink($lastEmail['html']); $this->assertEquals($teamName, $tokens['teamName']); $this->assertEquals($response['body']['teamId'], $tokens['teamId']); @@ -291,7 +291,7 @@ trait TeamsBaseClient $this->assertEquals($secondName, $lastEmail['to'][0]['name']); $this->assertEquals('Invitation to ' . $teamName . ' Team at ' . $this->getProject()['name'], $lastEmail['subject']); - $tokens = $this->extractFromJoinLink($lastEmail['html']); + $tokens = $this->extractQueryParamsFromEmailLink($lastEmail['html']); $this->assertEquals($teamName, $tokens['teamName']); $this->assertEquals($response['body']['teamId'], $tokens['teamId']); @@ -309,7 +309,7 @@ trait TeamsBaseClient $this->assertEquals(201, $response['headers']['status-code']); $lastEmail = $this->getLastEmail(); - $tokens = $this->extractFromJoinLink($lastEmail['html']); + $tokens = $this->extractQueryParamsFromEmailLink($lastEmail['html']); $membershipUid = $tokens['membershipId']; $userUid = $tokens['userId']; $secret = $tokens['secret']; @@ -617,7 +617,7 @@ trait TeamsBaseClient $this->assertEquals(201, $response['headers']['status-code']); $lastEmail = $this->getLastEmail(); - $tokens = $this->extractFromJoinLink($lastEmail['html']); + $tokens = $this->extractQueryParamsFromEmailLink($lastEmail['html']); $secret = $tokens['secret']; $membershipUid = $tokens['membershipId']; diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index 05c74bf7da..b69dea8ec1 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -920,7 +920,7 @@ trait WebhooksBase $this->assertNotEmpty($team['body']['$id']); $lastEmail = $this->getLastEmail(); - $tokens = $this->extractFromJoinLink($lastEmail['html']); + $tokens = $this->extractQueryParamsFromEmailLink($lastEmail['html']); $secret = $tokens['secret']; $membershipId = $team['body']['$id']; From b22be9b586f8668bee63ee36c7c9f173cb1ffc13 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 29 Mar 2025 18:53:51 +0530 Subject: [PATCH 008/343] fix: test with teamName. --- tests/e2e/Scopes/Scope.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index 54c68bb65f..8881a18da4 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -59,6 +59,7 @@ abstract class Scope extends TestCase } $link = substr($html, $hrefStart, $hrefEnd - $hrefStart); + $link = strtok($link, '#'); // Remove `#title` $queryStart = strpos($link, '?'); if ($queryStart === false) { continue; From c4852836ef0d9a2fcb14641ea68f373ecbd49c2c Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 29 Mar 2025 18:59:36 +0530 Subject: [PATCH 009/343] fix: realtime test. --- tests/e2e/Services/Realtime/RealtimeCustomClientTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index e356397408..2e9165b93f 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -415,7 +415,8 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("users.*", $response['data']['events']); $lastEmail = $this->getLastEmail(); - $verification = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); + $tokens = $this->extractQueryParamsFromEmailLink($lastEmail['html']); + $verification = $tokens['secret']; /** * Test Account Verification Complete From f2c43c14bf511e0ec2dfb591bc654a1fed075665 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 29 Mar 2025 19:20:27 +0530 Subject: [PATCH 010/343] fix: realtime test. --- tests/e2e/Services/Realtime/RealtimeCustomClientTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index 2e9165b93f..b4d202f811 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -613,7 +613,8 @@ class RealtimeCustomClientTest extends Scope $response = json_decode($client->receive(), true); $lastEmail = $this->getLastEmail(); - $recovery = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); + $tokens = $this->extractQueryParamsFromEmailLink($lastEmail['html']); + $recovery = $tokens['secret']; $this->assertArrayHasKey('type', $response); $this->assertArrayHasKey('data', $response); From f56fcc6d90e7fe224d5f8437718e0f7c1f4d7a37 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 29 Mar 2025 19:56:13 +0530 Subject: [PATCH 011/343] fix: remaining tests! pheww! --- tests/e2e/Services/Webhooks/WebhooksBase.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index b69dea8ec1..83177c7ea3 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -920,9 +920,11 @@ trait WebhooksBase $this->assertNotEmpty($team['body']['$id']); $lastEmail = $this->getLastEmail(); - $tokens = $this->extractQueryParamsFromEmailLink($lastEmail['html']); - $secret = $tokens['secret']; + // `$isAppUser` — no email expected; + $tokens = $this->extractQueryParamsFromEmailLink($lastEmail['html'] ?? ''); + + $secret = $tokens['secret'] ?? ''; $membershipId = $team['body']['$id']; $webhook = $this->getLastRequest(); From 0a4c430ae7b23d866647cbdce72b0c650eb0b6be Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 14 Apr 2025 12:56:42 +0100 Subject: [PATCH 012/343] feat: exp scheme --- app/config/console.php | 4 +- app/controllers/api/account.php | 15 +- app/controllers/api/projects.php | 4 +- app/controllers/api/teams.php | 3 +- app/controllers/api/vcs.php | 5 +- app/controllers/general.php | 11 +- app/init/resources.php | 50 +++-- src/Appwrite/Network/Platform.php | 114 ++++++++++++ src/Appwrite/Network/Validator/Origin.php | 185 +++++++------------ src/Appwrite/Network/Validator/Redirect.php | 25 +++ tests/unit/Network/Validators/OriginTest.php | 78 +++++--- 11 files changed, 300 insertions(+), 194 deletions(-) create mode 100644 src/Appwrite/Network/Platform.php create mode 100644 src/Appwrite/Network/Validator/Redirect.php diff --git a/app/config/console.php b/app/config/console.php index e37c9b7836..4a0421e153 100644 --- a/app/config/console.php +++ b/app/config/console.php @@ -5,7 +5,7 @@ */ use Appwrite\Auth\Auth; -use Appwrite\Network\Validator\Origin; +use Appwrite\Network\Platform; use Utopia\Database\Helpers\ID; use Utopia\System\System; @@ -23,7 +23,7 @@ $console = [ [ '$collection' => ID::custom('platforms'), 'name' => 'Localhost', - 'type' => Origin::CLIENT_TYPE_WEB, + 'type' => Platform::TYPE_WEB, 'hostname' => 'localhost', ], // Current host is added on app init ], diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 20f64496ac..f25ad92a28 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -21,6 +21,7 @@ use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; use Appwrite\Hooks\Hooks; use Appwrite\Network\Validator\Email; +use Appwrite\Network\Validator\Redirect; use Appwrite\OpenSSL\OpenSSL; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -1188,8 +1189,8 @@ App::get('/v1/account/sessions/oauth2/:provider') ->label('abuse-limit', 50) ->label('abuse-key', 'ip:{ip}') ->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('oAuthProviders'), fn ($node) => (!$node['mock'])))) . '.') - ->param('success', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) - ->param('failure', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) + ->param('success', '', fn ($platforms) => new Redirect($platforms), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['platforms']) + ->param('failure', '', fn ($platforms) => new Redirect($platforms), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['platforms']) ->param('scopes', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->inject('request') ->inject('response') @@ -1784,8 +1785,8 @@ App::get('/v1/account/tokens/oauth2/:provider') ->label('abuse-limit', 50) ->label('abuse-key', 'ip:{ip}') ->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('oAuthProviders'), fn ($node) => (!$node['mock'])))) . '.') - ->param('success', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) - ->param('failure', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) + ->param('success', '', fn ($platforms) => new Redirect($platforms), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['platforms']) + ->param('failure', '', fn ($platforms) => new Redirect($platforms), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['platforms']) ->param('scopes', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->inject('request') ->inject('response') @@ -1864,7 +1865,7 @@ App::post('/v1/account/tokens/magic-url') ->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}']) ->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', '', new Email(), 'User email.') - ->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) + ->param('url', '', fn ($platforms) => new Redirect($platforms), 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['platforms']) ->param('phrase', false, new Boolean(), 'Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.', true) ->inject('request') ->inject('response') @@ -3159,7 +3160,7 @@ App::post('/v1/account/recovery') ->label('abuse-limit', 10) ->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}']) ->param('email', '', new Email(), 'User email.') - ->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) + ->param('url', '', fn ($platforms) => new Redirect($platforms), 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['platforms']) ->inject('request') ->inject('response') ->inject('user') @@ -3434,7 +3435,7 @@ App::post('/v1/account/verification') )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{userId}') - ->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page + ->param('url', '', fn ($platforms) => new Redirect($platforms), 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['platforms']) // TODO add built-in confirm page ->inject('request') ->inject('response') ->inject('project') diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index b29bd227aa..343e281354 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -8,8 +8,8 @@ use Appwrite\Event\Mail; use Appwrite\Event\Validator\Event; use Appwrite\Extend\Exception; use Appwrite\Hooks\Hooks; +use Appwrite\Network\Platform; use Appwrite\Network\Validator\Email; -use Appwrite\Network\Validator\Origin; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -1749,7 +1749,7 @@ App::post('/v1/projects/:projectId/platforms') ] )) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('type', null, new WhiteList([Origin::CLIENT_TYPE_WEB, Origin::CLIENT_TYPE_FLUTTER_WEB, Origin::CLIENT_TYPE_FLUTTER_IOS, Origin::CLIENT_TYPE_FLUTTER_ANDROID, Origin::CLIENT_TYPE_FLUTTER_LINUX, Origin::CLIENT_TYPE_FLUTTER_MACOS, Origin::CLIENT_TYPE_FLUTTER_WINDOWS, Origin::CLIENT_TYPE_APPLE_IOS, Origin::CLIENT_TYPE_APPLE_MACOS, Origin::CLIENT_TYPE_APPLE_WATCHOS, Origin::CLIENT_TYPE_APPLE_TVOS, Origin::CLIENT_TYPE_ANDROID, Origin::CLIENT_TYPE_UNITY, Origin::CLIENT_TYPE_REACT_NATIVE_IOS, Origin::CLIENT_TYPE_REACT_NATIVE_ANDROID], true), 'Platform type.') + ->param('type', null, new WhiteList([Platform::TYPE_WEB, Platform::TYPE_FLUTTER_WEB, Platform::TYPE_FLUTTER_IOS, Platform::TYPE_FLUTTER_ANDROID, Platform::TYPE_FLUTTER_LINUX, Platform::TYPE_FLUTTER_MACOS, Platform::TYPE_FLUTTER_WINDOWS, Platform::TYPE_APPLE_IOS, Platform::TYPE_APPLE_MACOS, Platform::TYPE_APPLE_WATCHOS, Platform::TYPE_APPLE_TVOS, Platform::TYPE_ANDROID, Platform::TYPE_UNITY, Platform::TYPE_REACT_NATIVE_IOS, Platform::TYPE_REACT_NATIVE_ANDROID], true), 'Platform type.') ->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.') ->param('key', '', new Text(256), 'Package name for Android or bundle ID for iOS or macOS. Max length: 256 chars.', true) ->param('store', '', new Text(256), 'App store or Google Play store ID. Max length: 256 chars.', true) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 3e0e366b6b..0bd54ccbbf 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -11,6 +11,7 @@ use Appwrite\Event\Messaging; use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; +use Appwrite\Network\Validator\Redirect; use Appwrite\Platform\Workers\Deletes; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -455,7 +456,7 @@ App::post('/v1/teams/:teamId/memberships') } return new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE); }, 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', false, ['project']) - ->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) // TODO add our own built-in confirm page + ->param('url', '', fn ($platforms) => new Redirect($platforms), 'URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['platforms']) // TODO add our own built-in confirm page ->param('name', '', new Text(128), 'Name of the new team member. Max length: 128 chars.', true) ->inject('response') ->inject('project') diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 2c145febcc..6e4d4aefdc 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -4,6 +4,7 @@ use Appwrite\Auth\OAuth2\Github as OAuth2Github; use Appwrite\Event\Build; use Appwrite\Event\Delete; use Appwrite\Extend\Exception; +use Appwrite\Network\Validator\Redirect; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -288,8 +289,8 @@ App::get('/v1/vcs/github/authorize') type: MethodType::WEBAUTH, hide: true, )) - ->param('success', '', fn ($clients) => new Host($clients), 'URL to redirect back to console after a successful installation attempt.', true, ['clients']) - ->param('failure', '', fn ($clients) => new Host($clients), 'URL to redirect back to console after a failed installation attempt.', true, ['clients']) + ->param('success', '', fn ($platforms) => new Redirect($platforms), 'URL to redirect back to console after a successful installation attempt.', true, ['platforms']) + ->param('failure', '', fn ($platforms) => new Redirect($platforms), 'URL to redirect back to console after a failed installation attempt.', true, ['platforms']) ->inject('request') ->inject('response') ->inject('project') diff --git a/app/controllers/general.php b/app/controllers/general.php index b28718e514..2e7833d9aa 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -9,6 +9,7 @@ use Appwrite\Event\Event; use Appwrite\Event\Func; use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception as AppwriteException; +use Appwrite\Network\Platform; use Appwrite\Network\Validator\Origin; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -504,7 +505,7 @@ App::init() ->inject('getProjectDB') ->inject('locale') ->inject('localeCodes') - ->inject('clients') + ->inject('platforms') ->inject('geodb') ->inject('queueForStatsUsage') ->inject('queueForEvents') @@ -513,7 +514,7 @@ App::init() ->inject('executor') ->inject('isResourceBlocked') ->inject('previewHostname') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $platforms, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname) { /* * Appwrite Router */ @@ -637,7 +638,9 @@ App::init() $port = \parse_url($request->getOrigin($referrer), PHP_URL_PORT); $refDomainOrigin = 'localhost'; - $validator = new Hostname($clients); + + $hostnames = Platform::getHostnames($platforms); + $validator = new Hostname($hostnames); if ($validator->isValid($origin)) { $refDomainOrigin = $origin; } @@ -728,7 +731,7 @@ App::init() * Skip this check for non-web platforms which are not required to send an origin header */ $origin = $request->getOrigin($request->getReferer('')); - $originValidator = new Origin(\array_merge($project->getAttribute('platforms', []), $console->getAttribute('platforms', []))); + $originValidator = new Origin($platforms); if ( !$originValidator->isValid($origin) diff --git a/app/init/resources.php b/app/init/resources.php index c719a47344..2c9f4b37d4 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -19,6 +19,7 @@ use Appwrite\Event\StatsUsage; use Appwrite\Event\Webhook; use Appwrite\Extend\Exception; use Appwrite\GraphQL\Schema; +use Appwrite\Network\Platform; use Appwrite\Network\Validator\Origin; use Appwrite\Utopia\Request; use Executor\Executor; @@ -116,11 +117,11 @@ App::setResource('queueForCertificates', function (Publisher $publisher) { App::setResource('queueForMigrations', function (Publisher $publisher) { return new Migration($publisher); }, ['publisher']); -App::setResource('clients', function ($request, $console, $project) { +App::setResource('platforms', function (Request $request, Document $console, Document $project) { $console->setAttribute('platforms', [ // Always allow current host '$collection' => ID::custom('platforms'), 'name' => 'Current Host', - 'type' => Origin::CLIENT_TYPE_WEB, + 'type' => Platform::TYPE_WEB, 'hostname' => $request->getHostname(), ], Document::SET_TYPE_APPEND); @@ -133,39 +134,32 @@ App::setResource('clients', function ($request, $console, $project) { } $console->setAttribute('platforms', [ '$collection' => ID::custom('platforms'), - 'type' => Origin::CLIENT_TYPE_WEB, + 'type' => Platform::TYPE_WEB, 'name' => $hostname, 'hostname' => $hostname, ], Document::SET_TYPE_APPEND); } - /** - * Get All verified client URLs for both console and current projects - * + Filter for duplicated entries - */ - $clientsConsole = \array_map( - fn ($node) => $node['hostname'], - \array_filter( - $console->getAttribute('platforms', []), - fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && !empty($node['hostname'])) - ) - ); - - $clients = $clientsConsole; - $platforms = $project->getAttribute('platforms', []); - - foreach ($platforms as $node) { - if ( - isset($node['type']) && - ($node['type'] === Origin::CLIENT_TYPE_WEB || - $node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) && - !empty($node['hostname']) - ) { - $clients[] = $node['hostname']; - } + // Add `exp` and `appwrite-callback-{projectId}` schemes + if (!$project->isEmpty() && $project->getId() !== 'console') { + $project->setAttribute('platforms', [ + '$collection' => ID::custom('platforms'), + 'type' => Platform::TYPE_SCHEME, + 'name' => 'Expo', + 'key' => 'exp', + ], Document::SET_TYPE_APPEND); + $project->setAttribute('platforms', [ + '$collection' => ID::custom('platforms'), + 'type' => Platform::TYPE_SCHEME, + 'name' => 'Appwrite Callback', + 'key' => 'appwrite-callback-' . $project->getId(), + ], Document::SET_TYPE_APPEND); } - return \array_unique($clients); + return [ + ...$console->getAttribute('platforms', []), + ...$project->getAttribute('platforms', []), + ]; }, ['request', 'console', 'project']); App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForPlatform) { diff --git a/src/Appwrite/Network/Platform.php b/src/Appwrite/Network/Platform.php new file mode 100644 index 0000000000..ab7b73cd17 --- /dev/null +++ b/src/Appwrite/Network/Platform.php @@ -0,0 +1,114 @@ + Map scheme types to user-friendly platform names. + */ + private static array $names = [ + self::SCHEME_HTTP => 'Web', + self::SCHEME_HTTPS => 'Web', + self::SCHEME_IOS => 'iOS', + self::SCHEME_MACOS => 'macOS', + self::SCHEME_WATCHOS => 'watchOS', + self::SCHEME_TVOS => 'tvOS', + self::SCHEME_ANDROID => 'Android', + self::SCHEME_WINDOWS => 'Windows', + self::SCHEME_LINUX => 'Linux', + ]; + + /** + * Get user-friendly platform name from a scheme. + * + * @param string $scheme + * @return string Empty string if scheme is not found. + */ + public static function getNameByScheme(string $scheme): string + { + return self::$names[$scheme] ?? ''; + } + + public static function getHostnames(array $platforms): array + { + $hostnames = []; + foreach ($platforms as $platform) { + $type = $platform['type'] ?? self::TYPE_UNKNOWN; + $hostname = strtolower($platform['hostname'] ?? ''); + $key = strtolower($platform['key'] ?? ''); + + switch ($type) { + case self::TYPE_WEB: + case self::TYPE_FLUTTER_WEB: + $hostnames[] = $hostname; + break; + case self::TYPE_FLUTTER_IOS: + case self::TYPE_FLUTTER_ANDROID: + case self::TYPE_FLUTTER_MACOS: + case self::TYPE_FLUTTER_WINDOWS: + case self::TYPE_FLUTTER_LINUX: + case self::TYPE_ANDROID: + case self::TYPE_APPLE_IOS: + case self::TYPE_APPLE_MACOS: + case self::TYPE_APPLE_WATCHOS: + case self::TYPE_APPLE_TVOS: + case self::TYPE_REACT_NATIVE_IOS: + case self::TYPE_REACT_NATIVE_ANDROID: + if (!empty($key)) { + $hostnames[] = $key; + } + break; + default: + break; + } + } + return array_unique($hostnames); + } + + public static function getSchemes(array $platforms): array + { + $schemes = []; + foreach ($platforms as $platform) { + $type = $platform['type'] ?? self::TYPE_UNKNOWN; + $scheme = $platform['key'] ?? ''; + + switch ($type) { + case self::TYPE_SCHEME: + $schemes[] = $scheme; + break; + default: + break; + } + } + return array_unique($schemes); + } +} diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index d41e9af2ad..6120c8b51d 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -2,150 +2,82 @@ namespace Appwrite\Network\Validator; +use Appwrite\Network\Platform; use Utopia\Validator; use Utopia\Validator\Hostname; class Origin extends Validator { - public const CLIENT_TYPE_UNKNOWN = 'unknown'; - public const CLIENT_TYPE_WEB = 'web'; - public const CLIENT_TYPE_FLUTTER_IOS = 'flutter-ios'; - public const CLIENT_TYPE_FLUTTER_ANDROID = 'flutter-android'; - public const CLIENT_TYPE_FLUTTER_MACOS = 'flutter-macos'; - public const CLIENT_TYPE_FLUTTER_WINDOWS = 'flutter-windows'; - public const CLIENT_TYPE_FLUTTER_LINUX = 'flutter-linux'; - public const CLIENT_TYPE_FLUTTER_WEB = 'flutter-web'; - public const CLIENT_TYPE_APPLE_IOS = 'apple-ios'; - public const CLIENT_TYPE_APPLE_MACOS = 'apple-macos'; - public const CLIENT_TYPE_APPLE_WATCHOS = 'apple-watchos'; - public const CLIENT_TYPE_APPLE_TVOS = 'apple-tvos'; - public const CLIENT_TYPE_ANDROID = 'android'; - public const CLIENT_TYPE_UNITY = 'unity'; - public const CLIENT_TYPE_REACT_NATIVE_IOS = 'react-native-ios'; - public const CLIENT_TYPE_REACT_NATIVE_ANDROID = 'react-native-android'; - - - public const SCHEME_TYPE_HTTP = 'http'; - public const SCHEME_TYPE_HTTPS = 'https'; - public const SCHEME_TYPE_IOS = 'appwrite-ios'; - public const SCHEME_TYPE_MACOS = 'appwrite-macos'; - public const SCHEME_TYPE_WATCHOS = 'appwrite-watchos'; - public const SCHEME_TYPE_TVOS = 'appwrite-tvos'; - public const SCHEME_TYPE_ANDROID = 'appwrite-android'; - public const SCHEME_TYPE_WINDOWS = 'appwrite-windows'; - public const SCHEME_TYPE_LINUX = 'appwrite-linux'; + protected array $hostnames = []; + protected array $schemes = []; + protected ?string $scheme = null; + protected ?string $host = null; /** - * @var array + * Constructor + * + * @param array $platforms */ - protected $platforms = [ - self::SCHEME_TYPE_HTTP => 'Web', - self::SCHEME_TYPE_HTTPS => 'Web', - self::SCHEME_TYPE_IOS => 'iOS', - self::SCHEME_TYPE_MACOS => 'macOS', - self::SCHEME_TYPE_WATCHOS => 'watchOS', - self::SCHEME_TYPE_TVOS => 'tvOS', - self::SCHEME_TYPE_ANDROID => 'Android', - self::SCHEME_TYPE_WINDOWS => 'Windows', - self::SCHEME_TYPE_LINUX => 'Linux', - ]; - - /** - * @var array - */ - protected $clients = [ - ]; - - /** - * @var string - */ - protected $client = self::CLIENT_TYPE_UNKNOWN; - - /** - * @var string - */ - protected $host = ''; - - /** - * @param string $target - */ - public function __construct($platforms) + public function __construct(array $platforms) { - foreach ($platforms as $platform) { - $type = (isset($platform['type'])) ? $platform['type'] : ''; - - switch ($type) { - case self::CLIENT_TYPE_WEB: - case self::CLIENT_TYPE_FLUTTER_WEB: - $this->clients[] = (isset($platform['hostname'])) ? $platform['hostname'] : ''; - break; - - case self::CLIENT_TYPE_FLUTTER_IOS: - case self::CLIENT_TYPE_FLUTTER_ANDROID: - case self::CLIENT_TYPE_FLUTTER_MACOS: - case self::CLIENT_TYPE_FLUTTER_WINDOWS: - case self::CLIENT_TYPE_FLUTTER_LINUX: - case self::CLIENT_TYPE_ANDROID: - case self::CLIENT_TYPE_APPLE_IOS: - case self::CLIENT_TYPE_APPLE_MACOS: - case self::CLIENT_TYPE_APPLE_WATCHOS: - case self::CLIENT_TYPE_APPLE_TVOS: - case self::CLIENT_TYPE_REACT_NATIVE_IOS: - case self::CLIENT_TYPE_REACT_NATIVE_ANDROID: - $this->clients[] = (isset($platform['key'])) ? $platform['key'] : ''; - break; - - default: - # code... - break; - } - } + $this->hostnames = Platform::getHostnames($platforms); + $this->schemes = Platform::getSchemes($platforms); } - public function getDescription(): string - { - if (!\array_key_exists($this->client, $this->platforms)) { - return 'Unsupported platform'; - } - - return 'Invalid Origin. Register your new client (' . $this->host . ') as a new ' - . $this->platforms[$this->client] . ' platform on your project console dashboard'; - } /** - * Check if Origin has been allowed - * for access to the API - * - * @param mixed $origin - * + * Check if Redirect URI is valid. + * @param mixed $redirect The redirect URI. * @return bool */ - public function isValid($origin): bool + public function isValid($redirect): bool { - if (!is_string($origin)) { + $this->scheme = null; + $this->host = null; + + if (!is_string($redirect) || empty($redirect)) { return false; } - $scheme = \parse_url($origin, PHP_URL_SCHEME); - $host = \parse_url($origin, PHP_URL_HOST); + $parts = $this->parseUrl($redirect); + $scheme = $parts['scheme']; + $host = $parts['host']; - $this->host = $host; - $this->client = $scheme; - - if (empty($host)) { + if (!empty($scheme) && in_array($scheme, $this->schemes, true)) { return true; } - $validator = new Hostname($this->clients); + if (empty($host)) { + return true; + } else { + $validator = new Hostname($this->hostnames); + if ($validator->isValid($host)) { + return true; + } + } - return $validator->isValid($host); + return false; + } + + /** + * Get Description + * @return string + */ + public function getDescription(): string + { + $platform = $this->scheme ? Platform::getNameByScheme($this->scheme) : null; + $host = $this->host ? '(' . htmlspecialchars($this->host) . ')' : ''; + + if (empty($this->host) && empty($this->scheme)) { + return 'Invalid Origin.'; + } + + return 'Invalid Origin. Register your new client ' . $host . ' as a new ' + . $platform . ' platform on your project console dashboard'; } /** * Is array - * - * Function will return true if object is array. - * * @return bool */ public function isArray(): bool @@ -155,13 +87,28 @@ class Origin extends Validator /** * Get Type - * - * Returns validator type. - * * @return string */ public function getType(): string { return self::TYPE_STRING; } + + /** + * Parses a URI string to extract scheme and host. + * Stores extracted parts in $this->scheme and $this->host. + * @param string $uri + * @return array{scheme: string|null, host: string|null} + */ + protected function parseUrl(string $uri): array + { + if (str_ends_with($uri, '://')) { + $uri .= 'placeholder'; + } + $scheme = \parse_url($uri, PHP_URL_SCHEME); + $host = \parse_url($uri, PHP_URL_HOST); + $this->scheme = $scheme ?: null; + $this->host = $host ?: null; + return ['scheme' => $this->scheme,'host' => $this->host]; + } } diff --git a/src/Appwrite/Network/Validator/Redirect.php b/src/Appwrite/Network/Validator/Redirect.php new file mode 100644 index 0000000000..58bb955ad2 --- /dev/null +++ b/src/Appwrite/Network/Validator/Redirect.php @@ -0,0 +1,25 @@ +scheme ? Platform::getNameByScheme($this->scheme) : null; + $host = $this->host ? '(' . htmlspecialchars($this->host) . ')' : ''; + + if (empty($this->host) && empty($this->scheme)) { + return 'Invalid URI.'; + } + + return 'Invalid URI. Register your new client ' . $host . ' as a new ' + . $platform . ' platform on your project console dashboard'; + } +} diff --git a/tests/unit/Network/Validators/OriginTest.php b/tests/unit/Network/Validators/OriginTest.php index d9bc77c19f..839960b671 100644 --- a/tests/unit/Network/Validators/OriginTest.php +++ b/tests/unit/Network/Validators/OriginTest.php @@ -2,6 +2,7 @@ namespace Tests\Unit\Network\Validators; +use Appwrite\Network\Platform; use Appwrite\Network\Validator\Origin; use PHPUnit\Framework\TestCase; use Utopia\Database\Helpers\ID; @@ -14,62 +15,81 @@ class OriginTest extends TestCase [ '$collection' => ID::custom('platforms'), 'name' => 'Production', - 'type' => Origin::CLIENT_TYPE_WEB, + 'type' => Platform::TYPE_WEB, 'hostname' => 'appwrite.io', ], [ '$collection' => ID::custom('platforms'), 'name' => 'Development', - 'type' => Origin::CLIENT_TYPE_WEB, + 'type' => Platform::TYPE_WEB, 'hostname' => 'appwrite.test', ], [ '$collection' => ID::custom('platforms'), 'name' => 'Localhost', - 'type' => Origin::CLIENT_TYPE_WEB, + 'type' => Platform::TYPE_WEB, 'hostname' => 'localhost', ], [ '$collection' => ID::custom('platforms'), 'name' => 'Flutter', - 'type' => Origin::CLIENT_TYPE_FLUTTER_WEB, + 'type' => Platform::TYPE_FLUTTER_WEB, 'hostname' => 'appwrite.flutter', ], + [ + '$collection' => ID::custom('platforms'), + 'name' => 'Expo', + 'type' => Platform::TYPE_SCHEME, + 'key' => 'exp', + ], + [ + '$collection' => ID::custom('platforms'), + 'name' => 'Appwrite Callback', + 'type' => Platform::TYPE_SCHEME, + 'key' => 'appwrite-callback-123', + ], ]); - $this->assertEquals($validator->isValid('https://localhost'), true); - $this->assertEquals($validator->isValid('http://localhost'), true); - $this->assertEquals($validator->isValid('http://localhost:80'), true); + $this->assertEquals(true, $validator->isValid('https://localhost')); + $this->assertEquals(true, $validator->isValid('http://localhost')); + $this->assertEquals(true, $validator->isValid('http://localhost:80')); - $this->assertEquals($validator->isValid('https://appwrite.io'), true); - $this->assertEquals($validator->isValid('http://appwrite.io'), true); - $this->assertEquals($validator->isValid('http://appwrite.io:80'), true); + $this->assertEquals(true, $validator->isValid('https://appwrite.io')); + $this->assertEquals(true, $validator->isValid('http://appwrite.io')); + $this->assertEquals(true, $validator->isValid('http://appwrite.io:80')); - $this->assertEquals($validator->isValid('https://appwrite.test'), true); - $this->assertEquals($validator->isValid('http://appwrite.test'), true); - $this->assertEquals($validator->isValid('http://appwrite.test:80'), true); + $this->assertEquals(true, $validator->isValid('https://appwrite.test')); + $this->assertEquals(true, $validator->isValid('http://appwrite.test')); + $this->assertEquals(true, $validator->isValid('http://appwrite.test:80')); - $this->assertEquals($validator->isValid('https://appwrite.flutter'), true); - $this->assertEquals($validator->isValid('http://appwrite.flutter'), true); - $this->assertEquals($validator->isValid('http://appwrite.flutter:80'), true); + $this->assertEquals(true, $validator->isValid('https://appwrite.flutter')); + $this->assertEquals(true, $validator->isValid('http://appwrite.flutter')); + $this->assertEquals(true, $validator->isValid('http://appwrite.flutter:80')); - $this->assertEquals($validator->isValid('https://example.com'), false); - $this->assertEquals($validator->isValid('http://example.com'), false); - $this->assertEquals($validator->isValid('http://example.com:80'), false); + $this->assertEquals(false, $validator->isValid('https://example.com')); + $this->assertEquals(false, $validator->isValid('http://example.com')); + $this->assertEquals(false, $validator->isValid('http://example.com:80')); - $this->assertEquals($validator->isValid('appwrite-ios://com.company.appname'), false); - $this->assertEquals($validator->getDescription(), 'Invalid Origin. Register your new client (com.company.appname) as a new iOS platform on your project console dashboard'); + $this->assertEquals(true, $validator->isValid('exp://')); + $this->assertEquals(true, $validator->isValid('exp:///')); + $this->assertEquals(true, $validator->isValid('exp://index')); - $this->assertEquals($validator->isValid('appwrite-android://com.company.appname'), false); - $this->assertEquals($validator->getDescription(), 'Invalid Origin. Register your new client (com.company.appname) as a new Android platform on your project console dashboard'); + $this->assertEquals(true, $validator->isValid('appwrite-callback-123://')); + $this->assertEquals(false, $validator->isValid('appwrite-callback-456://')); - $this->assertEquals($validator->isValid('appwrite-macos://com.company.appname'), false); - $this->assertEquals($validator->getDescription(), 'Invalid Origin. Register your new client (com.company.appname) as a new macOS platform on your project console dashboard'); + $this->assertEquals(false, $validator->isValid('appwrite-ios://com.company.appname')); + $this->assertEquals('Invalid Origin. Register your new client (com.company.appname) as a new iOS platform on your project console dashboard', $validator->getDescription()); - $this->assertEquals($validator->isValid('appwrite-linux://com.company.appname'), false); - $this->assertEquals($validator->getDescription(), 'Invalid Origin. Register your new client (com.company.appname) as a new Linux platform on your project console dashboard'); + $this->assertEquals(false, $validator->isValid('appwrite-android://com.company.appname')); + $this->assertEquals('Invalid Origin. Register your new client (com.company.appname) as a new Android platform on your project console dashboard', $validator->getDescription()); - $this->assertEquals($validator->isValid('appwrite-windows://com.company.appname'), false); - $this->assertEquals($validator->getDescription(), 'Invalid Origin. Register your new client (com.company.appname) as a new Windows platform on your project console dashboard'); + $this->assertEquals(false, $validator->isValid('appwrite-macos://com.company.appname')); + $this->assertEquals('Invalid Origin. Register your new client (com.company.appname) as a new macOS platform on your project console dashboard', $validator->getDescription()); + + $this->assertEquals(false, $validator->isValid('appwrite-linux://com.company.appname')); + $this->assertEquals('Invalid Origin. Register your new client (com.company.appname) as a new Linux platform on your project console dashboard', $validator->getDescription()); + + $this->assertEquals(false, $validator->isValid('appwrite-windows://com.company.appname')); + $this->assertEquals('Invalid Origin. Register your new client (com.company.appname) as a new Windows platform on your project console dashboard', $validator->getDescription()); } } From 944624f13afbb57bf8742c4747c05831a4c6709a Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 14 Apr 2025 12:59:39 +0100 Subject: [PATCH 013/343] chore: fmt --- .../46/d0/0f82b9649c970f7aeaffd81272d8.val | Bin 0 -> 55096 bytes .../a5/d9/b57b6547e797b53635ad0d3c93e2.val | Bin 0 -> 78981 bytes .../ab/37/ab16032a4cf3218215f82e6b33d8.val | Bin 0 -> 38416 bytes .../c4/0c/131572298f4b919688b848f0d865.val | Bin 0 -> 47855 bytes .aider.tags.cache.v4/cache.db | Bin 0 -> 14454784 bytes .../cf/bc/6e633cea90c4e72d07887e4a655b.val | Bin 0 -> 77806 bytes .../d7/41/5f8dde2b6955c58d88f39cdb650d.val | Bin 0 -> 45747 bytes .../d9/2e/bde17980e9b4fef0f06922d7a9cb.val | Bin 0 -> 48781 bytes app/controllers/api/account.php | 1 - app/controllers/api/teams.php | 1 - app/controllers/api/vcs.php | 1 - app/init/resources.php | 1 - src/Appwrite/Network/Validator/Origin.php | 10 +++++----- 13 files changed, 5 insertions(+), 9 deletions(-) create mode 100644 .aider.tags.cache.v4/46/d0/0f82b9649c970f7aeaffd81272d8.val create mode 100644 .aider.tags.cache.v4/a5/d9/b57b6547e797b53635ad0d3c93e2.val create mode 100644 .aider.tags.cache.v4/ab/37/ab16032a4cf3218215f82e6b33d8.val create mode 100644 .aider.tags.cache.v4/c4/0c/131572298f4b919688b848f0d865.val create mode 100644 .aider.tags.cache.v4/cache.db create mode 100644 .aider.tags.cache.v4/cf/bc/6e633cea90c4e72d07887e4a655b.val create mode 100644 .aider.tags.cache.v4/d7/41/5f8dde2b6955c58d88f39cdb650d.val create mode 100644 .aider.tags.cache.v4/d9/2e/bde17980e9b4fef0f06922d7a9cb.val diff --git a/.aider.tags.cache.v4/46/d0/0f82b9649c970f7aeaffd81272d8.val b/.aider.tags.cache.v4/46/d0/0f82b9649c970f7aeaffd81272d8.val new file mode 100644 index 0000000000000000000000000000000000000000..504e479e2e2c63b9c47faea63c10f3d5d42104de GIT binary patch literal 55096 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 literal 0 HcmV?d00001 diff --git a/.aider.tags.cache.v4/a5/d9/b57b6547e797b53635ad0d3c93e2.val b/.aider.tags.cache.v4/a5/d9/b57b6547e797b53635ad0d3c93e2.val new file mode 100644 index 0000000000000000000000000000000000000000..4d93f55dc9c89af6518217aa70e6f48f134d803f GIT binary patch literal 78981 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 literal 0 HcmV?d00001 diff --git a/.aider.tags.cache.v4/c4/0c/131572298f4b919688b848f0d865.val b/.aider.tags.cache.v4/c4/0c/131572298f4b919688b848f0d865.val new file mode 100644 index 0000000000000000000000000000000000000000..7b8ef30857218e262d9386592e86739021d1d3a9 GIT binary patch literal 47855 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 literal 0 HcmV?d00001 diff --git a/.aider.tags.cache.v4/cache.db b/.aider.tags.cache.v4/cache.db new file mode 100644 index 0000000000000000000000000000000000000000..77c657782e5738664f7e16a6179727691164f4c4 GIT binary patch literal 14454784 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 HjcYlgJ_MrtWgdCAv_x*Ik8U7V)=f&x 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 z%0A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

2`g+n`gCP7R3%ZHbh;0kk2~AS-B1qycL| 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%0D?#>vJJ#zDsJ#@5Dq##m!nV__pO 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

as7>%YU}Ph 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�`Bz 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

wjw7LBzroH_p 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%0D%5uZv zycKYZTAW9inrt(N+)Q)q8KhI&Gx*jnUYDf?YqyN0wL>45khN`Q!fiA2xrmhzJQIeE#U{$U(Tc#UKEyl!3cDHyDq0&ffk>ya=_2U7i` zvy-Wfc|xcw{5h8x_s_X} zRLfEp6}m!wfn7mE&CJWiQ|1uuHPv-@jqkc!WNs5in<$VrGy_Tub8lR2Pi%X&J>Ry* z1}rT&8WVt4yc=3wV@Eg|f7?W`f7`^zj?-Pn0qZG0V2fG^h8tNQYe|5w)YnQrxWUWX z8$KKL09@2(gMzC;1BCJNEUo0SF1+DU74{Gi`bax)Xn2zoMfa0z_@-t-E@o`T?gCO2>divuS z5W51E=5-Vh*cQDu&G9IAh((n;m!aHVK%{s?D_Lis+%6VRF;jKZ$!!IE4INekrKTm*CCL&&-rFi*W}D_ar)EI%lq2HNqJSF0=8|Ian} zdU&7l{NQQe4!VxI>N#gPjyWpZN82`A|Azhl#pW-~*Icjt8d7?(=GoXgxe^0 zQHlz;3C%bY)qtkVoKYyZedIrX08!#8Zi!o%)NKY$mt`xOC?52nEzP7GbQo>uai>+7PL z;5F?F%rSdSlccPi$j(xGKVh%EpU<9HkF__vrhR}tX0K_IU-D=9qu|#f0f}>J@dFYU z`LDA05GB$Z@I^(5u&%0%q^wbS;6qZ@KE%>B-quRK#q0jSB0~>gt*E)t>lx} z3O@|d1IR_~LPaMhUTlI}IYBG=*fo2w28Vv#Jy!ji^-&YnisYiNITiUAeJ!d{fn}}} zEbIo%qV6Tro0@pK32wX^$`W5hC`&cnYgjc{_#ohR5ZkB8q?&M6IHHyOu26L$YgXXw zDv(n*H79)KGqsY>S?LzbSu0rh0C0-B^^bD;Rc8Q!Ec=00@?k6L(zHSxQx|}ZK^zlx zDG<&wNm|M0jUUV!7orL~18)qX3d1*d2yLlCt>jbRr%OBx;T4^LItGz8+7=O^yf>hg zeA@C~vNnc*h5Lb4)Te^!z{JVTY%~$vl5twe$1b;z#fDEsN5B>}$&bL+wyOwhi2+*4 zXD+*jVJ7$g?J$_~Og7^(-xI##-j}@fJlj2O-TU2-!tH;#&Ku5o&N7ZQj=J{E_Kvm# zw!YTytXWorWvQjEdAGTzslZq>Zbw`v!%@R9)iV%sF$qX#LsvR@`yb*Gb5i8=WVjJq z+lY|_Y>R}|sx8LxenGZ?Fo1ulFVw~?0eci-brO|?Rb&d-n~YvvsD&8<_U_nu3%l%* zdkfe_U@OxtSmf9SsR+0Wk3Kr(6isfnl%AqE6UPXB@sz6Q+pg3%TEJ7&H%)ubmDdhUOo{^rdt2bF_4^rD3>On~Ya$QAOH#aao7p|C1 zPti4Wgn-0TQL2W!T+>JC-2L)!p|6cfJ(wTUufQ{Y=6X#^&S=*3U zJkFdzR_Z7@JyqArM+Kx?jBF)rUF3pKnjInr$KqAZfr_z#9})V!RJ)Lrmy@P^#|Fis zzlLuk$^&EZB$a5kunjb?iY)W6u!|V z_l-qIin2u|_aXcLjSaq@-e)~0J>}eKu8q#$oQ)i^{T;i(*3ml0a>NpEmQ1@%4r9N# zRfZo8jg@S9nc(LTbzYKo3cSQ8DziV;TXo*{KEii&3=A@k4kfKX20)8CO%feiTh0>C z%tKjP$p;^xOHKlJ=!^kyQFrK2aCR|AKzn($k`LVfd)Ct6Asr3CqCBK}VBNfh(DwL0 zQmnpz3Dom_pCR*SS<-*675cJ2E z@Xg#;a~2I8(c=MGlp~rV2Nt=6vPU(w z&?N!0_<=6mf|~$$eM~L+;5{#~;NbO71aMJa|KP5{&W#D~qZibYkKJPULjQ=AncslUx7Y^2C8lGc0irH3 z4by;7rwHM1_l;We`5&3h^1}c*2KdDfkgA^}5Tk;nDgkc$q+0U9JJn;sVME?%0FT;+ zJQU=hA!>B4zwLRpx4;(25x^g{Es(P3C&=YQu$#ZDmVEp+>sfr5dJPBss15C^_yiXV&1ePrA+YA-~sOAYXnderyl0)6L51 z2MBTcfntb_EHRAjGosmB?mxDt4JZ6*!}2yL!o$dt3-D1JS=7K0 zVI6x{E&0qTW|kRV(;Q%q+G`pdej?0cMye&BJ^2L74zFo8ut)7f6efs8ut(iiOFn+m z85SP~bsyl1AJlOq3ww{~cWC5ff;@6EA35W*~*X+xBQG9)2jG9>?%AE&fLz-}^4P4U?Y6UiVWEf%m}SFKA9%gc?D z+w_cpO;y45cym&da^=bv3E0maQdyRiq}G=&bPKC8+YF6ANlyvgVWifp?vkG)bPKCm zTi7kEvxV+?3{)NJ7?WlR-BzX49PHAP`~pS*Iur+L#iPy4XxKKK8%dfWbn}?n%1{T8 zG(8&cjp~+{o)j?jg*;4kKk2k+^w(f_iS$G?o@5wDhcs2_ep00i1-U4sDMI&?s+9&i z7o^G2=(Va_K+26qM+#ohOF7Z#NMV-ZQnrB8X6lqd*>0pxg%%_U7!ZQ$A~QUBE;L_Y z!<1m2+OT;7+oe=R+x2ub=3JpWmZZ4?8c9cU;scOpT=?7U6M6`YR;I4UBqVfZbAx#oGy5V-x8Uxmi`T=hN-A5g0)Ww}wy((EAZ1M!Ik>v{M z>%Wlf|9@8J>F8bv>wk}Plw+Iyj=j6>IqM~BeM_$Sn7O=Zym7bDVCbXY2>JiI>YlyN zDnC+xEr*lk8!bhJlYL2X=?LHdm!6aki33ndD!ut{vEspBe3$P;c}5fMsqHV2FR|<@ zXbUJI4%*QC%nQWb^UMo;()=G-M^$5gfqYY?sG}P!sW*&y^RE-={Of$^ygMv3n76EO z^O8>^ynci*Z>n1INf#Efq+s4M!p*CE#KV|(p>oUB!eVZ@TA<0?*3e&28lXiTFj0p( zbw*BHS;V^YmDuq7Eqp7_*IYH%$X`$jfJH@Zf`9{~B|)B7NiF%v^Xjr4qk+GmBp{2* za-<^TPp0YtC7g5jsU@Fxu4X$DjKL*Y1n2l21LWB1_%WU*H64QQ^`MYGxisaA%BAOFs6@pxYe_9Dpr) zywJ=B3FnhL)RNCTqXlbb_=eblSM)bT>jNO5(>kanANa{vSYUVoZ2&C#8=?RQeM6?6 zCCF3H@{y4eEQrzLG-3*(uW4q2z9nqE&230-C6ore}NI`#cvT& zY_C1cg_Ns!&MuBKj!BLZ_6_z)?G)g_)6|uo9OsS8_NBnhd-7e~nezP$(hkw) zgo_@aKA(Ikt+ZW$TU67;kmkK6tn&w)6w<2#e1xP`%IDOVIWZ|iw%;~kubEm?;5FMS ztmi9LDX*E_tStg|w`dFqc}b^a`MmPq$@Og(5R(g6UwUR@YH}*vf38;iin{X(51)}q zfv2t5o8pZNRJTdk>!v)zET}Fk4xvDeFAE4HYZ@qzVNy~;W)56)?M=v3uJ+t0Y!Fi# zn(j?(u0F(DXm7^^HvI&?U1_YRR1|)FO%Y+(Kcy?uqKhA zUG53Xg*8e2e6Z0?X_hy4X!Ko)gkNP`@_>?FLqv(%E$ zy-9Q079#8ofm_rD2ErW}`v~E#O=`&}eOYsXAp}wz0I8_J2uli??a30DaK3I(OFr+$ zGHj0kr+t0k6%`oK@~R7I0=h#v^tPjzLvJr>PS8T+w;lkCiu`JT>2jP9Z#SwX-^3d< zC-WgNSr>>!1tzt`nq?B9eO1{i^6FGR^@|$nHvWQ#fLhea*>Kdst^tC-wVzt@@z*=p zehoWa>Hxl|jYL{}*16N0)?$=Waa5$2TzYRP9`R+2S%O@BdUU>9|l zC1F>bV}$Ry_G-!Jd{*;GfnfUsz$q%&PC0{IY=m{WvH@m!F&ki(mSt^Q!(UJdm^%u6 z_lTp8U@jY_mVDDL(R6{j{(_2tDeC%7Vp@6Umg?>!kV}uLB_DP%yLDZT|6ek^uk+mY zT=9J6IqKQxdDXMlv)D7s}XH2VJ{en_Meh3tZD&8Ln}z0j@5t7OuLkN-n4K zALlLSW#?(;WIJU$ zWZPrgY+Gf^vrV^U+2U=3Y~5_FZ1ruGZEl+m_9k4heq}vs-DiE(y4JebI?L*_CR>MD zds^FB8(FJcOIeMU-z`@y=PV~I2P``+8!XE#b1joC6D*@FeJq_UO)a%72|7UsIwjlUWTjc1I_6zot_V?YL47&^)4J!=u3{wqhhB1bIhR%j&hB}4{2D|>A z{-*wt{*?ZZevf{$ew98?KV6@tkJk^3oe1gohWb5QS=zq-W-d1 zQ0bX4o{oAfW$ zy3d#Xp<35Bq`#@wrKfa{YMs|gcd7P>SNe-;9Y2@;q*{l*(jBU`+bjJ+wYJ@*->KI6 zd+9f-wVEXTO0^chNWW06`E2Pn)gHbj{YHZB z2Gtr=lde;(-aFDYs?}{R{Xn%kN2RM&t36gKqFT*sQX$o9^py&zR{cxq3e~FhlfI`~ zm5b74s#R_yeMhxQ&q|l5R?#heOSSSD(nYG3y(E1@wbBQq3sfsPM>2s?6U0?c) zYIo;KpHl75Ez(J<-Ki#hLbcz=NGGWF>ka8+s{N8F9jDsQo1|k@yVYJgO0}D(r6W}P zainyZYS&+oKBC$+t8|EJR}-ZVsaE)hbdYLS7DyjZ?TdWreX4yvQhJYSCvQpzsP@Ss z>0PRws3+~G+VK+7J5)QmUfM^sBR1)6s(rLk+Do-VI_WK{9b7H#q1p%Kq&KPdUVmvf z)!uzwdV^~F+e^Eswr_*0JZS{}RI;ySeBdw*{$^vN()t+lFt)|-Yv(gJxTQ*8sMYW~Jr01!&_^z~) zYR|kNJx8_t>(UCUt1E8daoPdKXlIY7@Ue<*7Cy8I_}2Y78n%weibP8LA~$N2RHj z_y#IPwS-4dNvg%=qY_jbR{?pbHfAYuQ*Cs05WQXTCI-YS~ulDXO7$(j2Nyx+Be|TGlLS7S%FqNPeoNACP8JEp50o zgK86QNz$OWYAL0pX;e$zB0WL1q;}F&swM1_rcf=;Crzf>*t=3L)y9mJa;P@y zwviFktC`ObxD(`Hh7zqMYVzFrA(>~Xewn;t=}mrooanEq%^Aa zaZ3}a)?1P$1hl-T|3viz8r)+grBdy&B~l92dQ_9fQ?1)pDVb_rACr=(_UHvEk!qdO zqy(xx;*{d4)^VE@N3{-}rEyei_l-1`YHgpC#!#*GFVbkLwVEr9qFT#3(nzW`e^(ko zwPvHG;Z$pSTpC8T#(zsgsTMm&8bUSiZ_;3@HO!X=QLRBkX&}|=9hC-9t!{I;t502> zEv)m7)Q@Vl`$&DMR`aIRhiWwzNsm+Q!A4SVs#QBC^&;{AeL7DU_fprlu13x|u;#2{ z&$J!2Rj?*m_F9bQex|j?AC2t|%k^jUbz^dM`_$Fq|7_`pphy>Rvxp6fD4tkOP~@6& z*5#U&?{;~=73<1^u<)Y*FE%W!z^BEg`=eE9umS$J?F zcLI1(PGn+ijT8Bce8TxfKA-cQeJm$*ijKlN1>S{4j^fZx{JD~?`ty-|-hG=`UU=&| z0I%4$4)ZeSd5B?8-c(CI@Y@SmVAzb&9)QJe#=yX8PFZT=PZkm4PZsfs_olPN5Laji z#G>K~wCj51F*!Ld0ge<=<`eY@^ND(V=C_6iF}IBpb6`&rk-QJe5!esP@nN@LXJMQB3z`9} zs2t?fw4BNCd;JOdd;R(3uYJst!|v0Efn4nF)4*W@Liq0MYRM;kbt_8>6NsijDs}>) zY)KBBJ|>|1l`#MQ_I%)Nudu){@-_iru_Lbn95UzGw}GJV+rUTO`WA}}bDqY4EOySL zMGj2Y-)=~V-)_h!-m;V>hW#qBKrCv%3VHJsV)^9@zw`U8F@*iCF?{yTBN=u%{$E`` zQD@k0cvSzbexm1jPZRfN?qt`WuBEP8&OOeaa2_DrQQE%R-qd!)*3Wv?Is@(ne8JMh ze8fD;^fN@it;Utc2V(w=$&V?kTjNhxyaL6Xc9kGQK(XhnB9ogmDI+sBX>we87UU(5 zjY~+#%+Bz|s`~}QSW`M3g?i)0rzUu_y^=RAu*+QfA~J`zc3Zl;vz zrKbU;&mwc&nOAv2N?cl6QpR|Eug0h1U-`I<%#11Nnc0YK=gG*VmJQp^xWvSeFNO4p zfMbBBGKEA10D%;TP+al=Y)i|z2t zv)U^le+RK1aeYc}3Hy-9s~9?Y+9RwRutT_F??^RrB997sk;NeEdTi7{OSmBdPMO2YS>w z@;u|!lJEDpSitx_02yn}!|g4uYBBM<9Z z%`-R&y}`++|JoizKQM~)VO)xYI%bwy^69@^z|w;oegM!%&<)SCz3Q06q_D4FE&0T! zSy#3^r1uBnC=Kaa_a@=}=NYx+bDz4$TDpV3pdWDOMrTMT++mz<1pV*&YRPZH=O@`F zz=8R`(1ZvcnCEqtkl|(F-MNJN?p!|gXPGQD3@?3vI!eP!I0qo1{&S03^65YIu=H@V z!Q((5!J7@j+B}>ak>K7@4$$8z<^cUCJ6LQ8q4oxBu_4r8XCwjsU5SwWUQC4S*b_m( zy`lviaA^|YUvH=-zhfNj#{$FFm7V}BcI%4jL{u^k63$;T)soM9q+Ss3V^QN(+^dB1 zXC-CD&&8yyIBaEkVQXm*;El@0~4IfvIkv zJHwsgj)!alL)`t`J>6a09o(%TuRue09d~tiC3hLO+ii90UH4qSgP-D>>k8xyVGvA>ui77euX>-S8bPV7i?eIK7;!f z4%rUa_S$yYUbStqt%tk^%WR8m^K7$h(`-4A|6qbG(Kg05%r?N*8}cA@vbC`_vo*5S zwbg)p2<2=gY<8Q``j7PvhW0)`r$PkUyc4wT#tmwOaL-dyq%rmgSn| zisho^jO7&MQ#fpS-?GoL+p^uV8S*Nuwydx$wk)vBu}p{j3X&zwl581g8DSX&c@}zD zI$PRVT38xe>O;PTs+J0tQWmGhY|%m9go~=0oNK=Dp@!=2syP z!+P^7^D^@y^E~q`$j6Xl&N5FhCz{8Yhe2M3-sW!RPUbe|X68napP`1ivbmhOgxPL3 zLY{^@rrV|)rb5#t(>ci3aMEmm3(l{cpE-{^4>=D&eu`brSDl-j>z%8d%bbgx^PIDs)0{cZEawEs*D%I8%sIf> z+u6<83Gy~Hb2f6;b=GiJc9w(u4R)u|@sHz<J$sgkLT z$!)SiZi#!w-;KA7*Nj(;7a_;QDdP#_VdMM8eQ-zTcH?H_2IFeu3gcqq0?0Wr-8k7O z8Pkl(#&M8)Vvw_u#Cqt4$E;^j>U2emZPy8h2=;r zM_@S|%VAg!#c~LigRvZhvJIB4v22B9ODtPp*&NGeSU!wpQ!JZc*%-@M zEE{3z#j+um4X~__Wj!qGV)+o3b+D|BWi2dgVp#*r2eGV3TVp#>t%2+;tWhE>t zVp##p@>rI`vMiQmuq=&bDJ)B3SprKBmToLvSURzEU}?wFhNTrt3zlXqO;{SSG+?R6 zG6qYXETw<3{0GawvAl=nT`d2?@=q-9VEG4@zhn6umcL^83zoOB{29wzSpJ0NO)P)J z@&=aIvAl-m4_IEsvIxsUEDNx_g5~#EUdHk}EH7dCEtVIt{07SlSf0o79F}LXJcH%e zSbl}&msp<0@(V0aVfi_hpJDkamM5|N1j`dxevIXDERSJ%6w4!69>($`EDvG%A(jWR z`~b`Mv3w8916aO`<$f&R!Ezs#Z)3R^%eS!HgXNo8?#A*BEO%k~I+i=J+=1nGEMLR& zRV=q*xfRPTSZ>Dh6)ZPl`7)Lpv3v>34OqU2<$5gFVYwE|HCV33@&zncVfj3kE3teI z%N1BI$8s5#&tkb0%OzMYmLKLv!J0>V!L;irJ`Q$YAB zAp8^%ehLUb1%#gh!cPI=r-1NNK=>&j{1gy=3J5<1gr5S!PXXblfbdg5_$eU#6cBz2 z2tNgcp8~>90pX{B@KZqeDIok55Pk{>KLv!J0>V!L;irJ`Q$YABAp8^%ehLUb1%#gh z!cPI=r-1NNK=>&j{1gy=3J5<1gr5S!PXXblfbdg5_$eU#6cBz22tNgcp8~>9L3##1 zkwsYMW0{BLLM#_xIUmb;SU!#ATr8i$at@ZWv7CjaAIq6o&cJdymQP|i4a+C6oQmZX zEGJ``i)9X$*;x9pL|95#PQo$^%SifW0{O)5|)WrCSVzl zWgM2{upEo!7%WF)ISR{>SdPGQIF`e(9E#--EC*vb2+M(34#2X%EYauq&;79Mi)9}y zAIGvcmc6j-iREKh_Q0|`mff)Iie(opAH}jWmXBcB3CoUHcEGYdmhG@?i)9-uTVvS@ z%a&NSz_K}(&9HnJ%cfX1!Ll)yu~;_3(u-w7EE`~1AIo}J*2VH6EbCxd8_QZ)*2J;~ zmJecC9m{H1R>iUkmX)!50Lw~PR>ZObmgTW5hhg} z9S0mXdoSB_*2~s9mR$2;a}~JjZ;#Pp=&xTJb2X-gZVrzBM^N}7)RYAt6Vah2)o0>O z_6EErc}=@u?+KKAm(*VySeFzKXGV`$-4aJg8(&dNKJlL`SYn9KWB{?~2#sRnkO)m) zYzCo@&EQktd6K0DZ)G}AN6=dtHpUUWn~k70GOHyY`47!L2QYM66by}#Xv8jv6olziM@53;zB)_4NoMljX&{c$yW*@$iH zy`z?V=wJG>&@gDE0<`F14)=`UUQxF-A+Fn+PyF+DEO9M=K?)E*DmXGt_SO-=I!D!# z4|;1q3kpHS@cL=$e55<{YwH} z{YyUdbZXf>3SSB+c=0wtgMnx>P$c8Yjl7QLOKxP!2HRW1^X zSGmZizj`^So5V%0nA33;G@lvn1@<%^j= zfBy^13cH0z18bCa3x~^ql~?u>F>={Ud?R1p!h*y2HwwT-kAKSU^5AcJ=>vqh^Z`Ee zcPT70d}u}jv*-_v!mNHH13jeV90FZ(4j=kbYX;hGFRQB_^QjJ^`;{Rg-`Mq*tF!Y{ z=V;q%o7eiDwYR0vBANd&KVvR$+G1*BJY*bcxMj#UJgDELf6VctW2U17xaxC0k4ZX_?*Sd!}%&#u&!_6F| zUn6twytsGl+pf0Cdx+iJbcHe>qQNIysBBxhJF;{}a+aOrwv zu1&pvMVjTFbS*N++U{Q+U8qSv#G7EL_215r5VkI|#FDN?=0M>6s$dpJQjx$O!7gj0 z!pPiwecv{PU64ox0{fwMRxU3kq$`m*gc!Dw+Un%mz85%tai;ImW${L3Cf?F_0zVD+ znKDb41lD<<$*%Nmk_o1(Vg{DLG*!CzALaD<|M!Jg<~%_YOz9heZ-r7N^NqV8uy-o8 zF_Sv!yucZgQeD{H#nL&L#?>sQy9oR&suK+*Oe5VAUzZwSk$w`GcSdQKW}-h@}fE&T{G575a$!T%p1Kpv|3_{&! z2H&`)G{$Y{FNFIM#YGkw<0i-Dq$be21M(hMLgSC~L*vU!=CS5&>@SP~U}0WJ1{g-q z#8jU*Ax=sRSh<(tI_<@Goh~mC$3laZby2c%yp)*>-oyZK&*7w7^c>Fb7M?~dFoZ8= z0I=x53tsR{3Hde=;vT=LC7;~Yn98Aa{L(k8IZ@k%uV8G(Z*|#ZZxx5Mu5g$?KvdJL%Gs&up8^ni--P zPXM#9@k2?#t1vSQUSiypEp};*Ov5iA^7|Hij%XlYux>aNJYr7-3x#1iOQ>4WvU~KE6?Nj2}kqT)-DS zVr%f}l8unJ+pCs*a)X66JiL)PKpv$xQq2q!_&~PpPN3U%=R?PQ$wI@9tZaZ5y(3F8 zH+yV5ul4r?xb^pZU|l{74Bguoz3v@$c}=ieO;SrP{<42Hci2GpM$zluGCsRVC&Vp& zQAJ#ebv(=JM|95$|+qCr;Oal5z(HRwC`4z|;A3V4` ze2efue2dS2_b|h6cQ@8mi#cWVlyX0BU*r0~^|JjiUTQIO7q6CwU!p(p$n-MK{GSPYb!1_-Q<5F!v4sR zilwA9e9aw7NzKw$Us8ZOG^G0AN=pdv5QbDr@@8osvO_@j_K6P!P*44)V5rE z#7l|HA|hLie}?fdB1kO(9>NI6DcHIc&mb~JCPVIhZKwG3kU_*&7N$Ye8;A5F0>4aE zT0a_!5!^EB0Yf^0@tphkuB3kjj3nx{KFTC7$m=BiBQVUWR2lFWNq-C6l%Q4?@bpOc zMD$IqyMyu3NOwgHS=#DU?~3%7i1$ESmwG?MZ;7akfX5c{wMorLOqwiz$=%VIvLvTv z#`&~gHdkaWRnUyiA+1cx$WGT*>x@FTQCwWop8}@dLE}qU=ah6u;9#n}_@rXG@{|4$ z|N1iyA?bHm&80+m77^TiuVEZ<_iDiIW{F_KzoPjrS{4zp2ei@&(&i5>B zOMhW$pcQq1oLc!l4q3vSTwN{s?6r5X>}~vorGQ;j;4_3hj9ZsrCn}o|5{ub{P-_&6 z-^pKC67Zi86rl*gzprzcG$P>}g|KKg_G zS@gF4LJy#eiV%gOhneUR?r{~=lFwhgGs_PjQ8)05|A;EDuJ$83W+`DFvy{(VtqsfE z+F$4bW>GQ45Sxdtva8zt9Qv5lk@uUtF&f_>t?>k`G^{d64NH z(KLN%T!v7OXrz{W`pRWldYFCLfnNOVOX=((v#()02==fYeC$fcS?qTHLK|SCXpQmk z0))nh2>4KCch1macIQ;oBvgaxqZJw;e)_1`Jq-}JBP5u@L5 z*bt-d95YvU=6~JtKP-?RrpJxpxrm=06VF^=dc0WKy|Z`{|0#6e%RB`?OpjxMR{Zo> z@goNBS0FuSk&-xP5kGOx@@~^uc9S2@y6b`9=TBElzUjLTX7OQq>;-)B z(_;m{nCWp|RnmyOs{BTDX~H%FrpFDT5#p!EN+ZHfj~Bd4&=vwvdrH83zJ)jpq z)l}$1LPG?4Zk}55;X7ur@L>A7(KP-2rkZn(5c)Ys`1Bn#*A>E4^C6%YKh;!BA2QXP zJ(yt69?ZvXuUVYHRI?6Xi=S$$*!Q1m`hOq|@c+PXK)VWTuYsv%ZD@e_six9^FjLK$ zN~)%r{8UZL+ni&;VWg}D;87bX??2U?p`1*cQOwD-*6*_X5BUpg0>7xlX>?I8A4U&M z$evW3W=|I5G;6h-Wd)~44PX`T^uPz_vCAWg=8T*+fOPC>1Na@gWjxCaVXy~*S$r4_ zGpoZ1rJh!y-Toj@A9#mjbqJS$6r_#u)7QQ6p)Nl1TkloTJljJ*38V|P-qoE6?KG!ju&!R zSL=23DF=0Yd-=dk>$A3nL8CGNiyt&(VD z^?@76vW)te6EP!nKj{2nm*V&TOL@nYfZd|W*%^2bF^VP590leSsh}a)#;%{g5hEYd@s5qw)TP zb0MHw0@6{^2P-d^p64kr%?IEbJ%q-IiH zN$5l}u=yBO6#CGV6^`nAKox|(V@hr6I3f=ta3Q0cgfhPjJrgp?JAI#uAIm>J3za0KcU^ZpHDk_AxjHB$}T`F%10SY z%Q`>^?heJsJ38~RM`b~A`kWgdu-M&aJftX7R6}Jjo1n<^c5iOai?=lMg+R-R3AC5o`m{ z;zv6?4`-d^gm#@?E&0>~G_wuZ*3}xQMQ!V%-6JtGHvJ5|}8p0(4Q+ItD!{EeU6OBDAYZt0kYd-wP})jL|_AsSLfN zSyXz5vN=7ZcdTemuvawaWB1miu7>aT!+kMyj@8S~67FSZ`P{vNkCHZxO0QP9 z!;E>)rV#LFQ~2OL7qGn=zUEB;T>RHu0awFngmuZ6YRPAQj9muUZJ)sXf5&yUa}fD| z$i3V3xhvKAt8~7_9mY`erf5on;;C z9gXY2mpteez!?nbHNgyHk?l(tIi85`gTa>?Ch`Dy;qG;J7@WL_-8P zOhc=LygZPhF+)x|j|K~H9fj5ymx}KXK!Z|E{{9j6mNKz3RK0l$|8WHzlL)0t}~C!Z-*~Hv#p~8Ee3`hq?;z_XgL)F8fdy z0RwMHg_`dvdQ`v*OsiBJVW_i!aEG>*fE{sne?&mIBd9*c`Gh(N?I@vcBh*pA=Q5~$ zw3}dyb`UUt&>D%W2DKM3&TA?O^b&cvYA3Xl1iMF2TX$!jD=-BR`T)bs_|d}xYGl4P z@DYGXUBK9~eFq45=|gHHOJCeY`$waNfuN_{!hQmFR)w^XnVsNf_7%`=Ln_5<7hGK* z0Z%c|P4Ievjx@4O+X%2JtuMSM4Yd|Jqab}$Zd@y&ABs@#6>14{y=ziLR2QEmW7 z1BK3E!g;z-3!zVs45sqai~cTk68~SQ^9**ss3o5|N3$mYT(2X5T9jj+p~heA0PUxr z5ZX^a;nQZ%WnF6EdL0h5q8#(VwBFpL_>|1diSmbu;C`Zt1HV5y?anJ zdw06xWau6PqS-wHli0xf z_~CiN{o#2&clsl2_kizWf8dV7caf|K=?aa|9#m4O94sbg{$3A0`UD?~4m(Nu0J^B1Bq8X5H79|7 z_l#Qdp;L#l&@fAV9H65xOQkUv!nr?JE&04Dl~`UFta}4*6s98D$PHoL_m5ignaAr` zX4psB3z$XiqhvY;iT@DBx1U!_K5LRDs|DD%XLRh#ym^5UdT(RGytgr*IZ>0e4%PsV z0do}A0BS6XQ0_UZmVDZTS!{2B8`*mRt*Fagncl!gv!Yyi%P{8%I{70`n*{o z_<8@@NMHQd#>ZbWh&4Y9rI~;)>QfaKKhS0Jekvf$KNawq7i+Flhjm2;FpFAOgfM4i zqm;nte>06B-%R5pKU14EGbEc#2V_ynCPR?Z(fHO)f_r%0jeiOIjeq&<`S)0M=;3M6 z?BVj#b9{D2Xb-n*gIrNVmEA6oJ3`6d!&;L)PvvvZMlh)J7J3oIUWG7L_H;MP>QS^B-WD z;WbSG=BT}-!7G0dwD|bdp5oH9V_$1I`xX4VZSA#jWWt z91FOQh{Yv4u!uRoR#w$tkL8>7i8(=>V+3+iKR}?%eyJpw{j!(@vs3a}&bt1>(ZJbD zkUc4Ob@h1pS&O zzffTRihyK1A#+S$(qtdpTb-J~&U;XffXp~ys!mHnspB;(3zRKjYfDJYu#F!jNU8DI z+kkumGNpx9neNj#2@n#{Q0BcLaUmQOR|CvwXf&$Sgogj`pE(h5z93BBkw3>sipEQc z!uaFRBmr6dLR%T?NkdrzHYCt$SVLV1CO~97Z z5Zea%deB4x=>kJ54ffKY3DM}as(%HgMx!GIdqz-7G&)ikp9UH);3Z{OZmc%~B@1|x zY-Jih0!k9xG}Z%v5(QkB4n$7;0XkEUP`xi3zF_cGv<%dbtG zM^N(p9NRQ^Gd%1slJ990wbzzTj4(4@V^i*$B;c7}vzUPAmakc7QcHi48Mwtqfr7Z< zRU1#)YmiGl^J^4yspsYuEPE4wkqOvEZ3GRnxf&{@)YZ>nk63>7bNrt2ie?{tbAOQ$ zs71N>??bJ%cQq2&&#zWYV1H9%*4~Z%MFt=jwVyJGoT$|MoL^-(F?W^Sd~?67fo|q6 z(gU=pV+Y}(wbriOoq$*F&IjLEnYDI9e^Cs8i@KhMg3AYeeVJLQ3973%zmn3iD;3kR zH~hu|!|SL6VDYb`3`|GB0CmMd#LN{3@y-0A=6*#80L=hu@gEzRS{*|I%;hT)=JJ*J z%A);1eyr^p%6k|Zh$USo|8^pm4W@5@b1OU(?WcMc@<&VhXT=U-vz;r+}7dhvs{VteiTY5$He z+rQ&8uhh&|;bPMqU>0?;X-Izw8+;_-HnO=e-&V}#!spnn-16?_Y-oU}`$5ArAT)$Y z_^l)w9e*iHijq!0MT50FZy2{S;NmyiaSm+*Vea?KtU*r|sAT>KhM1rG|R z5@zFNwdAueYt0y4j{jHFH`W=RHaPWbJ@Y&z-0R#8T?br4oIg09a5^BrpBM7`^|YO{ zC0cJ==U7WyHd(ypx6F^3PMJmYE>pjuaC0 z&5K4y3K#WVDD)*IPIlS9ga_RP0wNxCM4*+aE;uw_XxAYX20{pEo`4)~LCvG{N^H=l zg?85axb4wg0Rg$7cB;-Y+{&i}MAYw7U!dpA5s;`Zs7|6{CpVfcUH;mCCE$8G zS|#gPMt-3kCd4I-W(s}ngPgf&hR`8Yu1)DF^1@)cfZ#NJY5@l-dQzwfgIu3zn$Yea z&S{CB5c(}rs#J$D`N>Vy>_v~v9v%ARlody)qYzDrM!lgfJ~UbHZlJ3gvr(_p*(=Jc zf7@!;JFc$IW6s{T+Sc9H_Llc81I=e3|Nl+XWRu>w&{)dwf}y7VRegh)jc_s`)qcZ1 z+3s<#aW{`?sryJb8vY%5cfY;9ob?&Xnh7R<*Z=lLmx-CawA75)32`}bv4Jc_`1~9^ zw49kxPqm1=3T!=r{5<5Go_cGd{ISa!3pG}b$bKibMra-EbwD^}X}pw~3p>8#$~r)0 z7JrOsR?L6fj%wnFz}7O_NTqMy_mc1Iwt!)rX7cAoo+2&*Z_bNVrupPVMz&Y-rg;&h zEQ2c?zz*3D0DwLsV^D}0Q~<>Y2`O=DX-OG4qn_`sPG|c!GLxH3Uq+IT?(55j2aIBs zQ7A6kmjXx6(}_)vIi#!u>26E?e-bIcw!=_d>OQMrPp}R4p9` z@tjrpUaC_a-%6b2dB%qKOdt?bYRFHvGDTn`*4CCW`L50%~!Q>ij+C~pwtPl5NxhcAlw z11kMNfG32!vaCD83!8Gu)gEM+LSIAGMG^TnXt( zoHH0IzZ97_RVa$Q=6x}DO7tR zGVP3$n9okg@Sl^KlnaKH7G=Y?&R!-W_b`NfVoCRv$0VpK`y5nMDk2Nckcw#UQC?HU z`<%TG>hwh9UE$QJ_Sm4fRQ3x{xl2rg@7Hg$pMW}T5pf`dG?;#6h>_)IIs*FZnTXg| zJMhuERO3P-hm7%F&3*8tpz^N-ETYtzp*l59j`If3)TG-`_o>Ky%r)bnTDQ_{?EQv~ zfD@DC>9F)U)Os>9(N4|qpqZ7@>9@2KmUR*tj-X#vjQF}v+gfO0PGzX4d_-J)A^n#$ z63>v-<-a^HlLtWCvB*sJHAba_lBP~|@+)OPy+;Jp8-D5=$R{E_F0a-v8Q#};-L6fpm97P@X|4>{IM)DI7gq~cT~{TS)A^6{ zmh-anwDYiYuXC$&wR4eumwlssg?*lVsy)p<#@^4~+1|`v$6mp1x81Ydv|X~DvK_MR zv2C`kvgO&P+p=u&wn4UTwpOm26 z?W~Qg)vcwhM$7M(tCn+?6P5#(ot6!jWtO>?$(9M0QI+H}~o*R<8N+O)_t(FwZd6kY*TT=x69`XlAHms9><`@9A&q zFX>O|59#;lH|tmF^Yqj8S^9YWAbmG|D}8-^W!QeL{J0Dja!>K1MqPaMsn+mgUp=Zd z7~!i+wR%T<4^ge|5MLdt)%ns_n`*TO`f5?F=4ZZ|RD1B6uLjksC;A?wTGeb{b*fdq z=&MGxO0#@bsb+Whs!+|^*;kor=DofLsAg*7t3)-!HeW@m>FfI{P))bqS3aQS|69XX zj%t6$`N~r5?nz%6s{Pf;SDI>fUiX!v+8>pCC8_q?7+(ph{W8Mmq1w+~eQv7#bjjzU z+RZedlWP0)=m)CpU4pJs?XB{th-z=Xf(og&+kpzGwrf7RLbaW1(f3r_;Y63I_F7Z) z9o4o?N0+F!r3igXwavrPMXGIDiN2xQ#=p@8s=YKDou}H1f1`6$Tc3x{Qf*y%bcSkc zW}>gDwz@L^bL@SzW>HeHVnQf=BQ^a0hTo<;9dZOSP09@TPRK?kUo(+IswHQz^QKhkqFq!=cmuso zwfOdEC)LJ%hIUYG>{zs&YNKzX*Qhqik6xwPNGIAxwc+E?R;mr%iMCK}NPV=KYJ=vY zSEx3y9NI*+{u|NDRO?pJ>DN}pjxjh=tZjaoQc*`t;a63j%wYGptV%% zIsmPq+M|2XYN~bafL@?lr!2IJY8~#P=c(5I1+jTTd_@o@AE)f&Br7E#SR0_9V!!JjCPYW3%%g;c9s zfEG~gp+0Cn)oPDL^QczyU-UH9YV<{OsaE|QdWve*($E~LRoRVZQ>}7$G>dAL&LKb5 zDh@(3saC!cnnAU)ThMf>mHrexNwrcF(KM=+bf71w=9z=0QqA=tnnE?_Ks1?Z_U}+G z)ohbd4%Ms{lub4B66B+r@iIbGGqgn#)nZc7q<{tqfl(IKekwqjRJ)mmGN^XrUzAR@ z>yuF$)vh_wM5d>{R<FIxUyns&srKa$ zXbja(yU}Q>o!X8@QSI{%Xe8A>{REAm+9!9>aH^fihm+Xq+&k~%ifAa+j=h40Q0-_V zG?;3KkD)PfXdN6}+cdvh%6LA5syq3%@M)fsi8+Rpu`E7f*%MqQ}( z+7$FC)wb0@ovF6vAbNyqo5!I}RNHh9b)?$Mi%|!vy@XJEs%@~Nc2rxRiP}{qgGT~!SJwY;jxOSJ{>qK5MM|FXLMI?rS76|S#c4>-p=w%UKPH@5j8)1S-I z$GpgN!BpKi&ae)$1A1dJ;aC6H{P-LBi>ko63sJ``RY$qve~Zsfn3yDcugNist^?GP zf863j&6PK;{Y8}lS^S|i#bFt`*Mv|%x>qgv^dI<{!ye9A4*efuRWC3DT}ao%HlJ>r@0cLoxi9eFpEEwrZR`ih)KXZked+m zJKW_r;6Pp0=xzN)6`%p)52XbfaKA%o?O!16X#WDA|6LEu5BWFB1HbsQT?&8ji6+9_ zj@;9i->#T@`ri4DW%v4v$^pCh3s?f|vJ;&Uw^5Qov?(ST#J(?BV(2YpquE=+C440O zt(76BbumNC+uyMKZTv-LfM0yxd)4BhVR?ez^0->^JNw>aEIy2or2#)`Bc!~mfOeS{ zB(HgXiwS(@x3;j%FbOCH%%Ua%G;*VuTnQ%=^EP{3E&0fMUS^SDOeqP-Q5#c&k3GM@ z<6>@jc;gAS*R=8%xdC1L1uQCh@F6b(-{?KHc}5mVEXdXIXp0Yw7^@sC|gS99tvU_2;W4AAkEs79R$6 zJK&2S)Nwc-Pt@sms4lq(EWd6s7lFMtgGFxYFR}r$_$($X zzv~_>3G1NZhOb(unx1lV!mzeVS3j1gR!Myf&P1aY|PWTkN?*= z0JI=}cwZkD_`Yg3V5TRfLjrx2lA7g3zBpet?LEnB$YV%e!+#7HHFvVr^cOV+c2Re5 zXm;NbzNDIJ$>+SF$sq>gcoX0hHI7qGI8UWonA$es4Z@u82A}!7<~o)d{-Vaf+)+>> zAi@kszyfQZ`1S-dzC9oF+->Gf^w;$l#R8_NYeNExeVf>J^liRvzn;R9 zLK?@0Kq@MYBeAWrX+Dg3NBIf#C_f+iE6oHC%-cY?d5I@BVBV4BBE$TV#av|g<-0Mx4A$@x15@IGa(v>G8LWlt`HN};v8W`IDzSVVTQ+c@3-{kh zX!~#E(|)4yy+aqS6@@OW(t4G17zDLn9kt{mpU~VH3MpP|0xG5jq{C_V$R1*iqY$q zYM10;v|_K;h{z!+?Fk}s+CvTFCrDGWd|vtQ;QN5~M&y7Ar#?tMl$p^~t?n%WH*$~( zy&9fS7I$b*)XtzrBMqW2DKxB$Rtn9mq!=_fAp8GHib(ZrpG zy;1CF6u6t|KfaQQ)GAN%<>6&lMDmhohZkBykdq9(KF$PguE<_1L~0}MEwod>y+wfv z0*)!PBQob2HK!?QHQJuHJt8L=!#$yZGYGvV>}3k)#zC(NYf``ggSH84QaINM+8U8_ z%-W}NN?D+1mrO-xCC3V9yS|cE{LdeFd(5=d7bu{V?-DHej5HM>CX|K9H7_AbT zcwG6qg}rS8PV~VNy_{~L&eIFx|2JGMoqmY_m$VPJZL}6xV=YgbPnav4B;!7##n4Ot zd`w|XbNFR3KYj=yJqErLQ4u=g1qe*ah_htgXtm@!P41=#d3kyW^zyKzUUL0mz?D7s zZvs5`Z$9u}UKSWUY25{S(lo$I&JY?acuFG3Pf2{_Kdme>L^rwtvZ&}rIOKqlXa7uy zXaCG6{^NU=81|oZ1!7VA#Wcj}VG_|0=2`J-$!Gul5X%l7q)W6q2$QIdpw3h_T+J+I z!_{xku*h(u=c9lu>PAnExr1~55bha1wd9-nmoqFk40D}#L?1uoyBS0!Dz(FjmOg7ZKMud0TDz)VE-qQ34aK3i}UQq!KEiXtPYQc5|7~?tuu-Gw9F)&T#L`bKMQcFJZk3}po1Q7bDsVB6#uc#%T z`i5q2ChUf757eS|!-k_y&rF20kV%PZpn+iLDCc-`iaEz~U2{b$YzS%x_@XuhY4N=& z-Z(9^?;`^5`-pGzYeu%G!0_A_pv4Z)O5e@`=&U$|wA?6(aHAwX_f^e>%dpM94RDLv zX0I`}{1umy5;7r&=oD{4Cb{6AKu=N*XinP8hcDX48XZ34tpQ$C#8eCKO>8dzMPLlf zYD>_w+VYVLN3+NF2oqUONcSLl{ag;&X_OE4!WN24aR zf!ywQpkEg9`P;b_GR(KwAzvb@f`ob0GyzQJ~ zTVShdeZ%^grNDwLX7gfmEz?`3-o~p&IU&l+hA#SZ`gFY+?gw1sXktHXA7%S1=9!q< zx_$OiI>rYkz(+-fAb4m@H7GVRH#G$Q?KoeOH!UtcDNSC)qO$`0qMEAI!%FDP|4_rlaShs>uv02@TtGyW)EV$6qGQ5FBqh!e@C2fx!rmmM zD#nM0jtB@GvbJOH_&|pRYy;8M70z#lJ`!zC#^Z$!3CI+!X=1Ri3VkT7^9Q_4=%BFS zHpoAOJ`nbrsWqvd9rV7ip089zeKP1h0nugBE!4U+Yaet#z}6>HpZtB4KU-f3>k{}2 zOh!Ze1^!Z4m%uf#gW+jmT>@9dCL>2*2#7+`N92`kGXjYz?8*7=DJePuMq9t(Ll*(A%O1ORb~m|L`Vp z690c&=jrBt9?t)FaV~Rw=V)f1X**%7WKFfaZ7FFUWZG!_#n{3yPk&ZlCni<*wwUn$ zfAL?HgHvM#Iu6a~`aQA#9 zo0Z%%oB6qCR+M^xicMOeI?;y7#1zo~Npw}pe4%f`&!`n}?T^lm73;}pinOKOil{FIK zTwPf$`JA>FSx)E_gN1jBpp_QkT$Q4hd|s>O69RADAmA1I)&;NE2BbLmQc=F$}w zO~Me^oG}o9#cs|BS@jX(=ccJ8-^AtxY?pxKJOhAORB|5Lb%WN9gmr~ME&0r*sX@&B zqr|LPffCkblhu;XY&f}=!8Hny{wjeSc4{;3{2hn0<74n8}7!M z01QE0QbjHK$ok%_ePL+p1IS{(cNm%aKM3bDuc{@VHzt#JRbAM4!fK3v#Qz6g;@W6YY9YgcKBINVG;*;NF$1;-t|B%kp&%Mrd)79LW z?RXdNmFr+zU_EZNL;nAK(`Tl##*v0qkp0gaBk2zP7uV@g_;o*YY+qzMcJTGq%1zV6 z6%|-J9a}&wery5P;wu`z#`YCRL5qMkf+=XZwBg+VM{5xDqc!;GvHMwc*sCQ0dIa}s z@zH5~gwP&VQc)e|r=nWXh~47ihx9U&fI5QdW%$(U`x)pbAN3~qANA%N+Z)Fk8&dyg z0XB-YUt5!o3;0u`${#mAHNl(hmAq+z zTe%7MKIOE{KK^N&6*Yfl`wpz$Q-D8$t9O3inc&U!(wwz>mk{>7OZYagk;F2?5I-K6 zqc+47Z=ZIYd`t0BzEz%2{-B8^@8mB^2J$DO)!PZVd`Ll#Z7_SDh}qwKMJ@S_sJ4}D z1e~!*f<{E}j0L~Tgbp>k9fW(ggU?;H56ca&Y9eq)ZK#RM$jq3Mo|%n8?7mA$PrqwE zpTDx^%tAANQ3CKM2=6>`iHY|aBX_PPhTplC5B@+C*6`qjjR$bCPFN-M5#$Bfp(N|w z!B5t^qWt4Qz;V$64oc+yT2o@-*P8MzT+YST&31^tVjm7ZAlL3c0LcdlHQ)A^#akz==`v;9MRU)y)K@zx)$xt4pD zrz|DRtIZFZcA7dFKQ<;9e$+RJ*%#AE_nB@i{9|-0mb@V(GAT^%Gbn}GtNK@DHirC1 z70P?u{)|lSJAQrPCQ9f|G)&9xTm2(4TXXqM4W198--YdFQr@AkO8|6^c4O)P&gl}N zPmuV=nkK{PQFfYuev8cMh5PiIfJYAf>NCND{lA_2j$2Q#cLe<+bi7e^zR|Tcx-Imr zSL$Q@SLo-+bwPoCibf|2^7f#cks0Io4GrPs4y}cy!i&!bmM|(bf$1CW^_d|!J1c;sl%;x(f6V!Vu4jEx-7b?!1@w>C+uiU z(8>^95?+(CH5z>znXg!wW1VW7E;C_TD=_s^V+>-)!$o7m+3%WC^`XZvrA9 zO{8ra38azCgd%ORfCwR?0xBXR0yeN9A4EhzKtx2OiGYZxm;^;cMG?gB*_nHH=I(AL z&+~jT_w&4d&o6(R%fZOJ=iIq-XU;iuuC#LpYO^dIIrl3GHPvZsUujH9B+flkHjCzx zjR~)*(Ejx_jsIUZ_%8D>L`g73Hf}v2W?FcD!$?Q?Squ?DE~F9DC%B zoN^b|SFd9JzW?z2cLob>z>lT7O;vtwMZ`8yl>EYr>Q&r>KAIlH2Mevx1Nku;wFiFK zPlxjezE`s8zONx>?)?UDbzrvW$xPNtVdig@idWx?D_$+@mB%x;3Kp7yS$<$cv2*kj z`i=6*sBgrdj9S+7E}px2u+RkDWmp!dgoR=3MCWtW=%7AVO*}w)G~l7Z*hXE9O`t;) zVr1Io*_xF5Y)vtDcOTE)G*}o1++`Td5E)yOihE`%1wJ!X4BYi958N_XXaHdOiAW`- z8~0-E%#)1 zih8oU7`1aZ9u*R_X8~#%CTN#1j6=z;k*~oM${CpxbH&J=TJp#cMw|)A@}Iou{M_Tp z5I$bY5bju+2ksF3;Q;{7&|^4=a&(U>A22>D{($ka_Mh0@!u@~8& z&7%CD%@Xsssmb%hV414tVBunf6!(y_N}@&H@@zDzNDY?B{U5{wU) zl3?6YbKViyu`cY?#~c-7qjo=VQN4$MMlEW%E6b$lfWZD?+y{G#je%$8bg5-0M=K7|I?{ zEl`Kb>C&3wH$^_FVK}vKv3#eV$KX_~D&kw?y`RR)pTD)ZVRx148E+o0mPMJ_#V zXUwMrIrX@mp{99n339}m+H-RfP14tgVl)WJy_Wd6e3e>~d__RvEwHB(0!q!DFBP$jA3RB1FECPo#dW|yhW zCFka*(e-2nsY6F;PhH)G7O>@$Ea0M(HG{)?5*o?9DfRUqTC}poP43@PAM{XT>M}L= z2JE)14x`k2ruD3lVw?YmQmo|+9BzA+kdrl)enA6Ok-B&z6WR1AKNG4<>;JVi__}%* zd5(K-b&rDh|7B+f$Ak7m_KLQV*0q+OEFH}YO<$Vo8}s5e8?G7J8VtcM!NOYL@t7*j zpPB@__=EsFSn*0;9sETyO3O(02N23hOTZ|6+%doUS>pJBtJv|8bQ|aR2(}Ft)`Tv| zJL4PGg~Tj4rD4^4^RAt?MjemqpR9A5yPk^x>LG5Ats+0=oSC8+G%9 z0tkne#T53hZt7JGJ?s>3?-s$r3IHuXPO3tOcYKugPbI_R&r&ih?tO=+hPk9XP)nRk zw4;REH&X0Blw_wrN=bGa`W%l9ukvz$E%8;Z#a6d#l==5@>Qy{IhG;5V0JBe5W+gU3 zS$`d^Ud7CVJMnhz94zz#bFQ=&BQ%O6( zTnUu<=X2^+%zn3~3=KS+ZeZ8#*;LC~geSsF=@k1?x)^)lQQqY6o_7JZ#1)nH+0>Nn z{z)lc`jbhFJV5iwVHoC4J%@SB$Pcyk#i8m|+=2e%IGcy-|Mm6G_w4uB-9udk&ZADZ zV}O0J?JHYdYpP|F`I`AI(^B~2U%j{~|10bNH3}BChMQ1^r6MDC4s1V6eTu};`P~<* zSFyn#&=d=WLEcL0AlJb9(=wBir>W0nepgy%2Cib{8Jg@lSfI27WO)k|Ei!}&aYk}x zxHeIKm&Vl4T^ft2r&r`gb`a8hs(%c{c}cd6T!6 zJKCStF^yt(OcP`0UE#4|`yLP2^0w~`n|h_ggSx%K+rAWD%qKntVNf^IX;3R(bnT1}Gb+FJ6)bc71MOxV(^)$Bpf`YgFLJXe!JP!_=%BBD=Z&Mis9^-** z(Tk$D=p{za(RfYT1Pku~ba_S2qR^wC$@m?VJbs6me2V564Lp-gfLxDflDg@`&tx;j z(#=Y-boNAkkaP$ZHU?gKY1+)vN>~Bsq{nb-H~oZKyXhxlYiIT6>0vF{2b`(R-M=!U!!s8QXB3EyZ09Yl>ri0{E<&1)25JM{rx$JkCK%iHb$~xhzh^f&6KBN0zrC2^-(D=npE!cY2lL;qulZ?7 zkLWjTZR*R-ubm|3Pq~NZhjm$P;MZearVRS1by-bJ4PO(B!IQgi;I#f0 z<9y$8-)-J?-o~CSp3d$M-FLaZbd80207;G_2Rs_~C+szCui83UKetY>T(ZozlsCU( zZfC3*_d;9?!^b(fq5S`{`H1*`yV6M66ig^_-ycdtgT)Q%ASES>%?&iaF0^MSpRq^n zrKBoGw5JZGP#^=flTyPcqD8hgCvCQslS0S^Be|eDx=l`w7T?tvSQvB-CJYDJQ*HgJIVbikE!zBAiC3 zndE0qX^$T-eknQDk;aS|GEF7Ff0TY|M$H|PM@`r{f|^J%u?{q?}KR>UXUDJE|{vc2c{nM3+!K zDW|}q`Wn4wMs=rIVAm^sbVcoUQ5}7{9KBCPw@ZE%C^wgX71W+-foyN-R)!lMo#l;c zNq!G0{najAYU=a!#>%WlHOi*WV8nzK;C3i9CmL0!@&Bg{zP{eYkpExHJ;k-j`J1za zW14-d?HZi?pK94={?**lgp7NP-ne@WPnUegzfAv25TY)3fk#DN)FlOHl4Shw5d+wB zCt^){e&7sssRYi5T`EtcaxRt7$%1}BE-%y-MV^$Lot`ya6EmMczigX7VVW3y=`bE0 ze7Ai8U7qhY3Oxa*r6+)PrZt%A8*D}Lzt@%Q0o!qqRCoe-m&W_@7Q%>-X-_* zyb$K<4ZM1Uxs>Fx*kP_Qeo8;aFQ(7e6v%-vS1+K~Bg~~Htdgt>Y^H}nW|Dcy(}<{CMH!jGIFhF_=& zw?LSyJHYD^=2GEH408>?L3=R#hPVfhY7&VdV$ltHphv(+=|S}3mvRqFRtq4N8Tr`&zUi@9fO-l?$XYYW`+_Iwf6W{)K!@1^YddX=*0 zn>CHMI85hlfLxF1oLD^UzGmP(=>dlPo~0aMm^qdMC-MKdKMbZ1Oe2k_eUJIP-e7IScBs9*zWaD)_(WkiEv{|#w!xMcsGGGt=C9#KarBS$-Vh3=#7*(g$Ca}l?Z zIkU)p942K_VQngb|9hnbOf=1epTW?r8!9C-u5B;;K!h3`B6*e}$p)JFbFh@K8|z|H z*3?YMp-l3#5fkd@JyL?XT(imP$)x%W8YFpEQ$p41)E(;F-I8B~Y8HUzMh=v0Q5t^< zb#H)Viz<;G-lF{_&uL1NnrHDY$#+p{Q~O->lRU#Ijj9fP)K|)=VJ|`Y0uGIuK9Z9v zlvjPE6CL%IoK&H-8!M@zm+YhprR@?u*QlqI**)_1`XhYKsE0nwx|m57-6co-6`M!< zc~LjXNe)WOQ65^O%9}^R8sywF_4(bssuh%fqJAKsv!1Ay{0)O45e4b0k6DrF&u9I z_RD!`Ijo*g{yh5K6}XC-UtQ0+bb?S0VJtAqD~CWlGE>syr{LtA=`f6_VdoxGuVUDj zU*}j#siDR;4huv!68UNHmO%J_nPB8 zH`K`(0o?NHWJGXt{!EIC+o@ME_6wT$7d()|0b7p;l0*u^8&78MTv}T%KlhLre6{8) zWDuMg2H^67GZFS?k0T?`aZr=zIK<@7ui!@tyb$jNa(ORAMoztn6f*k>^(uy4mBYhA z#BnIV%8NK^V8c&i_+iW}q|}*(V(RBQ@YL`y4gqRC9>$QPF+8Zl*co{gJ0nkwy|M|9 z4RhaMz}92#i}H_B-gISInqJDX^qJpzZpi(*2e{?sez8Fk+sjJfC%vRz#YTVnV;&xs ze1ia9-X4I1SADgVGmX~g%unkk=3SwQro)VVH}L8)V@G>@Dfq;r>QxNBTmueEsDS{k z#}X=*-P3Nh}U7Cf#$SeOI2 z!=()Y4mTHN<Qzji6&9sbO)D0o3vq2eGOBNjM`rJhGqu zfTBPBff#*z*Fl{F%`6p#1Fgq_$ zj@T_I<%r#;FL-K*qXd9jUL1uR9!Y*?5mjMw>aL@58iwy~AL^q8rN@kQS`vC?w8yhT>D)^oL@O7JN|Gi za8$Lgwa44G+4@_*fG-kXw=A(VFz+^xGyQ686}L04zu~lDa@aQzosuOb{Y=^LlSoG* z&dEv6OiZIG=MPBvR;#AHEXZ)rQJR|}<@=2>oAZ-Tg@hh1G+j!POzc*Z{W#R*H2L>2 z3lbqR;R67qi&Ld^F}&c3SCVo#cN!WkB^4*CNfzJ=*;TjGCQ_;&YKKe`eFXCoE#T`b z>!LAAQ`ELZNIab4FxKy#EMgNtqU-np8bMC{xND6}vsvXM-~IX;kBFLFrNw^rL#p`$^Db zeeR~};Xsq5ELNiWsQ4yOnm#5CzwttoXsYb_Cej~(ChF5mekYGoq-4cM-AHczPZmkZ zQcjaaH5=YNqa@jHDz@)MiLxI??T!^CNIAX98I$fcQ9yRTxKR>%0w>6R|EdYsXuOnq z-kb&bRB1F$$_Y_5Zy2T(lH`oWN->|>440ma#z<)?JR2)pp3soEKeYcpXWD7-UGaVA zJK@{!+va=Cx5`)Go99Em6yGRce_v-`Ghc0A1)te_)m!L2^|>4=HBPt>VCz&(w*;o%emIM%(=ih!I&I&L^FInFtbIQBTU zI5s$*aV&Doc4Rve9K#%a9PJ%V9Mv6OhrxaY&MKU+@3(KWzh++rRSM?Wkv+ve%HH4J z+1|`v+g`zLwq3Oq+D_RH+IHC9u&uE@X?w&r%{Iw4#x}^-&DPRZ&sN1|xBg}Q(R$W; z*t*-g*}BfU!n)8p)0%0WU>$1hWo>J1WUXd(TW(q|Th3dKS@v1BT3)fNwB%dnT5>E& zmJybImX4ODmYSAw7Nhw$^9A!s^8xdA^G5S(^HTFe<~(z%d9-<;xr@2ExsJJ#*=qXJ zRBSq9I%L}Ep6kwWC%H$s`?)*1o4RYd%ejrN-&_}5CtU|z+g%%7t6fW754rMOsjktk zfvzsD=B_%fN|2@Tr?c33#(BuO)7#DTmT9eNnQ4J(hAG`N&NSH6!_?Z;z*N=bG~O^? zGM+OYf%=VGj2n#47#A658?%iG#$m=j#`eZ0#_C3|>b3EhY&3McWWzk{V%qu!*vYh) z4qyk<)}~-P(_S=U8`ECM!d9lO_F)UtRt>>srmg%5o0#_OIBaCv(|_SOrmc7e8<@7- zh5ljMQ|r-9rajpg{mrzc$I%U@Jw63pXIgRkVj`joY9Pnbzg_~3nO1is`haP-UqU;WR(m0OpJ_FJMcbKHBOkrTwCXj`Hl|g39lgu6TYI6cOuOX> z`WMrx1ke_yRXTv)VOquJXfxBwe}vvVJ-jWn`i^m{%(fWGwpgEw2o=lYN3~ycJ&-u z%e3EHqZgU>>n&&v(|+lLUSQhKRvzO6wrhQcfEo0iL1oRZsPV7KWGVOSG^aRt6zJiuA?MP$v zIMWWVK?O`Zv=}X6+NW-m&$Lf^pv6r4_K*6Jw8v@O%nT&8Wlismrw?U`sc z)82d=&0^Xcel(M58~30GnD+VvG=pic8PIg5z0wm+W7>vq(Nw0bAB^&t_Ruo#VI+Vq|1KBi4;gGMneZxb5H zG~5o2U|Q}WG@NNU4m6Bu*-xN*nU-0IhB7T94-H{jdIdC?X_H<;_b@H38ydv4iAT}h zOiQ^74P;u<88jfQEt$RvU1ZwSQ>d6}d8w#~Y1obmnU=d2{lK)GCg=jwviG9znFgP0 z`;KYQqi>lu`D=8ZX_M|o-!Lt;5S?S%#2oZB(~?i4vrJ2xioRl6Vg+=DX@QOCG}9(@ zL8q8D?l}6AX=78-Nv7R@34Ot|(S6Ygrj7a-9cS9eCg>Q`hChLhGHqxbbcAVx??9h3 zZBPL^%(Q`jqtBQ&;6ZeVY5k4pQ>OJBjt(-d&rI}5Sc4>H)SqdAGw3d+O_+xIF>SmL z^<~=Fb*K;1#`sZhrj6cdv%b$*3FChMq!QnKmQ=bz#~) zC(xZt8x)T^Gi~6TaN1g3U+4G#8+BybT?xWP!rv23oRb<+qZ=woJ`=c5v&$Qpip>j<7 zbu{uZ?U&xj%e0@*Ax|j(zp~+7gYO>i)1GsldhRT!`Db?abUbYT%wEoRuXQQxb!(Z^ zOdE_Bj4k63{ObRXAE>fl38^B&>~o5fey$^L5tY|HgI-qp=RH)MQrv{FYwgO zgGFYbmX|*qMV*avQ^TWu`!x!^{hAp1OU+3Nm|si)t>gTXkvp+Ni>UeKy$2}$dk=`| zPtN5{4kH~rl6sExP#AV1&WwIk-(5sI@a`gU2folG6Sof*#X$$;rQ}A9nUutgX!xzw zDg4&zV)zr~dFyu!78w9u-e&=#;r)p)(?kuPEy@RMwv_S#n`4^N8<2!K2k>>AWk~6& z@B_Q~DmD7%t74-c)fB;j55mj_Y8@ZgKz3$sw9Vh1N$KC7DW*U2C_iN2gD|szUdLBc z0A5R({umv2^KIIJH{TX_;B(El7~qh|Oz42TNuJM+OAlmD#Bh9zy_w!nKEv~dUkv@3 z=7cni^arGlbRJrhT1!p5agTZxQy$erTJ3!*9_`a%zm&U&km<5rvbaXQNHenqAdkoubgFBU&>jQ{rszk*8eXwm|irs zh6wR+-@`tS_c?Dp&+DF+?rrV?uG6jw&hMOgj+>509Uh3S*S4**HMPEL?FD{;N#^V3 z$IQ3J6~^Vp84Zj6XO01u1S2Jbo-H@X83A>f0a>XNLo+aXMoQ*XM5|P#NzqSB$)Swh zV7Qknq=!gNT@(cDP-29TGuBl z6LtrhmY3+$GMbu}o|dI)IbZTvQu-VoON*scV2-jeN}h%?peRD3rn8HrlopTCIDCaC zZKB5AgdUUp5XA~%poP(gG|S-48P(z3h~NWyR7!eqjCRQiZ-G9yH8+OCAI+EYg@EXu zM!V|KBl)hE1Ip(kc#0nh1@^bv{yFlH~6}EAMot;Slqo`i=3Z3 zZ*xqxZ?PL}{j5(}PFd=jCz>`He=)X;3&OAdulxzN4i?pt>gQqumN*i~l11HLQwPkC z_0_A`WAumS3j+`rttr*d6$u{5f!#XuJ{K!r>MSnhOPyDr;Qd@}f<-leT3#Ki2x_+a zXXJ&SQhOJEDz^9U(|K|Tj#dY9Jz_0npfGanXu0qYrN8ixnEtmrdHPntqT7I8UV)_u zyQ@29X7%sWDEIeiV(woZJa@ZbQ8nO}=Rz-mTWj-g&r)mo#;_;K8f{$a*}OA!IhIfXj#SepN-iin)KP!HhYyoQ1wULyv-P?HDm6fE)q_!J%H>k_@B zl>3lUCG^l@G5`0P$s72+`tnEnS}FghZuKhW|E?)-e|SPn1?mU9;$7=qRkkN1ZH@VH`ANyO@L|wBfNvX{k^@s zUA*m~u0T_718;3_HE$)a*K7A0JvTg8J(oSjp6{T}z)8;$&q2>V&rZ)as5h|Dv%#~* zv(mH7Qvh`b9`elgO!MS;(mg3qe_*s{m}iiupQneXGt?ny?rGww=c(zb>Z#yyd#tV* zF67FD)Ab3iF|HA=!LI(UUU163y{o0GsjGpjwyPSPw)eX1E~E2?^Q!YQoVx$cdDeN- zdBl0pxzD-Nxy`xRxzV}7xyHE?>KGI_7djtu&UQ|7=0H7z6z2rzXy-8JAZI_QYtY%* z*4fLUDTzhFOSKV?5=KV;u;-)-LxUY$4WuRtBgRrVG3rS?VkN9=R$GoW5Vrajf3U>{>2 zVIK^26MEUZ*xTD%+MC)NK>dVj_DXiI-EKG9Za^J{%eG?Mceb;(leQyJPhp>JCsc&o zY};tt0Cg2s+LqZ0Yzu7<*=9q1g&bSDEyXs$Hrh4}>MZoL^{{oewY4?3HGz5yHEmUG z6>M&s)nmKV4>sISq*4Lm8!)og@)+ep`)&&(c znr)qAO|p)&j)J-j1Fe0m-K-t0t*yNWtC-xWvOM6ggOrAT&G;eT!)~R=5DCxu*LO;>lN2p*DBWvsOzxE^@wY( zcdliI1z9pJsg?xG7^o#N*wWw9%hJWt-qI3kN;I(4wp6oJvUn|as4a2BeARr}Tx|Z% zd=_d<95Ej>?=$Z-Z!>R(S`!=0Ys@Rn%ghDlg-~;1wt1R4$DD3XF;9Tn6T{4d%>B$g z%$?0`p$0`0b3JoSb5(N%v)gR7m<&ezIgy8n{EWy$M1D%-K_WjP@&J(^6S<$rkBHny z|K278bB9{}njL4^me3Hl~h#XAhJwy&7@@^sr5;=g#{zTqIWIrPN64{5y-bD5y zvL}%}i0n>eHzK zd6CFsB8!MDB=QF$FA(`Xk>3&dEs^Jm{D#PLM1D==St7q8@(huui9AK*mqeZ<@(UtQ z5P6))V?-V$@(7Wi6M2}(&xkxk>$kslJdo5)>6 z?j-U9B6kq^K9Spre2>U&M7~SpRwDmJM7~Dk zt3xg`b$hAbiNaPwKUm$WdkV)UBKinU~(5QxeJ)w1x)S&CU*goyMW1Ez~nAqau+bU3z*ymOzr|E zcL9^TfXQ9Jle>V) zUBKinU~(5QxeJ)w1x)S&CU*goyMW1Ez~nAqau+bU3z*ymDC--t47m%K+yzYT0w#9> zle>V)UBKinU~(5QxeJ)w1x)S&CU*goyMW1Ez~nAqau+bU3z*ymG??6xdx#uFU|N5_t=eRfw!iWF;ai5?LW6@lx{V@BEKN=1d+#yJVxYE8vkEm@D1=TguQeX_ej?>&MzVU zpJIQ*_Os1zoo;#0e9hd}G}pM(XowqNSfNk&KL{b9*5Fx@7XngBVXKGxQ{bZ&s(*h; z#pcAN0#~6kXn8r!F(C*_v;t&#L5T?D1e`dTedusW`Hv`c`H#fVzIL4dCkU?3mH@4X z>sGC_AC=%rxy#WHYAq=z{-D-!kLD|Pz~4e&{t{fbOT6?Ot#B3F-#vu4Ke%q21HT@w zTgCorvMsf`N3pu66sx=L<*C7S8xPcaxNcSISSh=-3$DZJRcv@?XTA&Ix@`ts(8F~b z?m`K!+a=CEvU;vP6O&S%JE@k0;v$YfD^5ShtKsqOEnS24Za%-bKzh%^OyJ<5oL z>BCtpOKdeLv#o}h+4=*|3}faFeaB3!tYS)TnXX>NJ+N%&djQ21nm`ZqIIFE%Jvuj; zf}7~K@s^l&i929k&vyXk%f`?F9p_6m!WW-bOU+8)){}=IkY}sEG`3}G&UmH50$0W~E(8Eib{GY89{%5P$>VFn<&`wAI zs1>)(;9KIm)w>?z=zSpmndo@jQ3WEz&1~=3x>!H74zQfDq?>;+W3$b)#8lC^%-FzH z{AX9BNazTyO>NA4X zr7(I?pCJ{wh(&Ak8B#HppXde253P3Lh*o=B8tRqy!BHtl>Pkb&p=XPYcchdmQkzrK zmz8J_+AOtiN@J{VZ%Z!Zp**>HQ4tpOmOd><$41bbQr5=oHN-}=dh!fCFL|D#O@`0W zqE%8pG#SxFcH)aHqMnmHH;Ztr1x%=)#pk!7ZNzxh^EwsD)WT-;Fj zWqp2vaPGE0_*3MayG6-?j9m2t@EOS&P}x5>H7z@w2GHvy@u)26byDb2S>AXn=TQlQ z7w#^pUbqsl{kbTBaM&NTq-RG;-?O8bzR|Nhef?ljKcMd|?NAP-4^1y&J9isNNxO{{ zlQxVffLqiTNagux8L6KQ4rbr@MwB|fk(j!HCURacSkwoodrG!1IK{%|^?yh~{U3@! z>uciUO@c+e0rVdEpl}K?IfdD^>1c}EbhH?^UPFG|LO8h>;K~ap)6o!eHnPDGHgOYL z_IpVaaoO+Xbu07C4TD8Jf%z`UCZ;dbFl*yB)V__|i0ym(b)FR_;~u~&doosD{4q@2 z@F2x*cu5`3m!UFFqLx0F{$^&}n{A~jtASze?@-EJz#;T<5g@9me= ztJu!BjpU*I!J<0>dbqUNLWL$v|IpH#&B?VFQsUYR#l+QG^TaSGcLrj4bFzk*8ksTI z{FO4-{8h|c^-rD|iZpZrW_d*#RAx176`nL|tbV9evjvd0uAkfTV8>N zC~hv~N5OCHrC!D0m0sn+VeV)L;PU5=&?t$R?QS_jiElX~Ca(A-PYiFBwm>ZZt)g`` zP}C{`^(scL5af~JQEUUq^4}^7a)g~L9iY&a4v3-4^ZC7*agI3-G5~5D*Be{8tGixs#XEQTp71qv z-XHft++f2=!=w^i0}x-75@N);uw{=|?2((Co12!E2@@(hBgH$WX)Plq;16Jwnw*K! z5(6kJ^ie=`T8cke(=L3$4_ZXiL(QF%;&{|F7uCftCAO(7O|$)}{_H?*u0KQ)>gVTD zB3`tg>T(!vXHIfrR$g+>bbn$N{jdf)Eb)G-4f~VYsQvs*il0-{&xFLB>Def3*+a3? zb^h&-Cumv(KY3PWOSOxiO37Q%xWrU<0y;R!0$*YQUp1K}%IeDynzk|n8Kk`bCsORF zX-czULkFbHa3wUzT#M-AL<=|v<=9kl3Znf|;y1K!WOKtz8QLzOj}k24kdxCVSP+Gp z*q3SnSDLgY!Y(wlSIT>q+Ag%XW2OsrYfrKT+*fkCMc?Y7Rz8&Ya4BmCZMSwy>=vE& zL*3dXv0LiPg%4_=ol;|VTK5e4K#C3dH%rKdC#4K`z7;>WtUNCN{S052=HJi9q@M$Vy5}NlQ)&FAa`L8J^mvVWAfYH+V$KVoTjpN4nzB4k;@UwKdxu?6fL0%Xin%MkNQ(^*p!BaYi0SH&>8 zggt)5Uk9P&_XKc<$Se6x`$QHcu{Lki8a~y^5LdOy*sZkc)CZFv~j;reTid5~I|Cjp|iQ-#K!a zjMi_MaE>(!JE4nu6+?F##G4$xjBy`8%lk5h#^jOiIZ8b4xOx?nchs00CcRNWE_>1o zZ-6M{*i`i@X6-PPw=x7YMgpt6fCja)vW-$-&Xn|iC477TB{6aP1fCeC=@CFIFQB0% z)=tx-`%?7LeZ|P_GI?Z}@rDDk>={onGTUcS)=?j;S21(j-aIpe7KZ_|ywIY?%-Y== zrp}75x>Q#*G-^XLaTYey5%X`af;vH(-h?4dju3p8& zcW4Gk(_qm6Aih^xl9q;8i9S)#J~P#;7`VwtoQdiFf4RXo#QTEhPdNSmxa+*DsWZ>9 z+u^g1wY?3M*?U-)m=Bw4o3f1C;;zTtWmq1u(U+kH;m+qtz4LT-P@IC=JO8MX8}w)? zxj`d8;0zfe#yS$GW@WN^g$v^8tzQr?zV#!H@Wk)}K|n0~1)|zGMC^y~I(V5OUxFrT zQ0zx`t5-4pa7}72I1zFIU-k<`#fN-^saZLp+6xr+;cn_x3_a{i-sUhrwYJg#t5jOC=ENb9+Sz_Lyk%fn{^&8ZJRnc6< z+;dAY_mI!|@d3NUEWnq&OH>ARdLSV=o%zM)C~uHCGsPAke1J!Wi7yk7<-MdeBSbwM zPRGV9<=n-rQqEo6^D$2h6JLgYV}uaLp7>@yOuI4jVX?snX$%fWw9)}z-VrToa3vdq z5D+_HiZ45IXWef z2pO7ea9}&7$96IGUGpNSC+bEW&fH+sxoatP?piT*zo|Sm9OO#@YIz6wI9sP@O=P$^ ziX$wi6h~O!3?3Jjb;*D$ds#<@v*Pkk<4(F{@1-`*-Yd3opGiD4Oms;AE&Clvpd-g} zmXfTV6%Z5m*3=4wbEt_xEbkmD9TgCr4KL_2@~CMu^2DIM=JKY61!w|*%3gqm!pIS^ z&BF4YOU_uJ$48ca`_Y8W>e zyFoU;-}^7`Ao#vs&{G+{eRikoQ`cDM&(3+yD)2qJ4)#y&6Kp@&X4xuOU$i!{?63?q ze-B?7Gso?P$^b_UV>QkIWP#7H{=3P66LSLDsZ-M9lcxnTvf)fxd>}C~3uhv=a6esM zsSz6V_Z&-bmQIa^a@0e6LOw<8Mwyg5DXr6qse$zL1wf6rXBFUbblZKMx1KG+SlClzW*@M`kS(|3l z;vu&loI3szhfg3WDf*nuHHk@1%HB3SnWI1DHx@3vf&P$~DyF)klyV8^st#=_en#}W z#3MLrzhZd^(Qgu`7`0*M+e5!fIWt117^OM&%*Yif37VRws6P$;BLC*a^n{_y@*lmh z4-5S)|8Y>gPw0|-i^lXDp`WCjzoCOBw7m$u_*K;O$A{%i-2zLRqF zjM|Xyz0tQ4Uo)CrGdeGEK=Aur^o^A2d||7R2P-Ps1)Y<4qA8pSj=q*SAu3xcwlqE) zivL$OtTXuT_CDh|=c(mRajkZK?`-bKvTwBgVvDyT%UkBZ%sox>jVFz_#f^hs{SW*E zTLp_<;8ZEQyqglYD~gGtl7TnOqu!Mb^TghjDS5o}s(rB73EXA(4VTimW9I{}Z$RPK zHxR>T^Q9qz0PoNTo@U3jOo78-yk~<#zogW)c@9=ER$wo?gU-wP<5_W<;w>_Z3_d=N z2Z!f%27v1~;lv8FQSbsKXQiN&oRx8Iz5{T+Wjb`A?9R88X!%%y9!j3Cm_EN0(~q_B zW3T-I#JZeZdI>h*7UN?0$ercTK?(aJ5 zn(VypT;O{gP6f=4GZ_~ByN-b}`I=IR!&AA>k*g70LvHk(Yc_HnfvcCvckW8 zJ12ZwnK)HTZQKu=df4#bYI2(+Zd~S9#TCoMS65>1sB0BhD3f@Cs1+{R0+%lnzqGJ5 zHKPcZE0g$^u&tOo8|*8S5=$jE9Gz5xy=7A8=)c%v=uz;d#@e}Hw=UM@oTu0& zcUD(A8#T2$a=S>{3t5?41XYo{U?5E@F?w8C?vqN|(uC=8B|WBi5(?Ign>e{|Z)Hk~`Sv#G z(=@kVP-hAB4{Ywta+mN*&sBdPx~a=-sP)wS=hMgK+E|$gNvA_g(OYT!|7(MwkBbuj~IGN*t&S9vK~i ze2QsR$7wjo_mP{rWj=C?-7@nv$8+L?#kGLD><;yn_@Yv{HAltw4x`L_hl!aVnZUV{ zf)JRj3CubKCKcwGiwa8q;m_(-+=GWT-@Jp^SPkfb4zV$=2mITGLhoLpUd8Yab>Php zv9am^uY;?agOA*JQSe=@)T_7y4{9n%bqN;V1|66xKh&XifP2%iO$SB)Kq+eUL4mjn z^E7de=E34>&;=c$V`>)^{~CqfQB%E&p@U8NfdkOD>I$vCekkmAr8eaDjbiAzHF@aP z!Q!d_twTgfv2^rf`d)k5f%n>r!DnkSeOd&IZvpVKJNjJW%pSP~p|tO=Q?Fv`S(;*F zVD2jVm^;Qsh5~QBQ@xe~Zsf;_KUiEDz{~DruGrj~1JGOcP~t6n#Kbc_JTWX;Dgm($ zOP1(O73Fs{2%}SK{%}QeCX_{#o9=~$Hti$8SCx}zh zO{>(am^klm-pU<=#XcY|yQ)~C5fMAnoMLZmre4MPSX1c_W)Cmm>o9vnhf*l-YoDuE zF*nlGnSvxz4{+;{M5^Tu@6%pYk`!JoB}pMy^F>Hlbh`mthefv_tV8Yn@_F?twtLPT zZn)F^|51alr#I+1=(z><{~MfFoNXP`?R)JW+kMszmaCTT=EqHkOcjiS;+`}d)ph^= zKWQuo_ayWkMv3<%DS!eA0hl4RMF;{2<)kHG#0v9$--+In?>mX_$*O_eJqfl67Pp2D zNX*%Z>HwVV#u@No!SLhoty0+k+tXt5=SK77U4zA~fPA{VEnGBt041ZejAVbb_0PAX z)<54)+=rE#(&CVc-xB&DF%>_m4~bb&%^^`!6Y-q#)zovPd^Po14LfY1TL8PnEp!xn zLRMCKav(E?`M*{^XYqB8*!<6Ex^PFZxH)v8?CQNlzkl=K@rBQZhE@zy{Gks_(qVGe zt6s&tD;DrW9+tiFz$tg8T{HzbfN{gETw9I8051kPp zl}f02Pxn@@V&Y|*Qx8pp#eN{ZSKiDL;D}Sw0~5pJ;>$t`{AHmS_^J8)xPaAqQvjB^ zTIYcSd1;B{+qabUDEYy|KU-;rvSC&l{~vu^MarTXWQQmTJ0DdO3|0oM@Nb#TBb>=AjopFd75{`uo# zi|1?hb+A8b0Mt6{k5uaL*R(0_;Wp}3jJ;T6Y?x8%1GdZ=MJWfSU~{=Vl=skn^(y9G z^Z`Fe;H_Q{xMjZ8wcKjvC58P|2^xM{O3?5zO(jr(uB$J!QXPmwe==RYiY>hm^OlCF zVI6?hFKQSw_llAqsG(lPJ$Q5+-vgM*Z-*Y}Fq11|oc18nLAO7h!tYNP!!O`JOXPHp zh5Y}MW}n5IA9vET-qXgt!|{zH$6>NRZm(^7!`9LIp>??BTgd-+npc_QO?yrKj7N;a zApid}*Kp@4XPWOpZ{@h*hA#~hVr|ytq!CALLU2yHW&?unl#|sK)o?EC_%kPJ+wL5U zv&@St`x=B%jprn%lS2BrscG3-gidn0AMsL-8Gpw$XIa1jQ08SHqk0d25xw!pt>h%e zMzyZlvg4L=PI5%G8f&wSTa-zGm;b^x88?@doy2VlxD76jmz2NAH>Ye(akDb1`zAD^ zvZ=&=NvB4*Zl#2`gSe@r#7wR=?M4pYA-{iY3x=D>O#>}q^Mo7AnP(zq*obWpZX`Ep zSzY?00K%bytGJ=ugnzZY@KysikThDgi*0U`fa^<|)3hzB%X?f;pXQW>Ij*bALLlan z8rOjZp<7)D$QejcFUYjaq~vL#k=tHQu5?s`Dd|}Oq+NWqn{EkCQTrXAo;5kQd1icW zP9m$L`#&nE8`X4jCeF~d+*YSf)1+xW;DX!aS|DJh!>W%3s&H$$Q-2A&EquE!a}<|I zjB87JqiW|UB?TDQnreYBM$5mIk(-u|7G3UVXxG9g^ZiFpfG5d11Rgb8q-CPyiBPCp z^VD{r@&9)WzHZ(*p8Xz+yRU1G^L@un$KCd&wiCAM)?~|O^9`u~w+QP0HHphMyc27e zuk+spp@39>@VH2<=fccKlFis|FZ_9v0>}Nt-vU>$zvb;8d1n#C_U{68U1IwLJ$%0z zx$RR*Zu?YB{?-|sIcZkVfd5bqV#Amw!xy1Nv2lI*&$G=ia9Dn_X{5XMR=Q{ydVzM(E zC(8NW$WRTn^W|^UtJvP_zToj8cGwy4CB_b;@M8pgDEZII$5VeU<>RR@?cjURGg#co zYk+8x&0w<|>~V$(@xvjvBv+!_pv0&V?Z>66>Q#Iv*1pg8qeHN`BixA$9s3cneWcVs zZc?ve`WIL6^pG~$0qFHin~b#`qv#j!QLo}ItXar+0ba4~p$odK9hE0p`-&~vO0kQ! zim_i<#A8FQc00hV@JUY>6(2>VSRB2R%^Zq+9_Dv7CJCR$AKT^_oMt5o>i}6 z{^t>Q147^bt7+_RFs(AxH*WJi=Bw;|!Q0%k*K@D?oIA@M=X%;z-}#2~PRBtSrMl3Ht$*v?h)g4lBCds2_nfcR_6S0z6 zjmOFf+C(*)l$@QOHC@T4$7AI9zN1=Az-j5B@6+S^<-{`CyO4TDLrsmAo#3H3VIx-! z_&(Wv46mSCZ%!bO2nJJy-oCgOikOUDD{RJ4m| zP#wG^A7y}?RbxbxZ1j*u`^$bzqvJIAu89_iv`CD>(g+LgCnvJZ3>rFQr*0H+U)e)6 z)S5bALeE4W*+VqcAR8{BCVR`t4$xYZcUa=&tA0O9e0=g zl2Y2#j+<_>r#7Wk&Cux@+W((3?KJqV_`dU<@a^|)^S$O<@94aX(NImZ#l9>*5P2FEjwMUL5yY)67)n4^!Qy`zbvy2I-* z*ss{Xv!AfHE6f&nds^hBUvO52C7CX;44>@;wyP4iH ztu-w(Eilb6rJKf?2Ag`ATALb}s+yd}8^%kE8v%y_EIul%d{7tz%MfGh0}Nq)1H3?zreJWpW)R^d)A7dXWG+?@hYaR zXpEm@+Okb}CDWejh@WNJ6DRO9Oj|kyKh3m)6LQ znfB;F`~=hH@5W1+_DC=MIMW_-;sU14n}nAzZEg|HXWE=c@nWXUI*b=FZDxP`7}I9# z#0!}=y$gPnX;XLN1x(BHaFA(} zyWzP^OFMw)FfFwkp3StBeRvkrlE>khOiMh2A7ENSe>{U}6F$e&nKr&0p2oB>ALFS^ zySoa`W7>c%7&EPZEsU7f?**L8w7%7G4%2$i#Z#Ept2)kRT90Koi)r2K<4mS?-H9`p z)@2kuA7fOl!Xcr!uWw13ZywZQjQzOlv(5Co`?(9Gt|o=HKB& zro~Uf2~6`}!vUr>9gin4t;vUYJkuKY#^adQ@C+Wyv?#ndetGEx- z4Cit0um;IKxEIrI{D6Bh?Rsb2gK5|9z}=bl`+VGuX}`XQyE5&{2;7Bfm%qVxGVSM? zxHHo(RmGi{_Twhpk!ct2!5x@Zv=z5!T48i@dY43f6-(uRf4){%`ZQX|7VA{Vr;7v?>=WV=^ zX`4IX*O~U#tN69Bw&aV3_ztEW--4Sk?brz1m}y6@;zmsS{BhinX@}e3224A&AJ=Ev zr*2%2X`f8Tb(wac2Cl=j{pt92rhVkbwVAee7_P;%4}ZornYMcguEDfjt#EaweNcdJ zW7>|IxEj;8Z-lz+>Pmdcd+l*mroFok-@>%5cj78c+p-5&X4*UBaV4g`eG^w?+FLI2*wJ51%b$X-F>TRh^e59EyA}Pxv`1e@ zSDCgT9{tX=M|Pv%nD%ft^efXIJcq6@ZC)1og=uroq03C0GZX#Hv{_ftC7S=AZ}9c? z7I?n#)O07fRyn_O)`e*Q8r#>l+pYImmcvfAp()$AIqq6qS3|zKSCnxLLIT}*$fl5( zKo=P`2bUd5ngp>Kg~Z5>rGYf&F=boU}kfdbr47L1S7_3$9}F z14%qNq*;yya*1h{QRK;7E(SGr!!zntjJ{t}3kR}W#{jy-?A9oBO-2W0ZZJ)~irGK< zj5j;vY26R(67#g8*wwrcid*lxdKF{u`-I1a2Xi!FOMEbygPTSW!w+U%S}eJsZcq%o zw=xe5nXUH$ur8UcO2{)ZM}^w?_J7o?7=KSq9v?DWM*+SrnXL+bj7$tlUR${VwM)4H zA6DXf0GX{L^~!8jdQf6I2kl2q<=9irQjR_C)|54e%+?WbCv?edRr(Q;6hi513{M0Kfa$V{vD?Fmou;gTg`G|r@CDa(+;>E7K3lT!VQnm{=bUh zUW2cfccJG?&uy^(f5rK$v$tcR{jj~NZM^jj%WsyB=0{D(Om&Uvaqq`j;g`if!Dhi? z47M04Z^Wf02hve0Dd3%r6a2Y2A-r1{K#TDf4A>&J!VfQURtUnVLvlwQhnx~fOHWSn zPs&PQH?My!dh`0%5@TP;zsjOM!dO6$77N#{)wh z*lYlnSiF`44rHRVytEurFO0(WQmovo6f1x801pjT&XQ|o<`|(%o$#>ev5bQESSGge z*P68ftSU1BSmLTO5;)rR*IlVI(Y=&2YiBiIii8ze29Qf!kwuZm@Skr`YOW zHRFc~OnK?RE^*3Z?3(3Fmr)eA%P2AKnHoGUtP3UsuEceL7B@UZ*sG=U1q$Bzf*Aa? ziwB3=7?S{8Vr`5F@Ei;iNd~tN>y%8nJ0**`ztj{Qho>?PxOI6d$wDmb)Mgg%XrSaB z4Px?>-|-d)hkPoK>*A27OUUpkMTXv(s#Q z8mLz>?THFJEi6M)fL7ubLqi*WB*X8UHi{dj&HG~PW8d@G@I)p9wk}U(D6Ks_u*2M~ z757)`QrurhHKhSy3QPiSU8X>i{~sRKVepo7=s0OPM{MvTnsWN!`Ar0HiJo6JPLi^w zW_c^q=SO!v)q;2|zD#)ymN)rzdmE?D$C(IDV2C_;3Rr7-sGO z0P8YyE4lDdp;Z4hO76cVCO>qJCx`Xa1R&RCJ*A#kh#urk=~r6|nvNH3Yg_yK|GXv*V~^ti8xS+wQZiwY9Py zfXsj&Ei)k3eX+S(+;OM?@S9-{{9~b?|MDS`TsdbRxZTMVoQ#wGu&l_1Z+&NmzUhQ# z{g?6L!O4;vpFAy)k)00T`fJgwO|xn7P@M&;GW(+{eMdJ6+x*ar70;AYv^lCl<=eyf z0iCQGe*Qz9oFV6+PPh&AON-nii^s|7XjGg0oACck4GB3X=b{EJozKW~GF{H?jBZl> zdS__dPLp%cKdMpA9Ys1jRn9TNsCG&62Wc@c-2y(@GCxwvwa9$27)zgIwO&+=<;KAa`{^`t~k`PWmX zoO7g+-P3LvaE6=*fwii5#c;ZuH-xsK@aCCJVUy)dnh{NMo+vy?_PB}mA>lMR@4<*( zvW+G&ZK|At1FTW%x4{$TOrM%|!heWu7BGm*X$oGkmni1KpaBsr@XX4TmK37jZ< z2B*uz(0xph{Uk>F1aLt13?6GYk0;1BDl2U^p2q+C8hrgA{{NY$iu-=oOU_HqR*tFm z_u$lgf9unha~8jOmg$J8p%KUJh%+1d(oMcb2HOWOy1)e@@f(QgS&4!4)-EylpF?=?rooF)m_%m$f&(XR;xKS#H)`q3 zZerj+dh@{W7KsC3iSdg_VE@$Qgw!nfzF3$%{R>K-{)L$QYDbZJvG2J3+TH!qHY*HLUzsXcErj&0o6>ARKL3U0a&`ZqDiJ}jOcIZI4 zyNY@h517KQIID-^|Fw*_8BEw@FfQ~h^xf)x$=lKMk!Lhi>3huGz_rbFm-D!D9Ms{P z-G(&D;PFezOb)}r*^UYU%(XIYx6Hs(|Y;uz`lP2b*C27Xd({er}5Iv6k8Ghu~ zj^Pz@f(z;YN?wQwp-{yQj@6T)Q&+qs7{`_%G*Zb{Zo^!os=AOCcnrqB( z+Msz$XeG)igYR|W(RTEFz&Alm!~xT+P|v>aH8F?OOqGgH-Zx&%cn+FMEAPR`>bb%`&YRCKLF1Ee|J=~C)$=+uUVT}B=cI+ zzoyp435IX<|L8lwU)BDPzlHxwd2pTxOz{)8$jXsYQd2V6wFmK@%-gS&TrbM($5jqm zI6-*=8X)ilCAAzAInjr8XE364B zClg_wMV`)`K5HeP{n73$dvpJlGQch{&t5oth^va=ztdbP`S>MkvH11;S4soEz*Gql z@B@o+0z2b~Qu3io++m@i%Rd(7E+5IYL(ubvDJ8!N#rLsIc-nuZ6f{9#e#3CPhdYP} z`E>asOh3YJL9vx=3t-BB6j~6?DL)%pK>Noy_oH$wfUdq*#&G&jCm!K{ zW1CX)t?xL-^21zH6!@b#*C?()f;+LjQu49wO<8OhwM76snxi(IKFel&lhBDf_9`S>A9$!~#WKHCDA>^;x|fs;M!FJhgWgm&B|rQ}naRQXb&x4Xsm zc9vS@A|<$E-&9IIw(-*tW4oefY}V0AXkR^`lzeK#G=`e&|99xTtvs*0zjqgN#X6Tc zZaAK@zhV2qR@~ah^1k_`xsoZ>xCY*lYpx%q+oApT|G)b$LiWBZjm35tI=##H{M6Iq z*5`@ow?5A|eT#g?^nREg8v%Ayrbih&^7Od*IKkh1oR9yMDkVHjj|~AoD$}EaAAV{> z$iMEbl>8PnpTvFum>wI59kI0E;Cm}M0iO+B!EgMIP;dN>Pu;9DOAT?x^?_PooN**- zi0K|o$u~43+L7Ofhu;Jt|WSwm3yscbG3eCzk)>bH3#pwqY#~mlt9H zUtkz!h~<@|XlnPhvfbAfV)yzlu;6eVt~P)RybkveaJALfEF)H5vy5-`x~gQj4gFVY z0ldIa#t?X-GIz9A%Q=`=^K&rIu2X|GI=E450(Vs0sJOGs+-jSzlx@DU5S!QD$gS|wR#7@gIDIVz(wz)a_sAo%jN1bq2g zK6s5#*IhLLkIL^*09=_>g4oOCt6aH{WfgP45L48F-Ls!~M4lC~nSM`cMXvxkkz59LkJhlOl{ zDyZ(D!O3+6AdlwBHOfeb2(s`=W&ToP`uR)wrZ30lE_68d>&of37`;xW)Rg~kSkb*?7PZ=GEnhrJW@TRi3T z-F1g_y@UIB(c#AOZZOiBl<#ZN0fb8B;ipNyO=5yZ=={di9ay3IHi{0@lq(E93-NvR zsu`jNG>@aAEhQ-`Vsauy3-~^W(l?IajrDylCWex>TlOJ6I32QEHs7bB`%l9--wu-3L?Ph`zAr`J4pQn3 z4J`1j6WyWYnw2vz-xs2PIpqpNPpf=u)wh8m^GUt*y4hLrbz?I#rL2^kMEW29mDJsI zl*-G_@GX|_!zfi99+&J}Ao}|%i)}fg*f$?`a>D~ZXQC%z`8zAO88?XDI4TYOf6?`B zxLO{i-AsgtFyDG|{y$geZS5KF-s;x7x;SS#4mrH`{6 zGxv3~%-|322+RWg;UUZ+mOl9f=^Q7&;8VY-dRPlA-61-bmS;ParGKqRn18LvXYQlA zV*!?aCOVdunL{jnd^VvzKATV7>pQl8fN!=vP)Ef#EB}&(FB}N?vBOHqZ$QtxAq{93 z)6T2vdr zj>@$t1v`?XldvC_pN2jB1i$ZepUAcW?ufL8HbmuGRIm*XyB2j&zS(uKkeglIs<2If z;FVU;gs23s$W6$Oc(rK%4)P`T^OKv-?jo`HaJ8r<;78?ZQ4pU7uI!T&pY7u(KAZh) zaTXf7&C^ltHj$2Th`sm7nYi}wGjYxC^cC9#h)Zk%O^9Y(V&GyZ?WHe@n2x|CW#a%wE>;uu5nS*aFvMbfYeJc-7UST^$Mau8w@_ z_OG+lFv~Op>S)d~p~q6#7sPAmRQ-&WQTWPCkE2#PE~+ ze;swkmGJ)GIzvbA8(xQJs;7*5fxC+93s*B#-?T0l`WSZi&KF6eid^rrK&3} zF%44qWhbWuQU&`?h;f-dq{f)+oY)-vBD?Rnn6xUS;=l=Kpmo29&J`$szw9)8nz>oD zpHQhTQa-!?y8=waxSnb6fipN|nBY%)EZ*#YM*EXgQX!oA1$yhz|8RmT zAu)jiir-RMFc4p>@1U6ToRHdrzB}ImF*&f5`fz+rz`KdZ+I}%(O;s6b8m?}in1BJL zx?6~#q75mwgs$x(|q7)bgd&I<-gf=ZOO)6FXASPHKtV-s9$G2N-?+log4u$W< z4s`XQif@UKD{>$$Z(c8CUZA z$Hixj$jpfe{BQ7shutT+#$=`ByHBzvFzypS+?9L3>@`=-@vc%9i28it(Dq_{vg7E&cSSk73Y13J5aEZSJ+yY(V58jcfvaBbyIBxCaYe-G8MwKz9+{9fB?>0(t$kQu1Mw>anme zDfa?cfxpd#sl7NE}owZH|aLalNW64c8+rQ{>OqI!`Q=H~8zEO2gCAya1~fxTo^ zNJ)!Yo}7rFto!1N0WwBkopc2v_Zd`y5Ze9Q-axjfr3pgVVsPIp#-6~`x`J>N?Pn9Fq|q8xId=2YmC` z47rs_{2P>fbG*r>L-fPS)(6M}SGEM1S=r`RJWq%#p68QJN?|^n9|m>~kO~~wLDHBU zoJTEa+6p5GaD@?k;5Xt~U|5Q01F*oQI0aTM#dFJ(nG;Gr??hE(59IL50$zbRyeMy4 zQfy3CVtfWl%o-6BpF!T;Ax19uo>KDRUso9$R*S;`Uf`0Pz^j+!xn)-q*s`nnuoF~y zf??H_39tfJT`X*9Z!S}ZFqf&rXMXKTwl~AiR0c2$Ty?3Kv*7_r_UZ22#|{zd#}4tS z$9H6@VF{BC)B=|m3lbi_8ZNc zGJ0f#muNxIOSIslk15M`a+v#u0J`wGPrXylEw+uo7Td;$eYFw`3u~klfEB(*l6T5E z8AB7(gI%L2@u}q&jpHMaRy}nM({(Z+3!knPWcA|1`wua*_a8p!|+KvZq;nTLC<8o8V4E_oMX)7j5613<5Op+GSm)7H(h!CZ5_n@KjQh+ z)55*m{i5rFE6sk?o@BdhlWaEYTx*PFr{#I`X>+pauIWuv8RJ^x(}u%_WS8AJ&sp2C z&G9_M1x(VH)_qpDw~&}BCAvt+KVFyg3hYB5`&=B~_m5I3jvGkTD%A*68MCDK-4_$Q z$ke7v2lls^*dC_3!01W}dSra}#6(My3Il$;pohYDLrioxtxEAN`2G@;RE^dYafqkIKX zuq(6U^yQ1m*ntc8`w-vnV(yiw>t=TlzH=gnp={vLwZHEy91NMnuPoFT z#_o#zxyOq_`QaPi9g$Nhu1TIqQ^oLF6UV z8Ihk(9uCZY%y&8p^P4(`*>@@mbBrqb*!P>5{z;;zLgI#fC;$K3;UvN3e+AT=!XbZI|TS?kwU+w0~r~Zfj{BW7%sdV@@=EWV~){WtgJ>Szl3? z^nZH(Pye3(Nq>IeZA9%Jrx==%lbVuVcStOXts5JUA461v`(x8H(nq9a__CD+f6znH zVGZ%?bXddpkSx5zcu4&9{P|8`*Uohui9I$UA#CwZV4rEDlziw9ud&c|{rL`n7Ve{$ z$7ygQM_Ai^sg!)?4`zli+oQ-F%#lD?+iX%wKJ)vDEOQ-yz73d#AK!$`hXl11dGRy1 z)d4>8Jl5j}Q91e6Xd)+Pqz5xS=C&l!RZ#Mg-&2LjKjqK20J3n`uwvx^aty>`z;Obc z0K>U^a0+Q5-x6w(%;%rmj_oD&{rP6#7w#HX_`xGDWn?7;shg8GzjK?P71- znHV~@A&MP4;_8?fx(QNBzQJcb!5SQXX7s=xt)H3H*to=08sgXJ2w`q?gwH(lFP0hR zKOHbfYsyx#rW4eLFDoSBQO zAA}g0aiSB}7;Qv)LvJrx~3xfw%Q&H;xI+)$|07;MN?ilzi;BJ`cej5j|{`dye2%KdO{` z?5U~;4Iy55IA9Bp7slP1ecd{@+F-(4Z7`pA%G<1&;rw3$Ug3*8%&T%0651-CDjDO{9hq{9!1N$QMxF)XGNNprF2I?rQiCg~Rb%ZV!P??bL_@BMh!l{s+ zCZW<|QXJB`7%b>}AjaECE0IGO{wIP@G-(>=TPZgi0zL6DO@bykm1RcSyrWW@oB$MB zt#W*e9u+;{GO)X_L9oJ-njATB8YoxDjJroff69p4Ra8Ro42@S_su{YtCJ(4_Y#V53 z*e_8r;kCvNPKl54#bm{#!h7%}E*urrVv4djSI zZNc*hWY^>encp@giV@kOQJH)OfUF`z02J?c#07vwli8*an^M0!GHbE`=GP~C%#lfC zbgjzQjf_$FfRTUp4N(|^LH{z+M`2Vbo?)bmf>9&-bbbGl^Zzb7Z&%M0_fL@XKgIc( zuh<1+kNIwSZ*jjoP zkW8Kk%S|riiLkE^GTskA9C1|uWbKZ)3P*;e5Ao9^%~49ezh;x_NiB$^C=bM9BPnDf zM_QH==7a*JUw5Fe||YY*6tn{r-Ov<00?ia ze8?YL$RYoF)zv}Zeq1>BLp)l9dr*I+eh-B}eUyKkAlpUu7 zKj)LK8_JS4@aLBSQtb`{9!?tST_e~p*HB76_7~+?Y?$#%1Gd;1j~JNQ0TI%dUR6py z@#m`J3z#(?17fj1D>5}Q=NN^;D_e9z+vgjloH-g)HfKu|YKikD( zH}dB{0@&JJ@#Yvi%!5aOU$~=`eDLL~S#ap$C8E{EBW?%?bkDv@$%kJyorQ;A$Kn7l z_E%k=QUdU-dxr4#kmD$N6cR_VR22sYi@##PEq3w8a7SK|JU4~3;khY%n}6DewK=dC zjT(Cd&n98+UQ8+Z?4PJ|Z`ShX7Xfzdj-olERPm1z&aU&6lF$2bZPwN>g?oWFDpR=H z%SvdwG*n7H^+&3h0r1Iqu8ucCH!DQ_hBtvG#rT(zYSi4VL?s*5*m3A53M9 zDTdYh8~XOTnGf0jYxY0;VYmg}v=lqs6mOyYRu}o+vll8Q|GWQqlCfccH}HaGba-V~ zD&c&$nNsq34}Zb(!f$ur%}TM$Q^mfKys-rOonMub4}WL_3lG2DjR9WlZ?_7b9(fYp znS+#)&wcPimK(M)jeuM1Hb&v5j%b3KM{@M$=AGdqA5d+^Yx?sW0`ha3<@JslE`w+easdCysvy_rA1F0gC&@-U}=r!h;?&|rSEmlpN99*1Ee68Yf}ZQiuMytKukm?zUkKrii59PNv_d#1017xui8%7T84`Y`S-my#hyxUV* z-irSGs=(Vy=rV~-82;)91oPDo_?X*9v6!%$s{)u}S95_}T%kX2qn;+Xqn_sDev{7P z!YHc@xMD|H09T2GA&^7m4Aw&n$zZ*;ISbp^pI-@J6Ge9c9Gj>dQiLQ5AEGBM7^3H! zd5e`HcR2d%D(L&`y_GzxJ?-5It~;(N_Vf0!_L8r z-O8>T__|54C?y_W;6<%9iRpM)Mc_6~NXdzbkHzvAjqL zxe$$72y3ETAvxNj(+O&<{TGyTM<_MYjWcSbeZN#!ri5=b6c$G|(KRXCDHNkg5T0rZ zRohb4UutU-*BGg`&@BwAC9Gi)HXo>_CJ754+Aw+BfNBVvF2fi6sJgID7_wAH)drbi zu`OailSMYFDs1LgFON|bVf}zz*rLkWW>}gEGFap#DXIkPL3glDO@g5#^>=wHWY!4H zg>`zlF6EaraEGOtuud;mrfg17Q{go!G5Sx6UXDbJSVB#NeYfzCVN_9Ahg4S<=pz+` zt$H|Nx~M$t#8QIe??267t{QU8t|~4oLn687QOj7-AC3v-MNbG@w93W|TR#2|TnHDo z>``XRoY)*+Aaou*6}bO@%D7eMz3x5dJ>uQv-QZpB{lGijJKme)P4f2jKI?7at>Z24 zE#@_OZh0yHGp!S? z!>vQC1FYSxt*s5Lm8~VMHp@LrzU8FlfMpxxH&|ksZJBHtZArHbvh=jHw=}U-x0JTH z%n#r`#2NFC;15}EUTU6ao@O3r&N3&M`n(CP zJnuZ}-0j@tT;W{c%yUj~B4@I*zq6~erL&&1qO*k4;<)3u>^R}r=h*6LZCqnqY@B7B zWE^QsH4ZfPFt#-|GFCN~GCB!wtEtvI1+Ajm3%{Y2R4Y>lO{LmnDQF7SO4-q5s+FvT-lSTI4QLY8iuXou zP_5`iG?8jWs-f4Z=2?m+P|aN&y+$?XN;IBoj%LVDHQV=S9M!BZqOnvnpFv}&X7Zy~ zsb)BaMpI2+2aO79x&Nl2kyLx2LnEkmKM@V5+P!N?qT1cD2vP0!apa@gtx+h4YBx)w zY^weBKFXrn^?GO+)voP9nN<5D6=hJZ;5tgDT7D)IeD4uG^`=B_g9Xo+ysdls*8bq}t z`_U^@`>7ckNVUTY(aTgjWJLq0b|4eIM78}zP=BiJ%|rdDwkHPlrP}WA(Ti03z8C64 zweS8wy{Wcy3hG6*9rw`-RNJ0~dQ$D1LqS}Z5pq5lyFbO?PwfP3rf@<#%L{Cxey&q6>s?B+T zno(``Le!LM?>0kEQth2zQ4^}o9E2KEE$<9!M77-Us3Fy+S3nJ@Hf=eoPqnu?qIy)D zaskz)+T_6UABCQvTI>N-j%tJYqsOT> z@N-m_YA@G7WvKSjtEe>9`W-=!QLS$SRElbSzCn*tt@i*_l4>v9L614rn3OT6~T^ zq+0VEXaUulEO^(v#D0w zg5ITC%}Hn$)v6yr?@+Dk4m6W$Ra&AMRI79nD}@;{;JRC^);y-l^pZ=-2c zD?0HS2{; zRD1F)GE%JxLI$ceI)e06YxpwKQLX+pxKSM(#r4Me9#E}rY2QCoi^=xgr&_JMzQ3tf zbF}Xs)v6!$-KAQ!!M;0GtMa+;Hq|OW>$^p@isyYdsa9cx?*`S%TYY~~t=xOQ>r^Yd z+V>~b%GB{)quOJKe1A}_)DYj*pqAJ3NwgxUg`i+;@R$?&7}lRC6}={Z2Le4&OPd+3NewQq3~ocZOt4o=L9K)+!-q2I8bPhX(At_=5ny8^wKd%qFr6B369<3+#fOo+eg%qPwt z#M&Doi@N}^n8@NV;-u7!*qjK~{?bp_zx4Cjue4yq-&yb*1>|mm9O_VD`?@GdsD56+T4QE+gz~m+{#zd02LMs-qLIYnN4+Yj${w#g_(; ztq1%0=d}s+=e7CJ7fZ9y&Hecu0b0A~?fKBLIf*$bX^9c~%W65H!0H-&{0ll3A1+>Z z0DLhQufw`}d*VbgHrN|f3Ct3!<^9!hy~3V z>PSf@42hu5d7zYhXT5ljWF%U=*t9d|?x{jEXbl6ejhhfnm&0|$V>QXi~I7H+XO%kWF>&uYZ z=#n1SH!#r*>lsah6`3Dfc^!k=XdmLq))HKSMETMQclf2`B-V}1%q;XBQO>stZq)Io zdO6PQZ>Q;}qFqA{#T}secT!bBhE-qyza($~2ZC{xF%_t*zrX<;sEdxMKyCdrkIz$^ zFxV#omG#wp^wP>mgkGSQ7X^MSISvrdw}HC)2pm&#U2Nazt@$mkPy>c^k6r@jcO|Bh z@xY@O1ojY;x-9V3dTJi>PR%GMNb_Z-s{A?VdCdc-!|Ke2qm1;y>S}w8Hv1((v#{LM zti)9O3~F|A$axBSPV;9+!rB~KWp{zgNV&Z!5e{EaH-VE*uwHU(g1TxRGahEv@BQfE$6Z9@(#yd}hl>td$|r?Lc4_ljt^t znGQip{ga%3^QUHfYI7P(4Pgo|1GVTd1$=KhxI3rNhZho4A703ZHnn7-EBo^Y0CYPc zM~&3f#P34@4_TFx4{Eftpl}NI5`c<1XHFp|XFp({IS#x{)EAh=oXn^@MR3Fg=e9jD z1bI&kANe2EX)c`YzX-@;&h{yC(5prmcYm*xeAaua=VqW2_lZI$4)M(q((ijIC7<|i z8MYI{9NZg-MbE+E9zFv5-5*NHhrWHBg@!d}FMt-k=9Ho74_>e*@024yb`}!(aq~wO z8-Ar<0Bq5}(lU1V_}g)x7<j~7N#~;~62Q9oki?D9b;L+ z?{4o7?`H3M?;6Mlu*AE-JJ&nYJIy-@@&b(ZB5$U5h&RDI5b^``^mg@j@V53g_cnq& z0oA<~y=A>6y+ynZ$QSUybH{VtlkYk2IR$wGe)R0~?DA~$Z1Svw`~gcni#;EBW_$8H zQz4JQNKcL@-IMHzgKPqQJUu+mdfIzhdYVFBf!dy`p7Ng3o)R99$L2A(@4Iigufa`) zbC74?sQZw64|pxMx;H?+ffepg+zZ|F+_T)%A@9Hh_ZatZca}TVodo#@`n!9%ySqEN z+qzpo9)f!An(oT(a_&;@Vs4k);vDJBai+uV`Z(tRXCG$|=d;fCaLc}_vw^d=v#PVa zvozec_c(1%gX6yAmg5@SxDcPn01*-^9G^HAI_5zhgXxaRjtP!2 zj^U0h$Y+q`806^h=;i3{=mdEUS~!|G>N#pUDm%(SeuH8Tm&4-F+3(qJK%Rq(_A~Yq z_9ONK_T3O|vDv=fzQ(@XzQn!&@*d2zPqR<5kGGGuBglU+#GYUuXzy$9Y3~Yo5L(-t z+Z);I*sI$sLOz6&_9AwN-DG=Uy90R<@@?mBr)aki0=FCpEQY>TrEu=TO^fV>IqZ7pq0Z4GR-ZB-$ELTOtGo5yCe8Lamq zkHR(UW$QV}40+Ug2=XcHv~IO-u&%YPuzmu073NuIS*KekTPIk@Kz@ZRYpONLI>_4J z+6(e5bh5U!wy-v_*0a`xd<*5QrL4uQE~~|=gS-njELSZTEoUqzEJq;!!fwkB%Vx`Z z%Noma$iuL}GS@QGGR-o{G9L0VAWNoYh$X=?(9#$3GIX_cu(Y-`w=}ZUf&2^=EoChw zEk!I2iwW{H+%aD_=bO))Pnmy#d=2}|yUg3no6PIXs~~T~V)F;)+2%a+RP#jhIJeGq z&vnCf)pZf_Qk-xdaUF2&cI|L&hWr$3T+3ZcTnk)tT{B(NT$5bmU87ydmFXG+`5Feg z`nr0$y1F{JT0`E3My@)p>aL2evaXVlzro=$IUhLhIIlbNA&nwM zH*Qz=t1lgnf=8+8UL56fIEr(^jx zmea6&3(KikPQh|AmTzJ?3ClOIoQUP?SWdw5H7v(t>Bn*$mSeFTgXODOj>d8nmLsto zf#q;4B`gt^J}h&v%*HYc%VAh%Vwr(uI+kfzreZl1%OO~%V3~~NU@VicOvEw)%Xlo~ zu#ClW5SFiCIS|X2u^fQqOIY^DvLBXxv3wEBK3Mj~vKN*`u`Gh67fTP8ZY*6`Iu^1F%S~8r#Bu|cUtzf(%P+B9hvgSouEp|m zEZ1PU8p~B!uEcT$mY-p{9Lr@`F2(XwEI+~WV=R|o`4N_jv0Q}ZLM%VTasig}vHSqb z_pzLZ<$GAp#c~dov$1>^%UM{ygXK&tXJDC!WiFP}v3wiLX;{96u4Xu~?45@>MKHV>t@TkywtvayXU}mIzB9mN{5vW0{5J zFf22%%)l}o%QP%gu^fu!5G+%$OvZ9BmPuG9Vwr$tJeF}-#$q`L%U7@*h~>*z4#4sy zEc;{G56iw-zKCTXEPG?w3(FUDO5Shm3ODJ+{~*$m63SU!nm6D%8J*$B&qST?}2K9=>c ztcztGEMu^&jb$w?Yhqag%j#HG!?G%tRj{m#WhE>tVp##p@>o8BWjQP#$FeMzWw0!b z)u-uE~9xQ*rayORWW4Q~<@37p7<+oVwz;Zj5+pzow%dJ>$ z!E!T}Ut_rm%Z*rW!160B*JJr5mg}(m0?V~nevaiDELUT>3d@yPuE6p$ESF=s49lfh zev0KMSbmJ<5-dN$axs>Ruw01chgdGaaz2(HVEI0l^RRpm%eh$2!E!d1?_xO%%XhGx zNzVVD*Lk~m-gf`!F6HX){1EoG73_m;8*O%LPs=>>1@lv;3C8`#N`@i&b$X-jdG7JQ zA6&sB!6zc-JR`}MjxT?b-2NywDJB4NIt$Y-uTnej9Q z5-WlqSD(%~+DLQDkkd-AKh_xP{w&Z#zl1qVkk0&p>oUyXO9d%{1Fo!?@kp({R@Cs==Y32e|7dc*HO;T^gx13DZ_s$nZ_e%fb8Yb|o$@QtfTBhcgNy8ebY_U*=<~=0z$0*Q4(gohQmRA~~+ZvQ6@W!=V zXM_z2N)>qHTCVn?TM0B&^NBk2YldzD&=7%lI_368TE3$cfmeg&dczmqC|TewXt~y~ zB{MwQaZG2i8={e^Nb__cbmqY~jv!&?tdF6oFMB`>Q)rVAlxL75rF%--{9A2Y2}P4kc;cA;V@*W@CmD1>XCY z=Mtzt!oB|l*oY-)ns9*j%)m$pe8F)7Hz;_tDSZ=cR_(7yqjlF_S@@ z<|Cdq6q}VzB}dNxck8?_dOn1=`Z*A2{K!+eRp#F*f4fRTXxE_vmDQcAx6 z<(ZkR)2Ob$zzfu3PV&R3$qq6wo(Ss`!IID1-p?|Fr9IKJbg=gZsUN>h=pVn$r*1cr zrEcUea09g%M|zm0;}f%TQj${QVRokGE<1yOmz}`}Z#$g@uj4Op0l1j>lrV6-ZKTL$ z>Ja2Ib@<3_-er+%_zRqX+)ar0oI%d?#lcHDalxMPSPG$iEQL?oT4mrEe}MyN#TgTW9d#8BIotVKvm*5Z@4EXR_9 zZEex8Ei>MNy`jVgLR?}4pSZd7d2SeBLiuWe0#e4HvpL&^P zt>rJU0IQhf`V4C-B#GI0m9%S__B}Vlu=!`6smEGJDSm#Qm=&q6ow7w7?6bbOk! zp<~Zw2(E*qnaOh$l4ho1I~E&$By@l+=0}3sTHX#4QX5Ghk!Sm!Z{Yf?SW*aQ9Sfvl z7Qt%LV4t8r!PXZEyY)prb3N6<9ioQE0JE4?SqL-ZQX{D5GfK%vt~-o1GaOLA3dmv( zs6&v0z8-346M0H2&%}R9Yfc^2dn^zHI2xeEZ0kax)$ToFV#6_|hQt}kSzUh4q^8p!`&!O%o!9A-2a<{6rJ-}g53?DfRD|8eKKYq&PK zIy;X!hdTa-TkVzYYwhi9hipmK+tyro17M@2kNK8)mbtEJyQ!D)jQ$7xE4mxHS6K%D zcrtjW6`G&kfY&)Yb}(efRi6KgjmeBjkI9b7%*sG135kKXjL=6z%`i}6X^D6vF5HEwyJnvR#swqd0ZOZzXClJ6LL#me|w{7wA@Re)T~b-Hl!aQ_E^Zr4~T`S35FVBu@~3n~M=m?uQp ztq|))A)sxRC?y~Gr2-ZhP9G})u$Yrw7FgwrA*8KKC?%h`|0$LjOk6Q4CJt`hVd^BH zEjuVBAGqHk7Pz6mpaKAkdBs;{;^59d=xZRnEk0LDK6l^GSZ+9pDi7RZoZ*qViN}J# zHYc~W@|qWNTkFMfEHw1zC!*7zS-%G%Zn{7z`DX5eSmNsbf^tAC<~en>nThv=KsITp zlziCU@hofwf5GDb`?Qd-6&aRw**BU^C>zb@Q}(J8LRnTAC0&dJ=Y@vl2xY@^e9E4K zSjwvYf-*qaQHU)mrQ#1Fi1oixNe=Mz#R(bviZq*%1$;a;e9g7ViyTt)p%qe=9 zwS)VR;BQEkmV~-WOFnfcRn{Wt)y1OMs}(OKA+2;$Dfz@5RWAa-^1Ub!i`gNC*;)2w z63~hyOGjSCCVb!y>U?e3Z3{>A;cE8e-rsdKcmzi#`qoOSpxb08k`EQ-J-A+K&ps?akS0nLStfKb+$oQ%wr_#knj9CemhNYokX!CDvQ^=3dU zW?l~?hT!k)_^gyT9NIxTL%ck%#~V3 zA3&0jxp z)MDx3NTUwWN9jl-J0>kA2aYwuenNXbN#J`v$%jwA$HK!@9s}@En#u$4w6pZ+N{D-O zmQqco4CWe;vvKdf_f zm9K(zE#xX#qG}$2o?SC~Jv*@f9PEqmtJ6hxW_M}GH+%datl8ndYYl)GbKf|oe$c*$Gdv&_@f{f)aDyoH9G|2p4r zKJNI`(bT@x-qCj4mT3LMI?n2~EV4XpK4eZZ-7&pwDra1+zoZ|fx9Z+a&CqES4QB>d zm6oxc^t0nAeY!@%p+w(mp1bOy^?^H`#GmcZJRU5hPNhrZ7H-!(4E!Or1>3hxpiSkK zZfr*l*;v2B(uRG*9yt zX4jlZE;Y1P^Bh$XDh_vsq0a>l6xq1yfwD&YY9iDDg;r}G=^JKT;yOaB#DB&}P9L;V z{CX*Zy9TWgKQt9b3;Imp@1fjNWfuurF20Y3IycZV@n0~4TLLZB{JKZj&aRNMkqf+w0CwFGS!7JPqz(sq774XoX0)p(fDkUHN%@`IPW|J;}F4`+B zqbolsgmmnOO35dlWMPS6a6SvfQ5u|~emp`vrm|A<$tSAL^I&jx26EAdk+Q8L;lJ|SNf|nO1Ac>%6#AnCs|;Kn(7F^qNAoLu;MBt zRvxiTDf!T^g+`Tj0BF&}kwC|0frpNod3Z-cJiH^Hc>FJ{nIU@j86XxDy-SzD5spR( zE!wM;d}{wXmKr9J_CPIq5(%MJ_Yj{Pm*Gp`laKp~C5I~(?SNd&6^jsiE6!WmN3#DW z*3SN$&pdV$%MADM+5)qfdw36FR@*v@yuO{6mB!~DqdM({?8a??TTC9k5N@L4!wq8M zO!>Z0=2v{=S5>Blc&^rfEIOVGcWfD1ZRvCwJG~I>(ev0IQqy113b3COawCgcnmuSC zR!%Felzc0X8pYzmAZ!V^q6cBvaSdS|x<)Da%pc5U%N*=BH{(O@Uq$Xi%U%XN7$trIr|!k|+hL zI-|Kii_SIpBjp6wSZJr_X>UU6qNfu0WBp$cIHLJUd1!Zp6Us!TubkHWJT$B}Vuk3c3~e;Ij%k+zK@2Ux}g2y zzhH#(60}d?akboWLQXo+UV+EeN|m8!6ljn5o~oQKpdZ9{pU`swv|D`liQv&k-wPa+ zWCs(tca5jkU79a|>G-ErDc&UX9XbD>s`Iw> zaD&Tg0=oWzQu2Wp4`T{>SW`M~epVu8WF1BBaG?V=)>pVn1MKJMI5 z`@SUHzM+mT0{ZbjrQ`$8In3G@a?bPzV9_~e8F%@_IFjr2KIi@V-I(_ z5$476>Fwe|PH$(aVnE<%u`jTTK3bIRuDI?9@uE&j$+z}9yV;%sIcHu3V$nHg6yit@ zK!W|@S*7IT&s@ynLsE`DfG;}dOb|cZjYy~$j8#fL{S4L84uWrb1HI_r8<{@T8A*ue z%jf>{OY_O|CbD*iMRYG97qf__yWt=?T|~bxrz?2BkaPvPs;~;^Coe>=pG0zu5^K+s zGZxG%BxAw!xs0{R{{NuP+t>3Ey!qG7wb1#Gvy0;+`xSdr+Z5}s)|wV%{?_b(7ydpp zoHNwZkJBCeZ*TNP{sVsa{SUm$DQ11;%LcE3;zS_l&cSWXZ+FOd`0WnAw}0~*V}C#N z_Q0E*VtTs@Hya*DWFH$oDaVhW?8fKan#A(Lt|sstr(#E0Lkdc_xfpCH(zNq{b9lcq+GNoXAS zAA%$Dr+UQJKh@&{f8}F)2+Se~fTJ*r#6_4z4$H5AA7064Uav}r2LsUu%uyJK5YLp6 z-auvMgR%?iU?DE3bw^nEx;x{Bo&)s)fDfzu&jq08W^oA^9y+H+=7JgQ-SN2Zt&EX@jRwcHFEx|BA z7PBRI2y#qzPHc{k_KY9?BF6sVFFyGy)!rB0<;VnbG4FB^^1vBDa8lbnh*0hx#HU=j zjP1X$L(c$8F*|fh8ACe+wd*c9@8qsR@=mV!m?bXnFGvUCr-Vd=6Jqe22F*k{_f0adr#e6EDidoE4RN4W8rrnMR z?{>uJU6#o5R`M4N1>QCSzdv#9206d^f^dHG1)p>2V3rdm+abUy=BJm~Rdzu~Fzpuk zrKT-~ywvn*I*SaZO%ZHb;?)hB_Uoy{v|mrfA5>F<8S zUB$KD)yIC=o^JQr7TMZa_gmvEe_Li)s+!lEyP1xfl8t{GCm2f_mK)kRuR5nX%Q{v& zp4K1Jr|Zq`JGvSF?ajUBnd-;_HgJFwap5i5G>>E@HOgHo=q8XXn#Yl-Dv~$&fgc6Q zta&hCq^bfnnFLu+KC=i~4?PgnB)KB$9zp+T9`jC&r_`j{lA!yV2Q@{iEz~7}{?>T|ZNfoc)O>+oP4ve=Gi-*mZwuK3p{ogI*v1I?=Y!i9RG|6KB(WD>Ke4U| zl&^VjBa^JM6bCP9tS=`yF+C?GJ~k&K;B%CWg63Gc&Xj~eZ8;+XRT%{RX315BHBBFD zhMky}y@UPD3baV4`P9nR0BKZ*CZ-35(Z8Cvgmgh-xj+q91kI{S*HiWL%YvFie%Axd zxg@AL%F032oQtqSOVYea?9dJLHLK>^0wuOh{vlVc2VT&8MhK}W7{`qM7hX0Goc}+n zYoqh_^elDXaJO^4={)AF?igV|Xn)L>Zrx^m+>&A5Y%Xq!HLf)LYv`e0sJjn;o&NDR z@m~$R<0PZY7n!(vB{2(xA*)vSTu!~Pg8ypZEl)9SWilXG zxAF|b8A53|!>2sjk)^ERzZ!VDQ_LX_rHrB1=n18sq;r{}Pvg`6+=ivC>AxCyvQuRE z1zx!^&JKdB(U9$Ut^;aPqjl*7Dv4+?oz`zO^)Q8E6jMSxe# z83V%`*x@F{#>1+Mo-y42gb?5Vgm2*=O{|51*c%n%;Ex<7zV{CyzV{EG_|Ts$aaI3S z4-ktvaA0h#dcF1TNP>EIWFe?l7PYqjsvA&69{l6cCa;TAnAAzPuMyze*Z9B(RWDY; zWaa{3;geZt-@W-Kp}qMhpY}je*1YBYSDipB=6sCw1onLFMhgOYqXi#we+d?{n*XW; zAjMqb2|~(053sZ&jMpWl{;O8t7IUUYxP$vJ!dY-nDf#yO!NGFELcs!@ zA{PqsZZ3F)Krr)jm6DJ9{R0*kW?D1gikxX>+|ZRx-jxyr_(};r@UFjDU|89h09fS8 zMhzUC8ZOEAqAq>R=lxFgrfy^ZRU`0eb1fmKIuN--sWEGUgDnZp6nj&PInJ-_jI>+H*r^Ymv*~c4_w#aZNVR1 zJ0Z?sscW8Vnq!S)v168Fl4GPJ)iKb~!_n5!$Whf%%Hgozw_mlNvLCYVu&=X!VxMcD zY9C|Iw8zo`_N=Xit&Xj{ zt(eVZy=A><{l&V+y4kwQy3jh)I?+1ZI>b7_+TGgP+Q3@bTGDE>+_U6cPQr@^+bnA> zODwZ3lP#ky>6Ss3o|g8OCYI`!(iWHbf%%&GjQL0NPKbtBYMy7FW*%qGGAEe(m^+!9 zn`@iPnTwbWrW>a75Gk?Sw8^x>w7`^SnqWevWK(}rS5r$4a}{wJoHv~3okyL!otvC1oC}L zmT+1ecN~`;Cmj16TRp9fYmAGHvy79BBaNxXfyN%jw#G)rs>V`AhvB~As^OI3kYR^m zo#7M1T*Fku7(=EZ&d|%y!O+xD(@+*BFZqw#Xf@zYG~?C~X$948I;792_SX_=In}Or zkd{&H+V9d*s{JuR`jl!{t4p6yEq|``G1acbNK2@8X|MDV)h_mu7E|r~b!idRexE2U zq}sU}(uY(#^S!iyYNu1A`BXb)mp-7{$xo&CsrGAUX&%*%@08x7+An>ixl}v)vowcl zKev!(Q|+e%(z{gqv5z#1YKKlp?@;aFOVUiL?fX%hLAAX#q&%wq@VS&rwcYKc=~SCk zQc9!R#MM$N)n4x;4W-&^-$_HLHomu%LbY)PQZm)Xc9#ZI?bTnUB&v;eN{Lh(`MQ)q zwGm~dc&bV3r8uggmQpO$a!yKvsFpoKdWC9Pk4XcmmbqMdnQ9pwr2$k+yCA(pwbUf3 zKh=iZmHJUFrMJ|VYJ-25UZh&mYf>MoB|ahbrds?KsTbAadP*-)ZBR3*C)Eb}rRS+O z;HuPvYA=nJo}*g-Qc`!S_3bEiqgtPnQdg?=PLR4#?S(7SvsCLjM(Rwp=SxbRsP^1q zsUy|8KPh#fTG!X4XQ=k=_$3LTD$8~YpS))m0D4)O=YPi z)mp8Ro~ByMDpCuowb&s&MYX58O3kU(?1I#cYE8#TO{v!8d+AB4HEty}p<2WJQe&z$ zXfHLQTD@~pL#oxSBsHK~%x0-R)oRz4>QSxc0jVz4YGg`vs8-!8#ZawkTd6kHD({eL zQLR$ERFi5IjZzJ&m0u)Pr&_t&QZ=eQK2fSlwK7MfDpV_-B2}hZsdG{#sy&)6RixS@ z`BDX{mB^OLQ?0mOdV*?2CrIU}R>UDaPBqU`sVvpp&q!sc<~%KxrkZ24^cdCbUa1t- ztdpfjsb)Sem86VgRMV$P#i^##NyUO1_*12#RJ;F)RD^2x{*k;?yE{_y zQ0?|L$xXGJe@ZT@-Dn{>sdinG98~+$D%q*_$3n?QwSs$+m1_C9l7(tlN=Rm^UHVuu zQSHLNl96iXCrbvZo%==7Q|)YDNk_HQ6Vbm^`|S>TK(&+I&_7f=u^HW`+VM{4Z>k;p z4&9^L(bniL)sAdIcc}JLJ#?FDhgYIoR6F=Px=FPIndk=9_FYDQQEhJyx=ytp{z89J zZTBE_jcU76&>vLWxffjxYBRp8B2A;(w+Yf)RNH<{no6~8W2Grn`^GL!rrMT~(wkKK z`ld9AYMYXzH>kE@g*1_BUv-yWr`ng7qzP18_qy~N)z+St##8O{L6VLa#19YBhU*@3SsrJQnbdG9khoZAo zTk|_QL$%eV&}piz?1)ZL?X!>3Z&X{}9G#@v()s9Ds(o4)ouJys`_OT!E$N4Tq1xiF z&@rkl>V%F`?ZdO^XR0k2i;hrjerfa*)!yHLex%yG>gX`l=59fUs5Yk$I!Lv5z32ed zCay;NgW8N;-%D=?wY&-4&_1e---z~7&2L3}s5bUP^aIt#R7Sh0HhLrao@%2iqg_-R zu?(`;Df^YY;T_RVs-eB;TdMgI&iEx9DxM75-aXd~4Uo1qOi{f@q*+AFDO9o1gGgubBK zfK0TOYW=UH&#Bfg6|JG#i|f&9s`XAms{;G~3Wj<*@4Mc{5dS~WeaAh=T_5)5vCf;$ zH=R#7);YSv9(;tosO=M5L+f5^65IutXeno22X_I^nX=(7z!am$Fb^^Vtk<{J?a{rU z(=ylZ&QSgSc5q63j4viDCN&t@B~{Zh7&CHvhr~!Rfh%KDRV^=qM6QcOlqhaAsmf@xU(zZ9 zk5^;h%DR-1l@LQO9Y~e63^$BixvJ|{65oYl(=*aXq-FTB*>+ac^6BW1cE%RoNx{=4sl3>Vf;VZUCj`ZDhJ?sVbd)==6Ls3$aTOe(8+ z+@PvkC__9jlanVJG)iUveUMTFL+3d57UnqPTg+9e0jNghE{d3flXM{wLF5qh@!1eB$*$!#ff+f0N+SOl+5SIxd4hcX(10lL zN5lTVq%JlP|G&t6(cQxJw)3R3lEY{J&R)uvVqIgoVQFa|W!i2kYJ9=)j{dm5Ed1sF z%AdgffLag^q51uQkfpyI5|M$|{|)HAiX3NG-l3HI*oZ&hVqzow&HYzv0=ni2Oe3R5 z>}&+PQoK^~@xje)N{G#go%!-iUmZV0RMh}{%_FKFj?Zo|32{ZEQu4|FP$leZ=D%7U z$kVjWOY(5?P!9{CF26`A`Se%&vUUghYEh(*;HM$fEk4XX~yFd`Na8kSz?IPtpdcFN9sl+XOp5<=ozgii%rRel> z!mVse8IKG>FHI6i%_v<+0;$WD*(N|FVI^pS=8=SvO&>nJlsZS~OP%8z{!$H=8U|=Z zppMe?63Gijs2@#NNdXI2W*k? z-k}~jf>|P4DfzhPRL_k7?i10$4f^#6W^uhz@^R13Vyz4JYRUnw$e>fjo5tozn^ANE zp)ERrPkUxk2<_uhqLqD>CZ3DfzUg-(+cF1zQ$qHDAFpn+?Ubkvx?I*|StB`RJ!q zZ>U3PdKo|$d22yImya~SxkW(T&nP7y__vo?TUYmAEe*h8a)6RekPOV`0G;7HO<M?*7dGkt!g}p)0u#VA$)iIjS`s)Ce6*_UL=yYPvKF01P=yoq3{X|<9 z9j4+(0X+)896>)Y!L*Xw6*H`p`MAgXvA8f5mjv7>OvQ>fnb4ZgD01;(cg6ZJpqE9lbyE8Bnd--Q?c zuC@W&Xr9P1WbG2_$R&n(rl(SJ4K%mNX~sZ)SmL$@WYJ4pj2sv`)Covv+mV;uX0+qK z>^9e{$_Nf)rj>{>6Uor*J?0s0$?ZBQ`9}7ra%Sd!K!gkYvl2?YQOSZe5>t62WZtpn=2T4fcl8{uABt?=WNt=X_q#Yp%_flyg{a$D0{XR4AbB?)v z9^W(P_x*jpKYzTYS9vtgd7YVg&%EX}uYvK_9)M&1jfw)Sx!k;@Ln6WLkjTfi4q)xu zCUB`8;KuwBuPC^j5BrQJ91MB)S*2RcAuqsxzP7 zz%Fb8&`ny!ubYJ5%w5vrQv%)MQ$Dm_la2;l_ALQgw98&Gd319(??K3$_u!I0`Hv>w zHITQ6135Y7X`TiT)kJy&o1P}*O;7X5|31xjbJ)c-2lANj;=+ce_HOZ#gxZ8Pp*ElO z+Jh`>%fO{(z?vfX1FjsVMNPHkB~LId@s{xf(_ixp8_8KO>f+o7`t&} zzOnzvV3}bCNdRWi9~y;OeGn)#X*WDXpc@|ILtm}VLc^J56M&A>nPu+H9aas<8!$^6 zl<@}4ujg2NILq+@ew@y72)-KsOUzwg@ln(-!$sJ!EAtqG+wCr0P5m*Qr<{A0yS8hStAq1n=K$MkTT|=X*5Q^PEIAgPd9JyN^pe!d zv>&nn-Y_mU);8=g^mY8;$ah%mEA4lB=IW2>N9(TWW@&f(JdFuK%9db=#VGA**qj^b zo0R*;GFB*hb!t3jAAvU^s9!MhB{8|Tz?%?E#q0-IzDHpAdKBM?+$EMVfMLHQu1^gv z>nyN;;)*o>2)Pq8GV&8Lb0+3D%}&VAOG!w|&6V>q3Vie*Qgc%B6MQHsD;J)QO=#An zRTGo|PqV>S+p9DvTDzzxLB2a#0$+fbp+|fGaz}x~O}l%SI|%F%!K&1Kx7@x^f}OK4 zv)v@>tewDqsNFW=Kg4VM7fMRIGz+tC zvCJ(WHWu;vMfuI}SEH-IC9l$Bqi#9nCb5hH4{N2SVs+0Yd&SQ_VcR^paV#$lMQ>z8 z{IuLi{7)M7h~WR<=Z^6-8^ym4`JiCVucRBH^YnEucb#?BbEZ2s*-Px5Y>!w!wU)Dt zF>jQ9m%5u48NV=AGi2)D(3{~e|BF8Xh=Ldn4w0BgL8#rf2*TX+@)Lp!^R&#Q@gc9- zc=Ay4lJWe9l23D<|jW$jme4OH$q;z$yH9)mL~8 zjB_k_gJLiMi$0FQt4#k*PQQ|ssFmbFd{Z~FvE<;790cT|{gKLoBW#&WOg*lhTJpgg z{K0}lgwQ|$7abv_fQQB2jtLOtF#$euea(9TaJDf3kVT(usK~zjeD>*+QI`nws7rk2 zyS``54D&~SU=}uiC<$8>W@eW`U>{Io7$4xrFs`WgISUO}Q~Ck4=ztpqTJ`r3;*pir zl5gg^>%)leizBfn*m=Y~gm}a~eBwHJEHRuPB?7VN^CQ*9H$Oib_8q|=_8lL;mgX=Q zX6$hwITHV+VJTsYc8yG2wdt3^pga~ zU8wX?Jz|7AQQ0me&f@dmriu51FJ}+nkJFbkOYy4_;=aGBC7-zBr)+-#;_mSyR=snC zv`*IR_T*IRt*Tdp$H!Tf(U^@mLMW}eFKwXWT+ zAJvj+J#|g?|2%L}>X2FZD@RgG%3h>uORG5+jxdBs@ zrwQc=0-TZ&RVEb_U6`eB}O=x9~i zsvWJP1RQlm^rqyToJ?O*wzjbk#44X%S(pZ;h1|mOFcHVTOjTNkt~^w5%cv_>9wIOn;U-R0 zd9Z+)M9oL6ti{6IpYkAqN3KehA;+aWP+&-cT3N{DC=U?PS)%UppPxKm zCVomfKRqK?J1hGHoVG@M55g-=jmJkQBfG#i9-;&_tBVu?{V1}z*{MDhT#YA-nB%nl zh;cg0{Y8BGwAHEZV!2-&>QWrN@_hmi=as=9J>DWwz-KqSw*>o1dcIF5@S~w=BlY9T z_lobHj0aZkE8u4gx288A_KDf!wSzt_c>Z5e_o>b^(EYUQimSQP@7V6p+q>K5zkaox5$5Ur)RNEMLzD9ZPKnZhUDP3H1bdXJnP5Noty=Q&yK7FJ zy96%z0Dp?0(~1cEo35b={8Wcp@*C0ZDYpMW!lG1YM9i~pDSP~gMue@z3G(EJ)RK?h zbsCEfr$s4%F6y)>5DvY_jRX3L@fxuaPHh5Rpu}7hlo4~$aW)GN zrXL$m(?`0-34Oj_E%~PJph-OhtFJLYFMjo;M6}v}SKISM9QaNQrNVU;Kp~39_0D#AB zc8_*sKn$LxJn5S5b;yfn@4+J(dO)dGoq=jZB24MjA1FW#X z1;#DT9A6O934f|3pSbxR*1V7jY6K7q%LK&|D~BKiGeg-_WDMowHk-`glKua=VE+H7 zTtB*6IA=P(aMZM?+qPJ5SO-}ao4+(ymXb`*8P6K)8`AYJ>(2dm-u~a5Ezl)UqKBVF z{F+#CDV4D%er+82(Ow(J|FKduK~${+B|2z?_%*T8h^TAg&B~r+^S6BTetoI%-)w!k=5Ip3=5IdzxcV$TtS=t~ zdhzQ^h5jb%%cq|t@J~O2vw!U25iqNla#it*Al%GW%(hWnhgA+@~P3Cc<}ad z$VvG`d&2redp_%khAb<1I*Nc*yr+X?dI=sD_-HE0rSB8wrDdcV9UlJXMj5*f6=zbMhQ^PS` z7C?(XrXxqtA=6QnTPiMF)|PXHhNp!^bI6$jnn!0Fr8Z`2|DSR@h4xP6CxrEGN}+lm=3$}Z zL8(zY9_9$>HW7_XF3iXb=Ejg85-|E`w;>zNU_G;iUh`2lwBZ32@+_fIYD%q9LLuat zLIZ)7if`($l>p|`n|dLtZ@@`Lec zZlp_5o+|VcqcoTO#7q%-n@g=Qnj24^EMVdfpBJ^e4%r`%@e|E;CL;mKFKJ^Hrzn zVw=5`nv}R@&$;ou{k&A=ekK+Rh1%E%s~n`)tM5Z>2u{xjnDaSYOI*Dmi6e|6(|Y5=qTz$gMurQJ7GOK zOfC8ToXM+M)@Ff{iohz$(Whk%c{`}P`p7qg`p7qYYX2;jx@n-K0#J)`^o3F96=nx- zoKxt-4-n|X5AdOp%tAL0l-vr?qK*c_phG)pihWQy**#ds$*w$!#cmNODG%79PGZ8a z>2{oQA5e}o4wP}EQKX5$s23=?1-L~WX;5zR?Ib z*B_DJlaG|wEkCNuH}$0REH#92xqwXvNRaibt1mSQFem)76rXo&67s z4GSeZV2fWUsgCH#j{UBUfWK=i1Kh%bL+`M~rFVo5A_(O>lhu+>n|X<)h2CL}OYew0 z&LFsNE1A*W{*8}4@eqp*-){?Gi~oK{ap4p0ok}S8&NM#vgsm($^lEcldUdpe00O>a zlUnk@Gu~vu;cG4dxcINR05Y{)98;o!E<1?o}$1=l6Gy$`yd75rr$zCh;Re9ql zLjA^1eA+aPh1j6f^?uBfsz3_sc+%-fX9e%l`6v-@6QE!{p)VgPpWcSRNUCjflqifEtu;NT1KFlK0>9W>@T0nXHj z=8?4~9)i!uqlKYQRIr6>1svfPZ4WYEedBA^x3K2{_P#k4$d*q|5~PjOY1-hFdAXaB3x4g$4MN z7OZE5fOmihv3s@aQRH$(`$xjFvz_d#BKzx~ikC?WWkR5S% zUn*dB537$kr;v+I8(Iba!S{?0r`Iw|=~C8p^n zoBj*^1l`}d>6-n&eO|Ep!~c37d;y@C84AAG(LU?yBU-`s)ao``!1e4*_M0;NBD=Y9NWrZqJQ;<$>4VC4_B(71@ zvd|7(ZC$=M%L@;q!_(+FMexpbFw6Ml3Q%|5ScV-V}%=6N%{ zG>fi(5>!5RiWDgPFOSWrl`G9AvDIoiUAF!KQ2(fy7(P2E)i;3&YbA3$=i}ms$JFg3 zW3u`SuRFgWCl9>K_b6EjoGyYU>}9g>HClbObBoNON%(Jq8sg#^jR| zUNQR-VA5Wp9H_BxOg5SkH7d!{l_8@{68P8b2bJC<;O>WJ9TxQ^KGX!N?jc~$M5sM4A8vkEjTGx=wzxl>H~ld_;t3R<($ z;)0yqj1*|A{0Y?9UVy_X;sYOc90k?36}n3#4GlK&5vZ$GOeS5eQR&>E3>i&)cm~wk zA|{`8ZLQ(ob$9?$eMSN9*QAnjjowgs)0li#qgSrP}+`2PhuPapS6*G1Ux zFLIo6G_lXL9kf-qW>_|vubR6^b4{O{?lfi?Ue*7u@2*>*+2hAhfm|ykUI?WS6|NUC zYcOE}By{38yIS%?D2jh&BS0WNs4-xRiVupwR)Y%&>o4onlFz*4BFhZHSdD;LRES}8 zW;H~C0AJ~)mVEHVZ-;?5j3>C}%R+!l&!{CI{Bcb_a|qjO0N|p+_984E8u~E15Z;p6 zYRTtbG@ms%^zQoc?A>b61!28ZUoH8}k7-g0H3^j51lcv?HOnhSBC8$!6x4dHXoyTEe8&4Jp$E$Ze#gteKl1#0rMR|xvqD}3}v zG?|>?en~Ar7j?fR0zDKMLtxL$QA}0Ij^(KaJ#YwFpIif$#e`7>O)vhW~e2f^`SRd zRKON8{>K5EG)o;jB#hI@&30I{fhiE4C`8UjTSzy44y`KU8KU{RqfR1w$} zR8%IAico%~TxI@h7@v0fGhwv13#1LLfM_@tp*{YETJmWh)O?y@^I92bMQvWgY1uFn zg8M~Bwd7+@WpCw>{XYuk|6k?0;Ogvr!cpSrVqakU+;)dG-Llo9H+Pffn2wk#8b=yd z>c7`F*1@s)fBg?U)K}6S%q8ke725qIDBh&tQFUkuQ(WA&-yz$}SceZq{@KWKlP3B9OE4$G2;yo)3lCZzX<};#=)} z_D#7gJKU`40_>u0)EfjMr&G$}VbKhoX~@_<&c!_T+(dX2LMhG_?2kJ~U!f`FrJ zZxnnRd8e}2c9D<2PV>41OzQ0cU(}?2vqNmsTdbLC$wyv$ik(@Yhqn{h!&&5%!n{0R zb_xl$BCO_r)RNEqoMtBtW^NlNGqdqw1XX%eE&0gLzQvlkRiLB|Ao~Pu{xxP+L)yIf zxox^oG1VgErdoXRXJ)hHuoi6%*+ufsz)0 z+f{6zCb9N}@9#gfpK;L|Q+m-_hrzy6}m z_=>Ts;gBKSv&d7={f>LI>zZq^tB&(EXJ^L|N2>jI`!u`Nw!&81y2;wg@{VPY`LubW zbXj^x@|aecYUwZPr|T^`2v{ro4>tfwKvYS@W}_%48v+U0)vtUY9`zQ;8JQV5ntJzh zjS=lw@%RU_I& ze_1w(m|V}%S~NB=9*p~-w?3G zi(V&jXvy0||9-41N`5_-H$IiAPTM>sihpa81a2T9znzk5;WYs@(8YLgHM1p60@q7y z+dykjT`uzGnA|nfes`E^sIx?VRlsGW$eKcK4*8Yf`F};-$zcBf0ObC=)j86!!v3Yb zu5G;aMavaSJM%-*7g8Nlu5pLaW*DGf34itftv>aXiqMo6p;K4L1s!xUhHzjd>#ZAkI>w8}lHwoU+Apk7O zJE{fN?2`#~6QzGNDWiY9H-$Abobe0>YVoJ@K{GQhD8lS5ua^9-v1c613}=^vfLYWL zvDVT=3%UA>8*L!SjW+O+-}SP{;DjCs$fBIk6q&^1t4`?RhV2M#!*+by-5Ofx6a(VY zDU`dE+TmAUv2gt|Ec{L_*1|B+^#^A06P>~wWdz>Uml*r5zI_I6=58?^8=Y|7(?4eh7c;0sL_be~glIjbPu_MJ@UG zo7vB5@ch4qp{33<*Hg~@w7aoumur~wC+8HW!?DKUwePa`wS8qvwO+B#w%%%4XYrcf zF!zy;K=%LBrfiemxWrh+u*T3*zf0dk_p$B)9dSOAb7lc94G3BLcS#QY+J1@ z+7vHe6ndl8^0z{}4yiCH58Q#cdEdk` z$C7fS6V^QHslhdVEwr=Z_R$(cR{cuANm5ulRqrZp<(C4Ef^Sk^sEx;Cl6F#iE*DlO zQAysjFN6l9;U7||F4V$fu}pOq(OcP*2>ElN9VS>6?WMu9+oM84Hr=A|Tq8_REmRT|O+-gkipN`H;}=AI-}xe=77_q*SR+W5HkUU_1iBBR$Li_X5z# z`Tx5*Pha;!*D+Tu=S0VL`=9o^ZI4*@TW^6l|7Fq-QUaX+ziPN)=%$~kd-uQD@qYmP zyjkFX5%1?!*1jA+@8CCy2WIe_d=Jb?O;QeUfMv$T0TyaNq$`1N4;rnOeEt)QSO*xm zOD6)qcz3D7AKhI#Kyls;*vDu8zAwuT?$QasF5X=lVh=8sh?V=-Q%gSaw|iM)=q(xX z>@CrpBZT|DVzuP+f3uwB2X|>Y@QZhssuquQu@LNgFRLXV|Lc(~KAeP&2Ym4-VGKU) zGJR(d=Dsud%wK9Q=tKBI8Ze6wUr?AeX-oRtN|5{9%18cUBWq@uQ+$9Nw>c%;X+)Us zc}6Yy?8i2+?9jtgOkwd7+TNMo^KV2%Q8@dJ}! zhg_9}wf#J`6^ci`iAL1+{qV4uraO2R`-3;rIVf7_e(2op+~8d0Txj27Uu$1xpKG6N&$N%R53qN$x3t%@SGL=2*KL<oMzI>kjKi>uT#F>r88bHO)H0+Sl6A z+QeGZTHb21T(z9Dd}Y~h*=2dv@~oxUGRJ}}6D*@F{VZK9%`J5-l`K~CU*-$&s^KB? z9`jc7I`eY#Jo8j@wt1X+khzDswYk2zirFdMkV>Uf(oyL{X}h#RS|u%%W=MHbsx(aM zEwz^#OVy=vlEL(=>8$CvX`gAQX_IM{X5$~m^TuzC z2aUU(Gn{$OROc{fZ)baFV`p_|Ij6z#tK+QWxMQDVr(+XDVk~ydb`&|%9U~oyj!urI zj#`ci4zv9a`+55}_Jj7_?k>hH#7-HyUXlrO_sA_PlJ{_0QV!)kf>HXc&V^kY{04=22u)*k2 zstx%7Euh+4s`dXBJwmm9lhItNCH{>brrNy&(HyGv`2;;gwcdTvY^wEo z2hE~d&oO8w)w&-=0jhNyi)K)*%PVL))jIb=)2Md$ZuB74Iu1rtsn&iwnnJa9ZO~+@ zwMj&NsK?&Qb;SlnvD8U z?KeHTk7~b6K#5elVn+8;t@K&cmue*~Q6H*Z+>3fs?ZRMm57o|}MZKu@Q-9QxYCoPw zJ*ake4(d*|Gv!b>s{Qa7>Poefdent#-_JyysrFq()QM`}tVefK?dwLUBh|j#g*s5} zi;Ji|)sE$$c2qn1DQZi#&&HxQR6BeIwWiu3gj!MU;6JD()ea0sEvWX%Nz|Nb`zE1g zRNH$5HKp1|Lr?lMK!4Q)JLc~ z)mDv1)u^`8fvQsN$yd-FR9jvjRiWCl?dW!@6@Q5;Q*FsObQ{$k--s$vZBYkQk!lNf zq6$=dv^%<$YV-G@@>F|d54weFb4R0cRGYI0d8qc#P~@iCtjownwV5rElWH@LA_vu` zcSUxpJ$Mq?s5Ui#tW=v)8Cj_2?}p4&lRrli)rxu{6V(dNA|uuE=O6>s^6DWy)pGYC z9o2G%$p26+>wEbI)iM+1zo|B%RK8BNj79P_s*OJ(|3$U58S?8~mnx zk!piR%NM9NV4wUm)%w?y&r|KbV)-Yk-FsO+N435)v2Z@fok2Z$fu~*HB~-IwJt{a1l2k{Cx1`1ySvNZQLV#S`CF>BpC^AqwRTP9uc_AN zp!^lpT6d7Yq*}}G<>ORqktcsawPvz>jA~77^5;}*k|!Ufnzy|C8PytXkdIKUVLSOS z)#`7M4^i!|zVfFbZE5|QD2HnG5Xz=noogtIYPI{KOsd_v9ZjTKO)r{2wdyNT2Gy$7 zL+MnzV>230wJJkV8r3S7A|KUmdl;ost&$$4P_4pJluWf-E1@K+-LeIZqguH^Xe`y- z$I%$7xnwk&YR+5HD5}{XLJv^QRuhe+nk5z8Pc`W<8bLMFBs83AMkg9ZHGLr(8q$jY z*@uQu?M5v$m}=K2pg~mo>v=SgYJb*41E}`<9@L*|buY;Wsa9v9e1K}Tz4Csl-FZO% zglaV>$@{2Q{VVxns#U8f@1@!uugf1%tx7}rL#kEYCx1Y-+q%f_Q?26n@_SUPkSFh< z+O2l^U8>z8%e$#o?hg4Ks<~&&yQt=}%WqT7;g@$(&2~|Ki)z+Pc?Z?Z|HyArO?p(` zPBl|4`34EbrQov_KP zsrKEA@>5j%wvW7uYF~dSucX>n!{ilIJN||IB-Os?C@-hl=ZEAcsCIOiyo_o`zLA$w z?eGI~G1U$pm6uTMKm&O()joMmemr>oUrG0Z&XWk||A$=FoSBX{9aj4Y+cVamt!*vy z%*W03r9#vDCXdl)c-3Im4}rfN|388Hfl?zlS48F6Ebt{|<>MEXbMt&@)TdIQcnk~9 z@_j0QPhh=R-askrsfC>?Q`jtD7QCdMpPrE$I#te}L%cxwbNIy9+p@%U1EqQ(?kVW5 z86ge@E)l{!<@`IZ9-s7@jU{awDAfU}sH6xiDTH)Im^W7mGsrC?%;3*b7P@YrWV&$k zl523Gj*vqh7%R>xIZMGhpe1QvIZAtmXS61x5rsvIJ}t(z@iRs!hn+tQzrTfLdX+J$@rU4${%;X zYHo8v?%*kaEGl=fii~~RX<%VG2WKoIycvu5yuWx@6GLRrWZ)GQ*`whl2ByU0PY~kq zC-}sdzh{XdWrH7xMWt*|iG#7KK?8^SLz)s)k~V`+Tly$V3tbq+p$n_D-l7bj976Wh zAO`l;;3Jnj!Xm=~jSR@54rsy+42chX8tRmH2zAOkeCkWnSZX*mEdpv$r=}6qsX20X zW=>LS$k@qdf}L#UV_$5(A3k)`%6bBnCz+pBX*`FYf?9WI3Q4{P3iAHh(S$vulWi=ET%uc9BC`mg; zl##UKOh?w>K%Wy&`kSRm8D5vPVt8G??N3)_=^;`i8|cMHiYT^MZ@&}Pq2xi3;-Qc6 znNOW&n1lEKYZ}JrjPDqG7>*gnKpucQ;B>#c>$of1`M2{?XHCa;N22|dy%0|0SK8XZ zDSN8r56k10rf^C=PC745k;vMZZn=GAY;q+ExTRN^4_jsRIlx?Rx;Hl| zKi?btxA3V$9s&1eH8p0XC3*9FDLF;HJij+3hh*VIZUOg_wAFf3Td8ey3Ao~=sVq4q z&!1ZmvZ+((Z5nkDL_VufBJ^IAT5nEnMhf(t|D~xX1YEt;bR`Ib%gJu8_FPA7W|f?R z%#7>=h?o+0r__|HDxE^cYKgdfCV)bY1}KwD&Q9KO{(+e7bF!F2Dih= zA|M4YsWs>*2-aX0FxF`ej0+IAM;a#uI>$KSFsThTGQsAU1Y|T0RS?{fV&^t83drF? ztI_s6Ly82B<=7@^CUu1z%1AG4Fe&>VZIg7uniO*4%Kr#!QZ)Cgd_%xZbJe$?%(2Rb zO#WNInkTHP&{j&mF5t_dR;F=Q%GU&pDNRkJQNejg{!73ObG0tj1S?j`*e-+q8!ktg@F9O@8bsNc7 z1hy;O;Uiy;$4)8IRRhs*u>Y^5TcGpY?|$C(x2vmjf#X}q`-g0MY#!?%%L?-ub3G~7 zw9Di&jyAlezozdEe_7C5N1xhOdsi;E` zmK2^8nCQz6^@v5vWuQg;%RnnDI9T4sfzk@VE9wwL%Zo3%g@70CB!*tNlW*YinrDI` z(&knG7In(20nYd3=V#RIjI?G8NO82n@I2<*`t>HZsOU@;zQ6-IlvbcG^E7` z&vKF$dajaJW$tJ`v|AG-0@Jexpv6wl%1R{M9ZrlqM=|!CJ$!E0Xx7+m1Ep@@7Ih0> zW9+C-bprp;P_^X4J2kI5z-QbA@M1sXiqW&EYo4IaQc{x4y39wm?_li>Gl~@Ql86z*& z^5l9Zcv3xMAV0t$Pok%nr;De(rzPYGsPC!esp_fZDd(|6zJMFt5|%?q2L(0C@x^y9?ae?sRuDWD^+X9^mfl?&0p_ZVPz@ z8oTScYr3nrE4bZmtJ~nZ?z-wKb)9#ehCBnuT}NE|T_3u3yLLdnflaRUu4i4VT+3XG zAn(9z*EAP$<+(ClX^?+lq-%()pR2d4o2w(_A!zDq=&IwY?yBr6?{d1#j>(P!M>gE9 zPj-xQ408-{^mX)rTlQ@o%^i&$^&B-FRp7S0+hKJW?APsA?WJ(*{?W-V$d(9s5W3jf+gjS1*y`JAK|X{^wsJPR&1Ah{{R8qMT(F+C zp0IvpJ!(B@-D}-r-D%xsebu_bx)$;zEVnMUF0jtA&ah5~dR zVeMpXYi(|AY^?|R6RKD%Slw2u)nK^}c@#=5=Pjo#-&u}ZjzB(z4=uYbJ1ko*n=I=g zufi(JGRq>%Jj-m$G{~=zXUVjrS;kpLT82QLh2EBKmX4OzmZp}5kZ+;7rLv{G#c45H zbdY!9SMw$FIrAy=H|ArIe_@~bee*8!cJmhVM##gk#=OE@Y+h)dYn}=D7>dlf<_YFh z^BD68$jgvu?q%*`Zf|aBZUXrkYMHB=E1Aog?Pe3?Y4}6BB3+QqN++bRAYa2lX|J?L z+9_?5UWL33Yo*oFa%r)&K$;`XaOs?XIe&Fta-M^{6yG?HIS)DaIp25gg8UR)oEx3% zoNJsboW;(C&biK+&Z*8KXRdPs z(xqf+6y%Z^AoZ1cNS&m%Qgg^DQBSHVRgo%4ZpjL{C9a#Uno3RQ;RTNGAjiZJ(|*&3 zrro9;rmc``V!i2E(<;+4(<0M6$T>01giLv+OjDX^9ORxDV(Mq=ZR%#~Xle~PC>omT zn5vs9o64J9E9aSEC*oOAIpAN-iKu(miJ=W7t20a_QvuaEPG+u6U!c0 zcE_?CmR+&zf@NncJ7IY@mL0L|fMt6u+hN%j%QjfH#Vc8VR1T33i z>BX`!mW{A%h-CvT>tlHrmi4f#i)9@wYhzgp%R8~GiDeBet7BOW%c@x3fn^meZ^yDS zmbYP93CoH>iH=}-7|TOgev0KmEDvD0AInd$+=u1ISnkF0BP>6}@&hd2$MQWa_h9)h zmbsW5Z@--~CV7VE~SFwBr%S~9mjO9iw zU&3+&mM>zt9?KW7T!-cJSgytLIV_*W@)<1GVEHtbtFe3v%T-ve#Bv3ePhzmUFRu7|S_WK7{3LEN5Xk6UzXW zGq9YFuz`2dz9vAiG45m*k#au}9Fu^fWs zU@Qk=IS|VMSoX)VAC~uFnTX}RSoX!T50<^Lya&r(SoXxS2bSHj?1p7mEW2RY8Ou&s z-i>8PEIVM?9?N!Ew#BjymaVaDg=I@DTVUB7%VtZ_iEE{6k0L%JV z-i2j7EbC%f2g}-6*23~mENfy}1Iy}IR>QI?mUm!T1MtSXRQaB9;}fycNsx zSl)tVIV?R`y0LU&>BQ23r5#HfmR2k+Semhvury(5#L|GJ9!p(N%Ku<_1Ixd$ypH8H zEdRptPb~ky@^>t+V)+}Ezhe0dmRGR6jAbd7C0Jg<@*2Xz^H~0bW#PTeb zXRtht2Cs<5+%y=zk(nC3V!@6`0=mc$G?If{|bKm zEBNuR;K#oL!oLE-zXHO)0>Zxn!oLE-zXHO)0>Zxn!oLE-zXHO)0>Zxn!oLE-zXHO) z0>Zxn!oLE-zXHO)0>Zxn!oLE-zXHO)0>Zxn!oLE-zXHO)0>Zxn!oLE-zXHO)0>Zxn z!oLE-zXHO)0>Zxn!oLE-zXHO)0>Zxn!oLE-zXHO)0>Zxn!oPxi1pgw3u{?z3r&u1u z@&K0mvHS$feOP{sv@xf{!Ou-t{^+gR?z@+~ZPVEHDN z+p&BD%WYV`j^$P?U&C?>mYcDB70Xw!+=S)JSZ>7fB`h~!`68CVW4Q>+ z$FN+8<)c_Gz;Zs8^RRpb%eh!SjO83GAHs4rmb0*&iDdxG8CXuoavGKoVmTGdDOgU% z(vKy=QpU0f%R(#*u*}CY56ekd=3<$HWj2;sSY~255z7f!W?-3)<#;U9u=HV>ie(Cx z$yg>~IS$LQSdPJRG?t^Vd;rUlSl*B22rP$VISk98!TA3>4Mv^uLt}r#w}x!b!=BsR zFS)zGTL5{mFIwWP=Gg4$VgC~1|MjpBZEihm9dG%|vcyssUIM%q_Etqw1=CZe76zk! zfxeFJE!}7x4c!+ItUR}0L zBKBAEc{7ueeVI6V)+->SQF9!W&z`-Zal6Y}#?5|VOr<-CjnAN_~a zoRs_oA41of)e0j2;9~1YM%$vR2P0~_P^s2iGUzB&2Uf?Q=`VB2L!Ik z3qLX(G(!v!IowB$1jMY92C6aZ4TYHy`>+c_DTGl2VS^jjq=ZD^!ChZK_$xJA=oNWf z*IfdF{+YUh6J=Ub3Iv7W+Ug0eEtF*h*H%}+4FINXnK|QeHFX4pH!{^IA!->oj{~YL zw!<^ORV@J*G)S|^Q46|L*lHjc!Apj2a5Yd6FrM6 z3tJ*8=8S0GZNfT#C}I^=5;ol`kxOc0{VVuwd4agJH`S- z*j{4*78SOq=^N_qm2mFarIvi&rUzMG=pBvX)jOi@feG}xx2Po_K0y<62r*?10bW#0 z88No9lO}xcOjb)iXOmH^k)cyG5Z)=m_Tz-}?JjD`=k+GCyfEtO1FzUo7rv_}pqt96 zB_Fu4!~(?A;6u9QhW`MjavEsN)ki)I13WVTSd9SX7uH?Yem7OLwh=b;AI) zqaW@lz1i^^??+&wST4mKl=y)&XWw$$S|*E8Y$Qx$aZ7*%a?O0Tr4L?EATs+N4%noqK@tpcUh0oErdSUS`LqI;wW@lzkEC7-;;RF)hrqgDfQv6oSa zGa7#$yd~pZ{w;~78%w&RRCG+nn#NqB3@pf5HGLKC$7R?X$tQDE9yScc?P;y zyH2{AIRlPEjvDqf+dAtdYXeJ;`7P<1)WI~}xXY+F^wKYYzxvLZu7Dmp zSIoadr`|?l_aBt(oj>ricdoqm4;CJ}e3y83`KSjvqyZ=OYRR{L-&fcM!0oxt(16(8 zo-4!p!3LzHCuL^(vd7aD=-|GYVff zBFtYm;xqS5W|?7%?*Pnko8pOkPdiV3sW>IS+{GvFp}8yCB~aQP$fv}sw-fSUj$Sz@ zFV!19Uw(0snE#85{6=)scpf09LOW~boU(Pbj1nqxVH`&bU2yX&WHw}GjqEpW$e zs!7Vu$@XXE6y`_R{ixzZIr=G|zsticf6G8=8{kh7-g%NzQ*Sayem0gE{vlg!jN;K5yGpmKWBy&4D*|>)U7nv8sJ< zz9afX$q4buNj`j=ds%pJ0W<@6u`U1=Uis97?7dHMZtt7KM{cco1ORewGzDZ)IX8$a zOF`D;+}L}BbdSA9__(duQ<`A>e+@%boiW+)r(uET5l;>G>+Zg;?_HVBEATG8-tj1S z1D>}xvb}C=Z+*|&&+?UJEZo(eX0}PsNR3Rdn|c`c8LH}E(zk%PfCq?cAe-dXj7c2N z&AzWe$0J=5pn)-oL*Z4XP911KOj0%Ss*1YFLj7Zst@LK~YJEyLLbP8@f?)n#g)rvO zeKF}UyxEBkaMbL7-0cy+1k1z!YL@LXeywObP?Q*tj>!h?-5Zm*#4?&1zR^Z~h1N>q z!kVW+>Ns}KfcnHF-1uf~CA9_zU+)45ymz9yj}rA3e$(O}p)-scY8Oh|h+}dcJn)qmsG8K7f|9%adeHx zPaAzD&?OEt5k4r@%tW1qeqfZr6ZHerDK0ffaZaMUV{-GSjJ~D16;a1{3|Xy15OtU) zflE*D40Tgi9%>(x`1>*ptm($>;?bF+xzAABJP90NqD&pl@rByNWLv~pQiohtsI};- zLe3`CO4#)V)f1pTlhaaoO^SmDwTQ`AjPpxHUnMjr@&6-qo<8m+kWa6nGuyGne$C#& z_7G%@D+hc1jb^=cpJ|!#jL~aA`rUe`Zp6O{00_Y0%t&y9h(DZBezPnutesWY%~D%U z>`}-TF<>ryeKQPPsnKI|5j9j<@$2KLxp|G3#8CG4TWd2uhHzPOi9JLDou3lX{Z z0BzhNa>IQ41o?szv2dY`h=sw+S#+2UdjY!m*-&vhQm-zdK7Up%`34`Pc>oS(lb%2= z{?nsSGv^Eh_ox19$;Te3XN(;@|F5Y(qcc8gtYvuJFu=3eb0_5I@8SB~mE!!(`LNUB zc-(P^eT}^Zya<>G+5b{3zd?5Q3g+j{O{E>+8TiJOW0Le|^s?TqTdacvo# zN#5W)gD6*wUzw>WBRiuYBZ;Kl%ZZ6=j@PV=tRx&wjj~fE*hz@;agrSb8WfX2fr$1f zmpim;|Nj+{B{A`GM%a_-jcJ)lB(f@v-%*k0?##|T8k%C4E zS$L~gW|i&>>%`C%Fs2hf5RW-RJt0IR<58P>wukN)8sebXRnvz?2>o7$pQoYWLK_(6 zBn%A`v!PL@AY7xGCU>aN=@nO{IekJygmz9`Aw5$>gUR`STb-wqdzx#HOYiLGc*6d* zy^1Z(y2WzM($l<1`dqr*lxBRzaNUroU#a_1*EV?mAAoBPx!~@I-8F}ZIg43nlWjA0 zZ!B#vLoNAkjv1PhTR54^0bGG6a||xC`6jIOm2iamWrQP4XHzo-^Xz2mRZ@t z6X1H}D%a9_h;QU+cQL-C09@tD0^rzP<>K`TWlu?X>s(VyKJQdbMie+t%miM6=ZTDg z(?UB_f?B(;TJn*nv}a8WUdD-lEYQoyAZz!x1ozJEYRSi*d^d{?mYxtdOVeF4L9OXk zOFpu{Jc|s+EE#|-{+Q(^du_s8eWhCR*=0>aEpYy)1G{+Vzq0%Y+p!bmYUKQRX|*!W zpNrhA*&!}yJfMq@3sTTS`+fp_$7Z$U+q>Xr78*`0(g0fgiG>Os@*WV{D&(#ErB#OV zsq;T(sbMbh0ky!nM7ybDd=Lb?a;aMKvGc-%Y*GPR;HO-Rt$H#D>unFKC7*fH8?32e z`H>P=X2l;uSSyj^{iT)4INs0ITy%!qGReT4FFY_v>C{oZDx?7wmZ~M+=s5+f(P0Kp zf(D46!8Hw_+gieWYbCYhvu9_p>@YUR0ejrWCgb5DxVLOkOFnj%%wofLek@=MTv2Jq zCVK&TX}LiJx!fQ=a^@@+8M^tHcy{xs-X;R>KCYJh226a4Z2)xh(edo&;XW(E?2^@z z&pu%*%MKw#qkvs}2$3>Gqj|mvxARuDup7_nrZPt=lc(dB*EKHWTU*#z9;rfw}a8^J(u zdn-H3-hKJlPiW#-8U-#J0bAVWonn)~GB`{iyuIF0OFr+?-&r#^3tTn;ueddLIIlM& zJJp9m)IG-#>Yiix)Wxr})GY&-Ay7tOBBTgvI3_5}@@0n-mo4pnlz?|X$_HPvjs3}XS=UN1M!TJq^1 z8^hAWN^mOBi`(!-(C0(&S@!rS4d_S$Czp0CBXDxzK(+zh0;N-+0n>%8Mj{%J=gY+J zX6C17Tn}bfR```0xvQvhc7X z^aH%O6=5WNc7bm^JX9Mw>9k2CEohU-Z^3*`LR@fWA!tE7KCH?h)_z!9kvvvQTa}T= zYF-`I?y!@Pfm+;7BEs%znK?-XQLNrlB35rH@vT1hJj>rcP+A21Iq@62zU;!RDEQ5n z6a41O`S=f?WAVZKh4D2%Nh%Q8>6?*D6-%3$`TTRfVEG|IWdZPuOHdineInLn35sVi z;bA`bL*KFBodTu#04~R`-#|-z1sPesD1FEK6X`qNpZHCft#RnWX+<71As$OhWx|QF zv}`<=pf{e&N1vs+eGRkyBtVbjY#%Lfosc*DQ!V)|n7N+mKf(C_8v4I=#tDW?2ES*P zr<{A4yPE4cR}1GG&MuB!j_&qP>`AtZHe{2mORbG8J1o7;$ITPXCh2jhn&~A|2jge@ zzx8wV4&Czq#4Di0b&+=uqr^N#zeVsLKHYxv@4n&=V#XkPe5wSaDAu9tbl9s^MjJh7 zk&w9Bh{`qn9z7-`;wz%kXgwA!6x`rw10CfFZm?2m)CR}zZi$eLar9RWh7bkgKpzzn zCatZ9xLn8^;tPa?nT6G-P6#*w=6oUfn8IqLLlW0HPw>Qt1HeLyCS2tsF?nhH=5wub zYiF*IxM6C|pbuBwNT7!Wcg|pCYF`NshB<;eXM}?qJtQPBQESdnKM6K*wvbyww8D^6 z7|jy=<0@x z{;7Q2!yS(3K_OQZBI=FeDnwHQItjde;?}H6n{VpnLsMdsw(REL4h100KZhpAXCapn z#j}R|f@deS$;x39LQ!@{3Hf<3+X^Z5MS8Q49Fte+%lvU8{7|SUK247FAfZCRp900$ z?5ChW@V-;6GU~oFpPc`1(s}y2pKzUr_y1(aI}V%u0o#+-@2q!NlFiRbKS;GrNyfE? zZz0eB7~Q7-WS1Z7zY7uOmxJ#s#^XSY?APJTLcA&yXQ?IMyYhJPyPZ z|3dipiBM;d)@Sx)5%0M5F12Kg@%2$pwAdS4(yELtg7kgixz&4;; z;PP$IfOs5;DGj*kr;;?oH&HG5zr)61Y%|&hE?0tP#N$9rX-3!wmq4c|4#t!}`S35b zW8v=(T&@W4@o(8+K?E{x@1^##(Eh+pFpLBvfcAQ%B@n86e#Rv13kFWV77Y2lTv=TWpx{Sz~buY90 z5b|>i@W5j+T@rXtvx0{r>K1$wz-q$D+f$=?3&T&YRKv)`Wcc0k!0};F(X@7BmQ4 zc0mioB}}86WW^~>D2FM*GsDUVo>`*_qlS1wC(y;XGrvHJB#WulsU_$+CcJ}`OFV;0`P{2tWcx;|z-2pd$0H^WbJJl-$p_|<77Wbe zlRu^DCorAcfIJ@4IVKOe(Pp31q*?YRQLP zna#pB30$@SthkFLbnaje4hU+Zve`&1W3#cs$0EZ7Vg}@ROdw&$4}|*OfojP&^pk9~ z7dijGp)-y#{A`%ydD!D}KklyLTJEameBRl?@rh%Y{gge&F4-2@s##yNcC_rX+;9HL zJk#u!R!R*`+f4(EU+Zt^i}ek4@9Bmr`+XrP4AOl`nFZ-Mi(XQ8K}JzVULiid+9Krm zYJ6T&Zu+Fmgh_?IJb%!=yjh4NTdgLmumHzV25Wj%NKI*l+4yopegavj1Z#Rlh_@@e zCT~$vUPe-KCQh-qNw8~AS%pQe;L&0sjiu9wx`d_S_Wu(@N+N#TR9|jpj$gT8fL<07 zd_XG=ei4H`ccYN=R&70@ev7A>mxP?RhSiu?2s2w2iFeo_q`!t$=tI7g!r+}J+{PD$ z91w<8NjnU#bG?x1o7PE|BIpGnr#6~uLj5J!LDvcHF2NN*=*J6I_`Ki|ftMVbvA$Nw z*&j7&YL1)@A=as0+GBzZeNOP_k(^=&YkF4j2vp9?+0WxMLgE4#oBA?+1->wgt`Tfe zasm~!=+lBNs+@JP7F{iPPE)GXjK!w}|BC97o@O|%5&&g;Q9Y!kn_K)Gt;rz{)fG{ZNBw0YgJ2{`Az8` zsh8<7;}^yThHU-odMUKazxm;Q@R+_SxI)Ao(?{7i6X(Zccd8}d3G#6w>$(Bn1fjh2 z3rv0rnAQmAqw~~~&->AREHC&Vn*gskA7nT$yS633^N*<|AN<1}EI6FUcmZ78c}xVj zX7Nan=iQ=~eDn``vFLD`(HPLhon}yUWtU4R=P0M{bILe%f4>P!3+DojfL7eOfR;AY zKZ1KY!aci(TJo*@UQL!8l4mpoZgI&o!nm0oH^H5GS}pn5dn&WoFd!QMc02|oJ`@No zH>te?vk7=$HXr<5O_oDAhp7+X;?7~h>`jLwC7)4;kk6>YC*LixCWqsUyMSEWaRwzP zJ_G_e?LD>R!|uAm!ot}=J%AN=HlTqGjmFSmd{9Z8@n9K=Gv0oerG~*+7pUVg7{mP; z#K=>PYRNbD&TT9<%zbqLJ05digja;{PJT`;`P^?k#&ScLS8d=H7v@DfNp#-|f%bP( zOFsM#O{g6#p=trVxFsJ0kDVByzAc|5yz)st@0*&>In3C10&hHK>_|Tk0WJ!tB_Djd zgY6}-gsKVP@mNAB;B?Lo*}SkCK`*SvN8h%JMTb68BTjvUcq>A@`41A_{0I5GuTNun zp^sFLQy)>hD~#ug0O#4%k`KN$iv@?TdNlx#$5&ke4=qSSCeK|@$aB~8$zRh1OhfOk z8mHc^kVom=IZ6hPoH8nali;L7z(x;1>4*X1F0LqA+-zPdHzBLM{2cCp5zaCfDx3EA9gv&g+$Z$>}*c z6Y0j|Rw5vz{QR82=Kyuwp(vhqNq2H<5PcEj-`f)wJT7ITQ)?e z_NEqQ<%W972E}Q#;TRwNTg^@n(7VJJJu3qojOwvC=_4}%`F$iDWa zCXG|mz~#GvTHNaa5%yLd3L?;JmDdB-Zswc%_$%ztgig{izMUkrmkM=~=Q@%WJlBy= z{>56B9KMwufIKeWO8m`%lk4CCHl4zs`G{~o^AVr>*gTdSEZ#o877rbKg)F|N3n5?A zg-`zZ<19J&2-*R;I3Gbo2T$?k6=bAkq`=h-YWCG#3H<7=eE6diS$Oa#wFP)_{-g+a zyh5hfs}>M!*p<$Zmex>~s}B~}Um#@#1Fwqj>H6hc1KwHrSydJr*05~=J1%S3+`?pU zeqnN`m#kP#h*zxU6CV!GjoccDYb32Ozr%n;?aGw43F-ipIAG?2}>)W z7I(tJbdOXoweb@xh>f3E!ME|JCssRjhQhR>KRL4BGgM?;!_{gB&>s7LJOdd z%Pt`$DJ7lm5{fGm-r~x9-UCmwR!#_9ZVtTS9(!T>1RGXPSQjfho5fG?nfE8N%y2T% z44B28OsJ>dYH&J%U8Hn~MP+n|eJKoVF#f-$p{~w&)R<-X$FS71$W!0F-JR(A+Lh`o zbxw2I9V;D;>~Gk+*$&u7ThCi(SlyOqE$z&onm@Up3sp{{_!98>VrEkI_(Irp2B&m%NXReBR+mzkm*>k)$sqN8DkQRu8R+W7gkJmqH&yZz zd?+a^H`AA&(5y+TCMW^kmxt%vyy0nE)Hz3UQ$=_`Ov!<}F%>H@F=MR`k(C33eU=E23U=^r4VD1WcopxxWPAkp zqyDCl8)y;LhCFO&yXY?!^^Ku7L=Q%-R|{opAoY&8D|@vCK5@H@l<(5dVMJSk;iGe_r>4;xzq#rwBkM9kGuz zhQ1T3b0XiDojN`*Bb9X+5GPG(W3}Xal&(L|IB9~3_(p<9Nn9en$QF3ByanKTU_2fK z{F3r8*rhTa2D|2G8vxGI`=J5i9MVx65S#}I^#$emwF_lDzxG#OmKshIM*y|B)5Hks z+`|0y5cE$w3H(nx`F-V&8!R-WoE#3&;!;jVKxgHTZ`UlMqa5!^=#Tg0)BnDmrH7tA zEWSNGxZoOJm>t>EkG(}2aO^F91FmYa?7#utP-uX-1G)(Fr=?^?!XMpF;E(R-!~dpv zc?~iJ4gq*^nF1r>y(uu$M0B3Re-Zq{fAR5uy^HNUFv|=E{5Z}sIL}CEz#d8=)Q3{| z)K@eINibjs0d*V)Y`8C*P#@f?mVEllAG0=x0Xq=rb;%RlHXS@zQ|&wY1TNnP&>6xaST&}ObU+j4-5;tYpZ(_-Sayi9Oayju zF_zKUi5r^$@0z8SeDL#{+a%Dx?~PyoW}V@LcBhi*b!QowUVj?Sn!9n}a$lex9H*{A zT6Yfhd8SVM+DN|LP_afJoGt# z{VE}S{VJdI^hMUD4Fi|&0n+}$Y)VPhLjr=iwZ2;Naep|>;0DkCPZ)RWJXbuYJ;ywI zJv%%bJ*y!KV5XFep}Y2vBrDep14ue#5+y&Nax@!`0eV-&Musbl!ltf>X|; z&JUg2og191oD1z+>}&1I>~rmt?V0v5_5t>8_LlZ~_R4mMLu|clZEX#0Rc&sY&U(dq+Iq~o*Sf>H(Yo5Y$U4(nU`?}*u=cffv^KHU zw3fG;ELSb(EMHmnTXtDqh4_VH%Nz@`Ot6fy^s{uaG`G~TRI*sjf0-|szcU{)?=f#R zuQM+<&ofUoXPd{F2bp`ATbt{ftC*eA4XIQ*B^{MMl(tJ7q*c;FX@-<1rAou3-coz1 zu~c0uCmBq?n$DVzoA#M@nl_o%m=>F6n~F^7rje#ZQzuhXQ!P^kliB!(@x1XH<3ZzY z=L~0_Gu1iF+1uIP+1Od#SpxREie>l~)*Y^*j+O~H7p;X&i;2%P@*UI?^Q*HCB{y|im z67VNbO%Ws%0no>r*XrpZ_kZP3+;X zN41RE{<>5ff6-ruYH4HqwW*eR++T}oDTDlXQY~q(zb4hjHS^b?+L&kk)u}eRg1;Ko zM(*}krP_!k{yV5PtjJ%5YC{J2Z>QS8$^Obz>+ka4Mz#B%_gA7?Vr_p#s`VY}uRyil zANg;kTCbD-@>J{D(|-%qy1(TwN40Ku`#n_avcd1BT4%4{MYX%9`JGhjc)Q<0wf3+2 z?Nn>m*>9s-n}dEU)mnGg`|A6=lDJrn&*HR~mGo@$m9^b^&jpV2w0nbOgZR5O&IvsBX;qB9|F=|8`s(^R|R zLqAaM`d8=_)vhI?lT`cjb##Jif0RexQ|;<~=sT+Y+7*3EwaYJ}Z>Uz<7=2B(OTExn zRJ-sB`jTot{U7$;J5H+Fd-$K7-bVqEqKHU`W$C?17il6ONS$r$!ZxD~O0-!QDks0e|NvH0ZJ!c)gK1A34!zE_$A^dZGVRfiLVK9D zwNvOdrak;j=vAgY)IGGDX%D^=dWC75dxu_T+NSG6FEMSy^3aP+yKhtI1*YBGFtm$l z>+cIa&$PAM;2essJl3wM6?%?otJjB~W!lPZp=X$O_qCy?Bigzhuc8r5+kO-cXWF(r zG>mDFpFu;J_EdUnITB1HoEBydn&$RWEQE#TL{R8!4+M3m{0p^X+JdI2Ez{=r zKy8>dw+m_=(bnFzH1rhHmK_f5VA|5lLr*g8j=w_NnRa`>&^D$mI1ze+Y2n*Lk27t4 z!_Z?)oBL+yQKsECIkc5&b1b1pn5H}wdYEabPv{}0%{ms^!nB#;(1T1XxjM9&X+^h% z9$;FbE3}De1&@U`GA-X0+Q78jUZMM$Hhp2}KBi?q61taZnHNK)Ov{)aTFWPoFm1@i&|;?DcvI*Orrq#< zXc5x}4G!JTv;liU3z^n`QfL9w`W^~}nbv1=XgChGGnv-L9x7p4%HmKl(~^G*6)~;l zl2D=B?J?C$I%tNx|7-n?k`DTMdf)Wk=-S|F>3qi7!SRk`xc#VolI@snhV@VDZC1Bs zt)-Fq74s0!m!53*1@~fi&A`&6py?-5iSK#3i>$Jg5`@E!mT&|+T%syUE6h&KD8$h) zze~O)5LG8cI8Md&o|O{f6xCLGe1>cMO-e3FR-<jj5D&Rkg|!Qu3{` zDz%#{L6F3t!Q=R(?nG+krA zlakCgPUUcWC3~tagd_B={Dt`{F+Xd( zAiB_(iMe%G6dV2)I+~cFt5%K8{DtK2sn(gakTY<-Ja6*gizYK|QbLDWcfyM$qLN!d zzepaee1(yv+0QvPcwfxun>DPJ>Ut$I51)~|4pb}C&qb#tcUQGW{%ihIV&=Z+V8hVo ziJ1}Ngb9WYONs1fJxCj&Q2~CT&tQX9AhF}((NY{NgkKm>L}ikDlGaQbOZR`}jqdDp zDVJMWU&22s9j}o&@K+N5zt0pH;$PuA=)2rI%v0(<;;!YI?0neqtD~p=PTN6SU2B%* zN%J4(u1O0_`>NdCC;Wd1Lj+|3gj^&df)bmNO|;aIyK*&pLRqU6j&iLp5C{TF69{ z3+(bT5k;{R6)$#(sr_1ihew8iISr5#F)(A6Z-m$RD=o#`z9OC*f+w?qI}u^< zQHwxA>mXt9>m1@R_zm7MJT(LdX92amIBb0f(MDus4z!&i@U}BzQ+sp+64EJ61!#Hc zlo)ixA4xc^S+o@Mx_j|PhOUvBpst}M52rgILTmnwmSSpGPo5g4y$qmE#I&bTvoCz4 zgCvy@^rR9oy0Z(94iVVtfG#frJGz7Ldom0R;UBaVgFEW*;N8N%rvdm3X<@7kTwDLg z`e_OGr3_k%`R(o~{?x?s$9j7S_l2Xh6!Y7XczzhELEulsB(B+CH&WOBGlWq8Gek^n z(WUU~8UB3=P|r$SuZin*}FrPg&~r^~f}3?=A)3>BlB`tazmlbZmtkoy;RE7uI? z(~dGn5Bp+>bhlbZSXP@4n0-mNnARs`dmru=F0+9t6Y=@c9!IQX`d-(r4mK;4LbGmY z6?H+c%nJO8n7%2$c6>}|+iawzm^yhg*BQb+!(|qrPQ>(0spB0S67<$JX(?_(OWi)R zN4N~`GbCjCjx?c?>3dzPd87rc=80R-;zs^Q=n^hVf)*rV4%Avu6mJe(*YXEK-|`1B zeY1-^eM-2@1oVlR10(dzlhuMG9az^woOEDA(`7s}eDdcdw$H>n+a%U*c7&EqXd9oVrI@-=Q{L?0 zvzPF=#qOK}6P{eo`*BnUy!fJ7t+(fUl(`5}R>KZ2HG`1)ITct{Wu0{BEE z2%+%NafSrD-u<)`<6kqD$A?*F7T_mvmZ685g!bwNv=mcc{WDJu19m1*Cvd>VO%SrK z?sh_7ce|MWs^@un7_cQkpTJL3WeGyo)oDi>P^X=^0d-6G2EZg=3=K%cBu`G>)rCA; z($rc;pldA?L)X!{Ou_G11kj1_J2GhfInk9@5b!In5QEpgmbW$x(Lw-E#1JLmkvIoJ zd&MKP6jRqS@zn63%nYEG_s$dB`A3~VvyM{zA|bDSQA}R*RgPS}|6k91tI6_=rHA=L z^R0nZftvnJ{#L%{$xQ&ySDqaA@9q+}!*#c-x^tbgv17ZVt^G~=7~79F#pbu(Z*7)z zCMld$-Sntwr0N@x5<4a(wWOAfm}I=qgjY;dTcXRQ#8T?&N-as7PGW1&Wm2NpX>IE9 zoZ2w8T>&ZKgwZu6&&&c98VrQ>x9ZB$0|rRfC#L3DKRB{Uo>;Xu(*sCkm3(Q1))&wB zj4YCGH$*Cr^%^6yHGT}Npr4x>hhaR(mZ?F#3~wE$P%c{0Ogogrf4n-pT=n-nqg zfUP`plW^IUz~ZbA_IYJ0>uCLXFeT!%g) z#_o3mj}0ciA^|2Q+rNm3hg?TYJmfktYhPU`Dww!N0!*xJRpXd=@MwZPc(fS%`nP!# zw+fe42W)vaHmI|Lt~ZFIlAsPE@4BxWB!1U@L$CQfa_eweH9(ekR1<|9aSIUW0mo=5 zwsTM2{jcP3+2sH&?|E?wjlccW&rL}CYw>-;uuL zU5<5q#qV-#=yrhb8ZE+Q0brJQQ-d;dK6hf{K0RnD?iF3{=6Rtj`xDZYDKGWh6WHEQ z&{7QDMd6{_h0A;ZE$_xuw2{>%hUPFPyuFfXDdz6no#$>JF7pDnywlPcZqDsYfP2iP zr5L=^H9R=X9UcIeKX>Sy*MzitZCZ+nJJ#cg;j7{XV)cSS9SN~>v{RqJcGT?L zv6mRS&Fg&UfIxLSKqoLzJ@#mT@V8$>OEG`Sj~u_-oo%XbzSb027ij9=?H}s<&X@0V zc}u-*UH`aNyHcEcoZ}teI|>~R`~CLjkn{cq>jCQo%Na|7`I331=Pl1Tce#6>`P!t% zle(EcFinnf4M;f%DuE};i&C_~Lh@9=3LUkT;yTe)R+Ldxl%1cau0>EADL(Uf)v2|$ zmf{N2)s~wXOb(V5XThuB*=fPz{6e+f6!}KYPFHIzMrw7fBpOv4_1bT!*49i)QXXPd zT3cEnDkx4?|C?H4Qz@Rscs1tcr)OtoXQW4}ZXzWxM_+YvR&p>>VPh%b5xNQspu&P+ zQBkDMMp9hkx;oWiQkapJKQp5cC8y<+M|e;}iQ`1;O1a7D9aIvvA6+NE=cej=ZUgz< z2O{zE^V-rTUMnRSgLtDfj|25jqWaTp@M@FMslaq~yI9ObQzmHd^+2CO*IW|>28R{^&O3Hy0X&d&IFjL|-)lId5hhI*ch-V+w$+CfO zURo6qpFFB9C|7UmU_;Fo2C27Bz_{a^-E^LSnP% zDj{;Bsa9A+O4p#?EWP6%RhO~`imEK)a!1vq3^7`r&RPCHHz=H(|Bo>R#`sHp$9%25 zb3N~P0`6N~_dAa{n>(`Y&)6>723t!lKU>)@TjT@{Tp)LBl8|%yYZYQp}v8yO0N$#Z!P;-rX=A zb37LTp`IP4rIaT$T*b^6vWROdh>{A;cvo zX(=X8)g45`p?OOnmlu~n$Rpo7!dRR`OEK$|zd65T7)~}?0IR%{4W2c!mLjBu-_TM_ zJo!_e7(DLHfmq(jhMpMTTZ_ydGja*?j9fADB%SjbX1r#AEPKY&mL|;eMp*Mdr=^&A zqAqnOoG~^9W_f3fIy1u?GMxX8@a7GnrI>p{2H!ophs&A(x4e6>@wlVCfCN0}Jz9zz zFkY880K!-rLj&YR3h5ib`w|K6^nSDyV~_iqw>wPNjR0HrbglLAXpbZz&c2M(o&2)QunMoeC6u{ zw!E*r&QD4Gy@WKlpO#|c5fk}d-7;Ku4G`ZfIkr>VT5Dco0y?D)EycjYujGNDXVjD0 zGjt}_c~uDRq%E`*V-Nj>$A*o~)qpK;V^aw>^I#L|i8W{`rXTVYPv0n9b`{X~m)uJ< zKR6-0buTT&q&H@9q-6j9fGIH4|Df*&Uq|m9p07PE+%sM8xGsm2|3~c=_CB^!>lfB0 zmSXesW?RxI(*tof{IdR&>PQ#}hLrsgp$9^6mN+ZFFg>!Yey|C#>4QzgHeHA~n}%VI z7y!`n<_PlTi#JC+pvBETP(|GAf)PA01V{D~ruk4kPW?;d}Xrq?Ke`6JC{O8T!%?&%nzJM=#r>NoQ1XD9|SorMy+H`#X7O}-| z8^j~Shq@0S%llC4dI-G%M*7BmEomtxo~>KSK_9t3aeV|6CqqmC1YJPz39x_Ida z1i$nHF}|{vH#mGjdIP?^F9 z#3BBh7l!fI6NqJxKTI6sn_i86d)kPZ zXHMd~FkIy84$SgWIk7IBtj^Jy!8C|kW7MlO$K$FTF?ET~(m>rUVbqbsI!3+HNxJk( zrB~mr_ZuAfYP+aA^x#ib3;r zq2I6o?FgW<7ocifN+gtla4yl_>{_x|%$s+PH!KXd4!|pWxT(B)r^R9|8~NfYvXSQ= z;&D5L%i063yr;S%{QytIG2xNK)Qc95z+ zi)rS67SLr#-i(5*f|QI7)eH((+64ic@G541SBcB)Kp-CvvujZZ;&!Q&jD= zr@$JtWEOFb|E85<5kvl*q6|?WBY<@wKo| z!~gKRB!cpff&vMZ4w6tN-kG@(usKQlTX5$Y(hL-5`m)S<)%{uw#flGKXgf6Use=l@rj zPMQMO`|tLB?Q8Cx<$2v>bq{yltTo=VyD zFwYD@JGTO}aX~vG=7M-@YhvlWuhCL$@r}!QdWe)72lU3p&{a)O{Wk=6kDr!e><6F9)@8*!~YBbOrm+VSpca@&^1`+UG+FhqzUBqTz zzm5m*94;FL;Kse2Ruy>syEi+FNh5X^i{aN5N5S8mIQTg3Zvy??WwaE-uWi7?LqOX| zfHy9nO=NlML?@unXeqm%d0Gs7&r%*3rt+HrI5AVX-W5-am7xG{T$D{*i^p?$6WYhm&{9l&*L^%SEXaodwQ&pb z_&$Yb$2mcLOk3POR>k7>&O4%zZ%iC=#Qjc?w;rUW*vdB|;>Di(^6uG5}hazu( zkTW*)`oPpgX z{O1J~$vef=hL5^bj$U!1LPMPL!j^JtMYcUcGi3gJ#Kg&&$?8P_R3Oi^G#n(JX-CPg zmNPBgG5^nwLXqBSBBxdPhB(kg14B3b^9*sI$E_~rNGDfb)8d`6}NhyIs6&y_cg z9(hbRaMS)&d7VLb+>u#q z3s041vr0}oGUWBZ*i1wy-H>D8xIdb{HuW2tChudWRTg)7k}BPz+Nj3afrIjveOe=9 z)?ZWPRY}$+ZDA3l^N^y+>9+7dIYWa~srHvih9r=U+c~v0SJYiNG*RAg&}!tSu?h0} zrB)etVur>Wl44b4%(&Y=bgT3zV^VKq?K)0+uZcQeLSz54fO7Q#YQekHBGYO$a-HWE z=|5-OGaWQW_FNOYs~t`5|1UBH2KhJoPWW2D`Txrvhx=xD|L?T3t7EnOm_6Ax&-$LV zmL<*ntT`#Ek7*IN$2aD$VQ|0}f)7Qq16HulCJvw@V*D3%nPcE=rvUIJpY2e5ZO>0Yk1wUA82E)D=K{2GuH(49I(qL*NWVTs zOEK}zjyy3OJ>|$ZbDSMCf&FS0Eyd8!)!?CUQ(QvR}-jrP#txALW^0y2u7*$@3d#WFNp6eA?TlIPc42@#Z!yhhVtkz zOQZw3 za^PGgo+twT?z^-UgFiAW3VgDBaN-z=@n;d>{ZnWu27h=m58gOjHVME7%AEuWcw{ub zeV(AceO`?Ekgjt;6z)VoO-vMSly8mjzNKYic`GR9elU+SG1>pmGX)0v@AQ4)Yvj%G z>~LRn4}tyv56*Uu+4eW=)ohcjJFH2To6TF2{z&R%nrF^`ZM-#BitP=jUVu^OA$b z#f90aCB^FfRs5^3uT7F_Kq1HPju_ymf><6u*zD%bFA5U*~QsGmMd?)gCzfiQVe|HG2Xb%!sS)~mbK92fpdfS zjy*A}Z4oWSv>$inX`6=2EkJvtq&b$O&CCf-jr0XeIf1p5i(x;yiid3xE;j?LtUU)0 z8=RS)#3Wkwm`#e9`F-7^ z0AOQNVr-mRm_Lg=Xoxx2U7AZvG4Ff2`2m(?^MF_KvJ8K6QA~gq0ltt;OELKV<9z3U zCBs|*m-OwU8F4hfVB96cdCk#w{*;*eon<^XxCU{hb?3Bqna`~eBfq7~5epln*?=r-=Frk5X~^7RCNXdM5n76w z_vw5V;A&HVS=N_Y&rDN>5YRF$k8oKPd4%5#^8EsUQR0Ag!NzBwAmC@85L@_-#yl`w zunYmPqLkJTZfj-pGkeAZLyf<}=5|%&*PmnZZ3<0?e|OO8UX5d#B)Z8sR;iCgy#$fais- zU7WD49rpm9P@npZmSXzdJ$ZWQ+C>TL+A4kQIp0YQ{N!(9@K<_s;BJrKR6nWEcjr8(*RjRX-u|9F&GwINrLDR38EY@gTb9wDGoF&b zoq?;&UnQM|f8cM^BKW8N_x>0k3mCJ3E-B2>ZJyCR#s_)CR9Xa^^}MP2dRO0O3nOEr zyJG4s%*eqh$cwVF3-qVWaJs!IKFAf%$sK?Rh zHhB@xw62J&0nL%nEA?x9&Pjk~OPHthwbAW8Qsh^qZOjq!H!>M~DJA-IruK_9hNSw^ z&4|&}BxmH6R@<6sdC6ikk4V}GIsW@bZSup7!sY4< zlg2$&Rms%Gg)FY`zZH9FpcFeheqO{mJHl|Zr9LVt$tT8sUG?Cb{YdC#Qr zysg6J>NAp(&Mox3+>Vl<_PL&xV&v1hSfkeA^16U5DcD_)tlJtA*xn_y6hr?spSLp{ z)7AlKN&a0ubZiJm&;5kC=YBEssd+pzoZHt1W=ZGvjG4rvQD^k}?tKYt_r7A-9~bbj z(2;8;q9bd;bNaE@kz}G--?55JG$&Jee`iD%O z8se#H0=1+wjAri`M-5?aK(5BFZ?II%{)IKl@Nfv5FvF7!qOsr7`XmeI`ubI5;rv|p z1|%%F+yF0q!KE2KX2EsM&BXNA+$=Wv;lFs3cMF%hfO6!U+^ zM^CEx|E@7lGFcw7bT_{rSP`h_f5t!9_mwZ#XY#J|wuRUKZUTQmiTg6wdRHUoHfJ}- zKF2Wo=k`gq)3zLIg>{~_mU&Xr&q=eBJf?@EJOeuQf58tJbt+)|0a9j39=-%X?**tH znCFc@wT-SOd1kOMJD8e-U!U4(eDaQ%`Z7WpX(ifi2lQN&Sq*p)EvCZsjDnneL=UE) zHQs|3Q)6mLc22tb`#od4J=vFrUdrOGU!b+d_e)kGnWWTqt@&?>j*;0m;y+j0_O#5l zX>R)HZ3ueme_}l1;tQXPa321EWN)J6|{P&Vge_CU? zH5z(UW|R}HFW%}3Z8iSG8PigoBMm*0fPoV?%IRU_bI-A+syQ;$S^pv9mj(Jt$k|H< z4#L=Cd@|Lj%4jFW)jcS46@rtDu%3b|+$?h#;tC`CJ6zubhCJ3-$=8#d@S#n{A8oVW zj6a)08)bGywI-`zV_ie7?tbIL5%gA!bPTn&`(&;dBWFelUgn2Jt54rY){*!Bj+g?2{rC93f&72-;r&0C`v%uN@cv&N$3*)k+X-8J zYpUf@^WWxyNq3u$=r;BL$0}hsP-+K$8A%69G22jnr%l{2SvS#A=#JTF)t!UE`CVJU zmUMm>gRR@I6W+{6Xes8l^yl4R;H7Q@+>*T1G2C?5Pf#-&(o&3UPT`T^?5;H+OFz3K zYfG3T31nIUEyb{=Haskx-K7Am^s_r{AsoGFCdgBMrKJ#k!@nLL9nS7r0lM_FI}N?k zv%AS12>s*^V){!qo*vHbl7U|O*_}pT=?0##PaHr?aT_k$`8L4WT}x<#^s_sy4N-0Y zLOgywEyd*joZ!jf?5+inOFz4#L4Bs??hL3fR5a`kMXeoyO zb2SeS2VqSBUiv|pW_WG|N@#B;+0oYDTt#-YKXh4c;UKIrP)k1uqtx+SHH3fUXj+P` ze(oOL>ag-^1pJa#UTo*2@$1&%gm=W3v=nn!OyId;ifjnniJBtgxs3?+a4qm_col(P z<+=!}#^Lho0AEsyH)eLt`9x5M_M@fP(!c9^IIM9S0IH-lt{#S zdPj`?>q6evFl}E0*wUx%Sf?DJ9jNVs1~wE^|8fUMt)BmXXW45Clm$)%4hQxJUJh&z zYznLlEC>__G6Q1+g9F_ItpfD})dE)kAO2JRqy7*4ulb+$Z}G43-{BAWr}-!Nhxyz3 z8~SVdoxZ<)KZ6(HfbR|8PTy8vsc)%ojxWzQ#W&K|&)3n{)K|yn^eBgM^@igQ!SmU_E5pqm(OmGZy^mep$G<4K-IPHJif3|;PKL9xociOkw zOYKYTbL@HcDfW@}e)f*`ruI5^ukDiUtnIk%knL^Ti?%0h8*D3V^KFH;blVu)AX`^k zOItnLWi~U!MVz!AfmaiDL*~TI*45VAtuw7z)?2MZtUax*tqrU-tai(J%W2D3mX9oZ zz4N_=-gNI6?;vkiZ%c1I?`2-Ir^0j6bHwwWXSZjEXR~Lu=XTFbPnPFa&k#>fPis#D zPYsXVecpZA{gwM8_g;T*%d?h;E$b{xEQ%$^GRZQ+(#O)?(%4eV;)Yipe>Hz+{?xqB zyvzKU`9AY<^IUU*In_MMJiy%9+}wN>WK`4s_$&@H?o6diUQ%vi+TwA_2&OHnP=+&Y z;YDQ_(-xE}LzxzCs0?A+ycd)knKrk-GMH&|K2dI9+U$|aAf};X%0Q-t7AXUmHmiox zpJ^ozDE*jL+)e4rw8DW(AEp&NtX$8uyl<4=Ov@dl^kUld@0FfRn>J19!L+Q4N_VDB zO;NfrE#n=fE7Q`)D_xkD`hwD#X~CvSC#Fr_s&r)9B(KteX%n)P_Dmc1kkT%qt-tV* zav9V98Knf6_SY`O&$RO`6(7_77^--gR&hY_Fs=Ls#m%(e4=66CoxMtNGVRwzii2rC zpH}QlJ2P0ZG3}=p6f4tCHBu~0JGoRbGwsCdN)pqK->;aM_H7IFFVnt!30-2^(Yoj& z(~dlXE->x$>gXS)eRe1Mn`sC4pud>*=}2^*X$QVSe=_akp6CyzefS|d$FvV_K^07U z??+V5w0C=oi#}l5ibC{0)0Q7c?=fxJ0`xA^mNr29nYJVYy~DIS&Z4)OwrCc5i)jmg zNBfwzU_N@2X<)SW9;PWh(Q8Z#tw*miZRT@mH`9vGpjVhy z)D^wVv>C6WmzY-23%$s+yv67Rrsew4E~ZUihMs3y_Cd6hX<0X+=a`oH2zr)j84b}h zOiL?3Pcv=GujnbJP40kpFm2)h^d!^9uSeUNHtr%SFk zVp_juXd~15T#q&|t#=8!pJ_e!qx+cFy)U|#X&nnuDbw0-N9&o^t`1tqv^FczTBfC3 zL~EGVY7)AKX)S+1tC`lKKUx*hO1lP?HcachS!vC*PMwq#rgeBvX~nd5A1TR9YqLga z$+VPPl@?4(Ua2%^T8medW=v~#L}|*jCJmJ)Oly>^G-ld$+muF3YtTk%$h7*~mFt*R z?_Z?>)2^PYT+6h&6-s@k)t;+d!?c>Cm3mC8u}ry|Y1K|BS26AKhDu$g`OhhJnC2O* z)MlD%l~Rjoj&GDJnPwla)MT1UwCOtX}ug-kP>&;q8J6cmnVkm?rAXWE5qG>>WLPocR?`_qnYW7@ej zXb#iLkD%F1E6YR*)6PDD5Yv9^fkI6CWfhvmv@^%iOs1VqLnTZ*^&2W?+R5Kg5z~IS z4HZVT(r#ZUZ6n&c6D~A^X~&nM0;V0SiSn8D?O2q@w69O0T&8_B3*|8F%Oo_NXrX9M3rZVkd50uHYPhLS8Ogm5ur8DiLM^PHnK5T?infCsxD9E&T z-$hfHwtotm%(S=9qe)DAD~KjCZC?_az_d5oq47-H`x?5HX?y%=9MfLijK(r;w;$cY zv=^JAF-+Ul1&wCf&SEr*Y0q7TZYKBtpHa{MH~N0?rFa*3_Is+kC%d-0%+4DfYvKLB zmbS3RLDQ z{Q=Hz`U172^P3pzIFU08<`eD(^Tpg(w&l6u0HhCaOF95y+`0phu%DoY{bJObx?9+A zns7a!N;*x@qei*~bIZ@ujzH##k3cro_=LAF{_5x<Nz=L>T0>XrQzJBCs0c|w~4Ye8-EO2=}EAa zo?`6FTk_cO$?E~wl0JD1n*=u#!jKjX6Iw4Oz3fV!6b>M}1F56~NF8Zp_(i@YGoK^q zGoKS9`~TsQVf1waWa*<%4S$Yw3WN;5>74#xzF6bpTvzt$s9)_8@6TnKJnYCzb?!qvk&C|l6@)nD!ohSJo4Qr#0 zKrMZ3L}S`xJ9VzM;K;3F!QuFY=Z3D)ArW08a@&>|dHOP1ij8c4l81$^(LNDfL(5+f z(>1aW66)-OVrm=zW{Z0MU*9~{Z0Q|XVgABA74HAP;P2}@JhPhC@>!^Yp`imeec_y(uKD*Z9s3cW2<%d$IuS}S@GSZW$<)`9SePH}eWv*4}$+$)D zOKlO?EmZTpXZ)1KwTODN(YwayQ|GGT{m^K?@ppx(UzU21(L2Uljn={We$m^;R}-0L zQzBkl^p^2APNS>gclKzX%nvh-)aQ2t=uP9tEo-6X<3w*5|IyM{5-}p4i(WT=K98!7 z^DCmgGW$rZM-c5X{*xTlI_65i=6ucgX@gZrym07M<7akV9gz;A&g{Eo_K#@K7kWiz z=a2DOp_h$cKru_k_co!IWX{H9HLCt@FUlNgu^t}ug3S72-3DkUMA5-^y{73YQ(&ln zi|;pIZ|`!?r=Gg*OxIJ+i_XE0d+cA@ud@|cU$*)zW6h5zT}&DS|MP#}pKyb4`DAdi z^pcZqF(*GQn3JKN{=?5tyeZqCqNUiY(p8r&7ceKu!({8N2CLTTyqmYUWJ>ulP)r$dANK6unw2bT2!207@W#*AJblbf6OE{ zZO7<$5XJ+pq(cPGv>I+Q?z<5iZ{0xp!`2OA=nez<{s8{gTLD^$jN2$ZgF$GMpaV0?3k158@*yrFE`tkOLbM(=`E$JLR#@-OF5OF~h+>Lu^DaKAd#A8Fx9+kkJtv)rz z2IGdw1bM?`F>=fMdF149`OSblTKYGI94~0@a6)?DC0dG!TjcY^&^JaVux~_G;*p_v zZ-8Lm8xUhRZ^mQ8k@`)5E&pps49y(M1a|#4T8g2Yp5>vz)*}*VYu+tQaMylDOEGqn zmw0T51Q-t3k|F_OrVq}G$%f;aVnV*ASWMpdHl7@UMTP;nq+pR4@`#I^u-;RHmSW~c zBY9?6mJS7G`O8w~XeXGf3TP?DZP=N|g-Ln{;L2Zq=-u@Mb)}b9v|0Dl? z{~P|@{#}qi;0gc3{!RW;|7!no$RnWmi~V{2EPpCw6By$k;UDbp=kMw740#1w`WyS} z`|J2?`2BvT-|V~K`@?tEciMLX@(djDed_zb_qK1Z?`6n0u*3J5Z;Nk(Z=G)?P75Z{~nUH_rR^KS!FyA0wA76LKL(tmS+}F@o&sWP=&FA&mJ&LE;lLxo!Q#}(r zV>}}~gFXG=mVIYWTTe?*V^4ig9k^}p_c%Rf_XYPK?z3>~{)GD*_YwD}?ho8=yZ5?Z zcJFlWa6jhW;@$vx3|6|Ax^H*Sb%!8oBFCNSp5ngMJ<2`IJqYp|ba!`jw{|yoH+0v7 z{07zBUbh`0EBK%RqBuH&w+T!&o;T<<}?gV$Uyx}Jqw7+YPNA@9K&*9zAX*8HN-l z)OpDHk#j#pZ|rvNaz5>R!uc@dNho!$b}o0`;hgVOAYVeBGs~IkoZuYe907R~`Z;?# zJ3HGtTRIy<{)9Tt8cx5{=`=eoKpus&j?<14j&B@C9G^lyg|{7h9WOg}I(9f7gS-kG z9P1n_9ZMazJLW=ug+fP;BhxX(ajRn#N#pTsyVz4yTb%| z7b@((+E3Y!+rP3OhWrcf+4tFBv%hG6*1jF`Fl@HpXJ2DqVP9fj0QneZ+6(N{?CJJN z_OXzcVTgTzy|=xqy}i8^)|+tA+I%G=c2zJp7WkE&(Dy@;XBV!&mqr8aI@wO$mg)j^R(v)&%>Tgo>Iu`u-tQpXTE>FO|cc* z@@!eQRNDl|B{9M_*w)Y1)7IJ67II27w$-=QvDL8oZBB@{xnTXnde(Z{dcyh* z`hoRr>t68C?Sxztk6E`^H(1wMS6Y`s&WX9!khRd7W6iWqf!q_Lti!B>tbMHAtsNl; zMRRLIYdvc%Yc;FaYPVTT=Gir{td3BZ86r5j5ZmQE}kSdxF) zhW~EG(t@QK%OosKs#N~P@)DL8vAlrgKUn^awwtERSIMIhKd9ya&tGSgyiyC6;$%xdO|(uw0JiGAx&3c_)@juw0Dg9at{H@^&m2 zVz~gzFqZSNoQLIHEN{bd4wkdARIo%?hOnH4a9Smt7x zgXMHAr(v0mWfqoGvCPCW1Iu(Q)38j%GKl3AEGJ_*3CoFCPQY?JmbYR#4$HAv-h$;A zEJtHG3d@_Z9Es&kSdPGQIF`e(9E#--EN{eeFqSu9IS9*vSPsClKbHNl?2Ba|EU(A1 zHH(QEE{9l2+M|8UWa7^EU(3~K9<*DSr5yrvAhb)x>(l1vNo2ru)Gq>npj?e zWeqH=V_6N$%dxx+%K(;sEPYsdvGic+#?pnQ6H5n{b}VgJTCucXX~r@MOOq1$hzp?xa%kx2j%vsnIy<*!)&g5}Rxp26}omOo*6 z3d2OwZ?OCt%dfEf63e4leu3o?EI-HcFqWTTc?ipc zSbmD-Cs-c9@?$JN!tz5bKfv;REZ@WOT`c!w`3{zEWBC@A`>=cy%Qvum9m~B~?!odk zEMLWPHC$M}R z%g3;M6w9qxK7!@LSU!a17Azmcax<0>V7Up)jaY8L@_sDu!}4A%OR-#!XgfaSGV*2nT1EbC!;HI`RlSr^MXSk}g}7M53HS(C*7H!xX#w#>G;%fz-1ug4em-(W zfKNv0F(djs0X6Cl2>++wE-^mJI8L|0;eure7>q?3dFfLNv(t6G^mpSQ5{zwQa&B^Q zvVL@&O~52u1odL;{$~6&p_oP%loVyD)9SAYm}_#2rgmw=&*i@);8#@7s;8Fdr}CeT zkDH7!Y-U=nuE(A+{(-{SI+N3&@9-8roq+y|Gw`c@=%)nqp+Ai|_`#`#K;k&?oM7J65{Mtd6TwO2e?`8ow35QYjJ&jLQrQo38-eQ$iAZ~Q7Vl1tPSmr6bBn%~djF3_ z%c8H0zj(mxl^h-CioP`d5&%~njZj5LjUTJg)$p;U=nLb=YD|4JDiks#Lo9zyQx{WU zr2hfmPrlaPxt{kuwcX=go1MQn+c;*~UxJg=A=Y~>Us|p*PfvQa#w{me0VF(T_27F0DtugqzO*P^D;1*hnxkqL4 z-0%=w5pYX-2ria8YHLoA-}{l4V)UEq^XQNau@KNDB}0sZu6~XP=(}37mv^g3_HvW% z1uW>|GZNUv<83kt{yXo|Qf%)L5AgPehxZBqU(&;SvG$JLsuJqA$I((uKRk=4hghn7 zpqCV>7MGs&mwlfSw# z*(7@NO^{#zn3iJn8!zza(7SUI*t_Fw;R*HLX|xp65B`RyhalbQKrbmsH>RsZIRXgr z9_`xAo+_^0+_0A?hi3t&0lB1S0b|Ld-3f&K)yHWmw)!C5r7W0JvVlEOa|(4z5Y*i_ z&{B*%a4>If7@=8!oTw2R?b;y7FaJbKG5P>qG%SqJseqoS?@t^D388*z5-r8_{d8FX zVKUDIdP$Qxzg_3uEQIuhziBBZ?sJ&$D$u(#m!|=7nw%>`IwQwAjtKB`57AN#-Ydj|!*$720GD)KGCnwQ zKM~qzo6%BC-Ln%<4ShP8pgzqzu?XtZt7$1l?r{x|+$>x^1(1g(qK6Py7@^#uU8~+v z#kJ~g{3R!{{~u!t^!DEc@Ag&qPV_wDE_3&H-2-vsEgZA$Z`uR4G1dnyCoL)FIZ1CP z)i900`+uPbcL`T`zy{K%el5jJrBi>!0b-kq1L9vW|4aTCOb%DLfnL(o&z3mY$&SMr z*v_L|TP2j=ASTZHj3;gru5badq`@7J819=-Wz@fGcK*EzJLm4>DTbXqlZS;K zF((l{LQC+aA9+U}A;?D_5hG8En&HZ41G4nPDh)Z#;QPEf;r_h3n0um+H#O`z72uY> zEY-MU#@}am66(+H6jP5s%2Rg^mm{E_E_+_48QJplAjT$k@;InvVL7-*41cT6Jqz%m z1i}~3%FfBokA?qqB(eObBgOFJbcdTTG-m<4^vOCZlANF(_==Wd%Z1}tc{aChj#(XO>>1#fjH6n zGGp~L*FaI!0k(3b%*f)G!oYQLM zGMNGAnqi~PnU#RdfOA@B^a-)zPe6aAXS<3o0evX?R95jOpby1ysw*CugH!JgSKP)2 zUb2aR)kQryic4m%A@xOE(2CRer0P+PW1BcUtvY0OQ`|aMVZ@|%<0FEjT1mHjxQ#aB zBl#<-F497)@u}UTsw66Qk}4MCZz;yFEz&-7whbJVl2&xQV^T?y*;is*ii%0*XpeFR zqJL#hn|e1Mx@3GyR~t?36-M+p9J z9OCSvvmGtLI{82b5wb%^kYPC^%`U54e&}S}3mevu46O zRn(teTDOAm)~yipF8Y9T%7h^R;TqtTbOI2?8)f0znuTjuVd2|%^Tc4`dh#u-xd3z) zt~r`mxaMfFg%`ff^MZx1mTzH=H_E~_$n&D5HI|8q7p&!pJBKT-0%GZ2X>C^(J6RAj zS35yVG5ma8`~kq%O(1+FUg^@y8xr`-8;arQE#xf^VJdY1Ub{@9k-LQ}Y6G%#uQWxj)GJ-;A@LJXiurH5o#*cwuBZk4(l3`q_$#?wR_a4)twswwU4Kz7+6`( z14CE2B7t3{(o0&U*8K$Ex?hZsboPcw$r^y4s7OgQuSZlq5khStr$?ohDo&3=x+`Wd zHC6}uL`{t}D+xhPBC!gkNmaxu%zBjXFYx8B2FQ}uR&1-Jb#UD!t$(!?-TzjRqI>3Z zJTc5BmjiL4W|L@#H8%G8OF>$Sdw0o;JUaC5%M#eT{7H(CFg;g8au&T8hyNKIeLh+x3O%+N5)qz+%_efolGH zA&>q*$bUZ0mFu!N*E^FP`y8X}KiHAIn(a|rPslc&W%=8(-qH+W1;!_x^ZW(*%Uig2 zxd-`MB`r^?XL`z2!D0Z6IB1V@uNvq6bK{Q@s27WVf{52mX=c2uJ*uXNH%Dn|{D`G>;S)90&xJ>96XVB{t|HPTTvcP^ zj}K^7>hz$w?vzIIekNK?^33dvS!!2rX#7_rx=HHfN~^oh_@jfE>gc=3YV#V%>xDW8 zymGC)L9BP3EA{2|4y`6Oh_8{?Ds3vHeZHQ&R?+nfJuFeKhGm%5_*o-nds~!?XN{V& zz9!o2uK${}H$Ikue2imigREo0;u74%cE)FeBbBOCy*iHD8h@h7D&Q6vxHWAi+rm9$ zESX@+P#e=)=6R;}GsPZJC|4z*+StPdrLOTmUCc7IDynDMTKc8!GeNWh1ta! z>@Vs0X+>=L+@@8BR-qKw+sw=;)Gw@KD~spQS85xd*-UP?Ko zmhp2-jCG^^^~#kAXl*>lwQ>bH|Nq()80=r```*{lyU26c)6iY)+UvT~nFcSrx$F~d zFW9WsiIy$qU(LOfR++wLJN*B{{}zVZtewCwBk4A4<$HPTh$#({*Po#jJ7ga0&N*b% z(29=0EGe`?H{Pg6fZ$HvN=q^BrWrhLvv5TRz?GEkLWiqO4}@}(mzHAMjW_eO&>`B( z>kv9x-I9f{PROFAn0Z4xo*A5r?SNU5bFmU;w(udy<4De#(s2)o(eJO#qc;dwv<38D zaxO;^bZz-WFuQ$0OEKnsx(DvT(=lVg@f-_z$)qBn{)zo zKOJXY=(rpQ#lD@*k zvf8#jj&a+pA?$6|h?(!vJvt4>Z6VvZ5oas`Ou3boV$jvPY*S#|=CX|&&!tOPlULGG z%)IIfzC%E;U^8Hr9FD1X3=_^4uh3G=d$(@Y03icSfmc$<0CnzZyb;e7A#HYqmSW-+ zLwF0rBC-h(OIk!yVx5zkU^dYr?3z>&VRu(E9v9}`#(*nn?$zNkS2qD}luS#peV1E# z;HKe1fY_ZW;|$g z@10FD#+1&kB4f;Ry50-lwt>JaX=$e8Ey^e=%FfSIk57nY(J@+zE&Qx5UK!Rp1Ati4 zS|=WH1UN);N0x@F$Q}929ekGn|5JYemgIlZ0juLKSW=t?Pf2B`1&j05C@f;*Sv6=W zw)NACcy#C;{SwqW;AvQZE=CdJk_QNJ$pd2Ir$+L`kYBVf5KGE0sxx+cLl<`=*u~w% z*gMAa*f78K0c@%BThw;Ba3BFK94H2TQfFV-7+nvbk~T)fzS?%VIDdLZUZgt|JWOy4 z9v0(npUm48rsLj#D|I@ixcbFJo_2dA?;A1iwr)HxOm4k^SL)=Z@oLj?#K5_Oh=Fql ziGiP}#{EF{*4E=ah9vY(RdjPbgJ0tO+bMw=)GqW?& zX=p5=o;Hn^V*1DG^7P=b>JIdh+<|)f95#23UxCYP_uq9ms(3x7WWX^bpuxGp@W`9_h92~ygU4UKc z%1$$RZgP4DwK0*oBwf3SmOfrg{E%*C2XjehAWp!*jvN%sHeO8Q+HP20r)2#OX_LbZwm6>0m%Mjd^joTb~IEgGYG$$GT!(+Q_

i?#vCCK21iW&L2p=N?Rh%@OVy!;BB)BaI?%FlDH$0j&CqBMvNO zh^!u931Iqnxw8EpJj4pL>r-J{$fYZ}rHRoSmJNY)6_YT{fh%0T0z zmwCe_v;BiI!1$OyT~+bi8cKi3w&WZVN{qx~03592Sa=37FJdmO+BQ=2s~6pjKC+lXc6%2tIu&t z_3UdtlF0gJ2_Ff(7#!N$_?ac=h6*7iE-b1hsOoS@+82O>R6`M zRdJ&|M#RMTlVmNW_qP$Hx%u8NNQ zwk|U)bmUtT)RE(^nMk)-JBOCyj{KI+&@d&B1NKBr$q`R9;ao%BPAy$i#oMX-zTrCt zOvz(`HxW}Z^=A{@)i2UgY~D9d@VL-5Zb?wri0c(6%&R8QQq2B_u3N*!t1-YX>Ee}c z4N36s)=Yf&i(<^zKjuvgJz})%9uegsAh;_?R<+UNZ2sRJ(B%|LjU zpQ5Fhch84BFGOS947^gKF=Ct*1a#RQv=jrsrh9o0F5-;@U`ZG8ShvN#dgk&Vs7o8u zQjGlSPTt0Vd{bhOb&eB)xxul8=n7g;~$Pn>60+6Lf{NirGKM`KKcpPC~JWg!h zSMK9kVX-zGSfwu3FsttPj*u>@prx4j<=H$j%xS}bSn5{}6G!*og<53G!YU$LUgB}d z`+u!WmLl^-^Ez{@z?wik|MUJKzT>`-&j#=R)%M)yY3zOxUIf_Z8sew(UnlKM>SsD=8c)3e>9+7dmoc8bO19(bv0mH-l``8HUt1;h#yO}` zjLG-(A62OOY>+YeKg9K^wv9Q}2^pXNBi`minIP-TS+{NYpC2@mh>^e_GtM%`>n!e> zF}-r8)LMzlxosxI5vFAYb8<5BrmD^prNo%AP)S=!t!h2R#+*$H>xuTRC`D4IG|h|8 zokkW)?WtOQ^g@qn)ftK{T=ZX0eg1kt6KCTXV`XF&s%#~?lvDZUzs!o{?~;53ByZPA#kV6FfPkcCF4}v*~k0P5jW7j z2DB8rgMQN8o`su3vw+{gn?quLZa+qF-_R}|zEQ=+!&ABx25|T>6R-_D;1y#>@9GHq z-oI!mHu;abJK?}yk`Q*XHj3FB66QTO(NfHQaw6|NgrnYKU^nonw-UP(cGwFM%2&x# zEv2vS64U;m%j^YL!;65{z^max+UR{MLEqh)mSXf1y1ZGCt)&pq4b0XeMrS(|Li@6o zIqT(>V(R13_Yh|Qwfxy6cF#<(U%W(1G4?TC9>DJ5iUPncl0J!R*l|Cs1pI~Nv=les zJKZq^yabgG4KVN}C~{hStM^jsBDMqk(A?G9Z&Cy`w~u1A72;F;aD6kGqx z-}wf>S9CfwK>i9q8?$Ny_zfXpetG~c#q39QAzrX(oCfUj7mXZy{1wcO&j|mH&&2#+ ztmJJE{MiZRkK%V)x`5)5xYOKke1@k^XV;|-AVj^CpG{7J-*L; z4ZSlwZ+oh_$Ge_zmN|Pk7TG_sUu_$2z2EY!rJi|u(oWNPQzvi$gu92&sSixbU(r#g zMZB{V(%w^TX(?>?rlh@GyThHr=hRmw<$vCE4T#5yAbTBQ1s48~=Th$8Hrq=K*X3qq{2kDrnfcSmy7w583w_V&qFpcx342?nHKT z!7A>U7L9bQLfn9hX?z2qo4XR(&Ev1)zSF*I-z^ZcU+B!UcMG3$0=xXFRqHP*d;C@0 zw>Hw>zqN_^|LM>3_XwYJ0Dp<}Pa5UtR&mi2&DRr23%;HxZo%Ip_!gvu&)J~`^4D>+ z1<4R+5%EcVsYN$_Sw(c?U!$U!ZHZ*YtDy+<7bl3Fzc?Yb^ZDy}=62z8R$!LD_|fbf zyZAXWm2e-KD(3#PCC}YDe9i*g24*~}WJbpUk6NEr?+p{!!;@$!hW?`(4-LjPC&bto zTAfs)BQ+2GO}G#JE#|KHiRW$^K9>aC21av>jIE2^J=lc+AM7FqF4sBDV3}e9VEN0G z$^v*l(HtM2>=t8}@foqguz8&a*zza6xKX?Z9K_TI9Af6*m+^h0akyeGFb|aese!oL z$ng89fS`U+3#vw>UXQyQva;G?g&Sw z3ed}+H)4aiiP7KDvU0xjy||a0Im8WI`;%@&Z#U5V&DG!|FwJ2XtA{jNubp|Sn6ER2RYHmE` zjzrW(9dODbsWI!?w4m!lw@dwAMmxQfg;ECYG@8NAy`-WOsWMwnw|J@}oD4124U7V2; zq<=}zPb*?+>e{sG&?=My9~4;9Cl^$*0FQATD2T-WpEL!A_)C4qd@Z~)J+Hv~e?wer zoyVPR9bx;2_IkDn)(0)$SQ?o#lD3*oCN%utpvvGD!8!FoNqI+!>EK&P4Z`S1(L%y9 zbMk}5$-&~{!tB(N;z+)=dtDu{j|oblZ)sC)-9uJg!{^kuCG(~EcVqZ7@=9{!;5$MD z-w_hy*P6~bnN;&%n^^Oc7^PVA+iMYido3~lmAVIj+lSB92Yv(J9gG^GG3JNSU6Kng ziovW-fUS?xQVd?R4{!LM;d9pj_^ibB8)!*JadvJ-oW5iJlQhBnr??4M=-z_u7(Q1I znjkNLImY&B`EboYO?#VyASd;ur5L^XG2Z$R0B|*+%L@RAK~K%k&&dep#Tvi#-%oK1 zpcJ>D+CIJo&BN!ef)*H<%qFVi2RSF-jAZr#&!w>h_tID~?qz@RxDc;U7jPvW-Ep{_ z51FuDI8RG4bKoM+49B{4fLY?<63?u8q6z3fGifOX_8;MaTZGTm2H=~d%_)4J(EQni z^Y5Cp6!ZFY$4L-&RttC~9yoFa&Ww1)3F>+6Ue$T=y{b*#uXz*0$@!IlEb#=4L)QD& z3HG1Y&{Aw^Pqd|LCd|^zLr+l8X%Q^v#1Sl;+@J84hWNNE09k$*XeEAr!e0IzEyd<` z{=>7wm$3%0%lk6Y+}E1xBkHt(AeY@h%PP>5cytIHst)M#1BW#9$e9CyJ^Lmt#n28f z58Wnwt{OngKj5X%k&_ET``chzim7e7dpt0gTn^L{=MufklRN()xW8f@pvRf#N`BU~FJ;pnITIpnjlQ!0P|Qf69N<|AGHC|I_|0 z{x$wP{2~7|{{;Uqe_MY;e@(yB_qXq7-#5MkzBhb3|3CKLJ5GvX>l@#lJUxjFB9bL9 zIVX{vlL&&OO)QI>*aUP9NH<85oLLYAL17gniGZkx2@wzhk(_guu!|&rr>nZBx@X4b zKF_l?&-;1bAAg*4zxU4F`qrs@>eOl1$F7C0DK4)o$u-#3)79El-&M&~+~ssWciwfL zcOG{B-`&0XE`&s)z$UV5lzS^E; zpK2dtPq9bYd)eFC8``VbOW57^FnFnO(RReP+qT{InQf_UrcJb^+lJWQvURjIwNtwpRh%VWz;%W2C2%Pz}i z%g2_5mMIpmCCM__($mt~Qr}X^QrzM+KR4espEn;i|76~3&NeSGPdAS>r3*$!PO5=RvBqMK3Fb*_!H?}m^HC8YdGjfKfhTDd-hJ%J5 z3|kDV4Oxb%hB1Z|LzJPHp{=2zp^BjdL_^B|Tt=$_ccw-6;!tgh?mkAfD7uq{YEpE& z5~@Mb&96{(if#--5fokf2UVl!>S9!tqAQJ26^bsML6s@G*dJA*=t3B(NYS}WRDq(i zcJwMmr!!G`icYRYRP&74?zfIAUKE&ez~{Ui8e6!qK9AEl^oZT?S+`fTNoP}JMb|3Oi&Is9RYdT!?rQPiV7 ze~_YXC-~nf>Ke-*ps4dB{x^y`4dnMz)ZqZXkD~U`{9cOMp5%X}s7+6P4@Iqx@xM^i zawxx>q82~!KU4Ht8U81Vnr-HPq^M~j{s)R09pt~Ks9}G87e)2A@!wHYuLi%9qB^_y zZz-z%CjSjZHCORpQ&giNzk{NPpZTvSsusm>r>M%${5Faz$MIV!s(6|IlA;Q2`7IQc z7x*tIDwmJnOi`H?{3eP@zshfnJLAhhIxk(MbL? ziVAcgB8nbu z;TKYrTZ&&m(Ze`?K1KJ>^7AOV*MXl)(cSO)ITYRL$j_$e)~Ea|if%09XHs?aofP?jG_(XN&J2#R+8&1X{dZ4W+!qOZ5`=@jj#$){1YeI}pk zLyLZ>g9=czD;4FZXy;9okD_nOArD1g&qQvDcDRv?qV0>2lcH@Ek%OWy*CCFgEnShF zqRoeqjiOE6kd>khE0Bev^@Wg`qP4q`iK0)>BO^uGsmMUl>OWC9MV|~nVHB-;%Kt;r z%J%$oidOu|Kci@QB>$A6W!Ly86fG^sKc;BO8vbvJ7PsUdQMBj)pG(ogdVCH=^LO(P zDVo=fe?ZZkd;EQhX1C+-`Ow0x&-vjLeL0m+p=e7%KAED;EBGXeHdW&jDcZ1uPoQXh zTmBu2*8RZ`qiAg`A5YPz_xYg|Ws7_qMXUGlLn!*B7avQ}s&RY_MISBXqbXYcD<4JC zhXwgaik2?o2UE1<8b64l#nt$M6fN2fIoo`rYT?^_e~RW`)cR)4+^MKiX-SK)jmOz*|NNzv4+d@qXLpTNK2LyLa=3>EaDg;Of;BjqgFx z#J+rYir#y`ccW=@ogx|SjM-eD7^{ailWqZd`pT_R`Rb?lysVJK~Z9R{xyo;xxhE4XxK2m z8AU^%@l7d;tHC#+DE4Q*F-0+N^NlEq`jT%*QDh~)0Y!s8=Ic{5(8<@MsQ*yDE{Xql zhZ%Pn`xven#(KtkJnq@1oli=b zWI^`p9rW%U_m3^wX(Eq8W&O(ZMTy`dzsQ@9Pxy67TBIDRx0y+(o~9Tww55q;6XS_Q z3f5D`wN&0l#uJHD9_=Yoi5r+ik7~{7>nBoy>zO>|q6LyzJ*lM688@CB6^PdXsl0WJ z$DCZAy1%St^4Q7Wn0{U6Gsg3oTu)7}`IK?5A;E`ID`qnZnWZL`!yGeG6Ewj_{2C_j zNCL`DgSg71IBn6Zg)p=5Zk|7^2q-%>HX%}q4oe#vpQ2^(36oD=1Q75q_G89-VY#j2 zlhR}3AiP-9qgOGWoqT1(E>-H+EB_lug_Hz{%hipL4lr?G_%8p^NHYZB=5+*rK*<4t zxBQCGR5>tYmS4_zDUcgiy%c=-g2&?jy$JXKE5m;g7^ccEW4sQ@_0?`&mWF2Z20h7s zK;r*TNcsOJxqfw-oUI)1LH_@j?SpNfSpTxVZkb{}Xf9!jH|{VR4IRQ~g`N11PWS&O z{78U!orX-~b!e|5&x?E~X>x~NnM9;5s{De8v|0;P0T}|MCu#t!+2w-rW33E6Us|O_ z6)zM16))=t?9>$1yz2=M>jQ6g`BVLP(?LX;S0LGf7gcDh&%8!wHFJpWuLsOS5#5jb ziEsU+#LElBrhM}0q1bSx8znu>+`OpNm>MfiZy{ZyFf*)wSA+|XYN-z5!$bG(x+Wf^9^$dhpz#& z*@eSX+CHBE;ra3jMeFmeut7Zzp;K26QK$CvED*NE;}xyX`c+LvbeN+ffORP5=s^Dj zAzbW^qVX>68Q+?@3$eW z3;d~QefFhxsjUr3k}CmwcDcX<*az|c5aRiJD_Xw-CBIQupr!DzB2?gAW-pooD)6r^ zBtqYFNYVP$c;$e)8V!Yq6`&gIzLyeE4L?T|A?m%`E+_B0xUKrEi?33#Cg=YT!aP0QGa>(f z0cT&wBJMa>9Do1su(hD&P4g<#9aCK+Z}`rTKfHI?2O&J#3$W^U0h6*@^@n66;fKCy zHRKg2Gcq+kGAe<-*Y9wE^ob4!^sU8Ve= zizYohY_B>1adz7)e?vz=oJVwq=3RTMV}yCDWBSZH)$;4z?L*YNWs?W#-7SX_>Me)r zQ}5tXQ-?{q9Z+XCNe37`DkDB2#}T5m-%#vlsi9QKKYQwqWbzD(pcK$nA-f1w5J8s zV0Z{lMRE-SFI@@$dNmZS-vW)lQuBwLNv{F_P~=RK`3GFx654fkDO#U?qv>k;VE*Qz zHGkj*FyUSMO-1YTZ>aeOAnePU0e^OTcmFj@9f3v&*IcD&ec}yzs|^o1lbQnYP~=RK z`wi42@G_cEuhCG^`cSE=FP@H zJ%saSu#0iRyjql^^=nW^lZ2?U@URiofZZp&sqy7Nal*2SZ0{;Buy^gfDtqJj|L})l zo`s$gkpI7m>q}QN=MT<~j{S~45C_oDe%?OPZnMp?m9lYfEKDe zD>%v|I#*jxgknt`Q~f8C=v==NQ!|pJ#B;d7BaFKYzQ^|+r*V;gFbOC1t0V0&xXi;$ zV%2GxaK8)FIe&;rjGv|$Uw@IxJIJ`ZNY~cB#*+&Co$-i}3ZzXZm3V+jq$o9MO!9~% z$Uqw7SL|<0;*V9u#wNt#WT*Uo#v?G$U(4@fJZUQz!)i|}zn8H^eLhnDSH>0%^ltKd z7|&^Pk(#mi3*%M{=27H#GoIn(LKR;i|1*Aa9=h{crq_jNbvs z^-}{5MRNf`I;|3P|L?W*nCe`f8jQ{8ynFO~Kp` zp?hI2-TxN}8yn{7?w;d1;VSP;a(w5oa$W5UY-en>teKXtEiUr_(|Y4mV`szs@T=jq z;m3LSPlym6MuWHHO=e!^p|Oz(=|k~X|57rdBGNLVU|A#{6SP~=`u?5K>r@^SDJnP$ z7_+-VR52bB8J`dv6EQ3~N;>Zmwxj-0v_5OE=0ot{m5OBQl~S>eiJ&$f=_PDOdiB}z zll^QwI8-){j!jLE9}*u8Gmp>4nS%-I%)$DsN3~G1hHKhEz?$7Pt;)vHk<5M$eKaP>Vgc0+CFJWZXRda?n4+DTRyEhMU zsgWr|hbPn+o)Mcm%GV*HW)TBN&C)k;dWxDXbcp^;JA^_uF(Vy6N%irKEJ*l97S!jP z*2|CY+f4aVPXSr)eS8OzZ%Hp2r2j4HrNa$szHrCX5BRdXWAf*#c2f}p54fdheM2Xg zRTGB`n!Z4s-33hmagF`fGxYnFj}_0{z0d?zO{*!`_|Uy9lu`98y>^-2Hxx*!}#%5InN2*K5{f^pBF@v z#%TiCVL-kKv_ml<16}ZhcyGI+_3a(22?2*-yk0;&6v23yI313(r}UabnD?5a&pdjX zx~IT`_y#a%w;mYE*y3F{v1^;r*E zt~N0Y#vZ^r6ob+KYJ$-1CcpIRc0!+a|CwsqF!yx_+M$^H0xmcR@2;_m*5}<%Gl@Xl zS2y6zF7AtVlHk`QgmmXeiq zHdG2Tjx?GLi#_u_HQe91`?#*S-gSALA319~zH+pKIDkm|J-cXk+ZNf%TQ@^ifIls< z=D*D|&DBi1O#_U#43)w+hPMhk6cz)2F2I$}3mk}99u6~~e zl%E%0*Hsr6ospUvn-m>S%6r1RdeO;nvz;mz_n67Yk~P&+ii^Ns-Q{B#)Ah9=W>$@y~!lpA)uxZqXxEx^mS61H$u~ziExpCd(U+y z+m(PiDqnTK78;ZK7F)@rS6R6Z{*+)~l{#FsZv69*sb2q4bR$Eqc+I`I*< zi{y+6i(Zg1;lpxj*6pO=rrKE;umx6PwQKrfB`Hn>A6*6h1ef229y~Zk{q#PQrxd zoO_Dar@QcbHC>2ZN(H(hiCv=SX~J}NJ4Nd=UeH&~7_J0{17mhq0xAQ`jD4qa!guBs zMeFmP_q&=mc-2#YH#@JoinnsMCp>2)Dq5fKTuqD^EFQ_gm)+vw&sXgsAcUu#Rr*hQ%WZh_hQf0*EVq2Eul#oT+YVq(19e5o*>DPLT+#*@aUCXRUZE2=yt)6|GNw z`U5}e38AH~@p%x+lX*q!Q=e8zO&#vc-vR3E?#u(MuJ)V|#*^gR{z-Oy=2NPunL{rh z7TR8}_+JR?32POt&wA1hHS3zf!+2o*HnSZ^fW2ie4k7zq3q|Xbo}kG_3!P+WXgi78 z7epA3ldsRmz2N$MJW`t**2*|w9+I`v-=jo$i^+=Cx44+2<_#7f5?YI^{ZfSS*yoDY zXDd)?leW~lOMZ6O&)?oVt_omAdvv_J|7vOJ9?_3 z^=ZGGrlL*q|7C@FI=Sb$&bmrDBjNmildEA*vaPp1v9_^{H}5jLP2G+242KN)!uy3~ z{ilcj|LO09CPI!I49YJ5jBhomAwSPc9}%ArpB#~rnw%LQ6PxPm5MR$Emi>CBzGb(4 zpt3By6UcD^e|B4`K>o=o@zFlkJKTiz4!1t*t(s)`&4nB%ux6M2B#?FN$n-?G4~Y&m z{Psnp3fmXySK-S>YQr}ZavV?vb}2-HQ~|y)6CalpSc7d9Ne#AD)UUyo+UgqA7jihL z0lWQdKn>toOj>kme3Yu!f4PoO|8ku^^)H-i>WzdPJ5Xnr`Yn)pVtPuT;kR@p?6-8) zXTRx&ntcr+#|G@#y@&|Ho-RC_4-?Lt59@Q@_=TD?ba!iLyL(z}QcPTGd`zI#H_2|F zP2Kcsut8IUrb3PdYQQexUZB+@5+l+hf^?e=@`oZeyx>C->o=>L0H%5~R3L;?eHv7N zcAWKcn!xpi^v(XcCP7+FA;$!)*_|f>%$|~wHq^I1t(BdbYhU2ZTz6P)YM5V)Ksto; zOJZ7Fqgnxbf=|zrvHIzGeUq;}q-GC2-4NQIE*(7MGJ>p3*{P%g*{S*!_)L@7xS@~} z4i#XxMGxpRL!uJ{=b6=VqWaZ;>XZLebG~RS_Tp9~RDj(iufA7P2V#@H zvRwA(E`NbPca`Q-K+w|>)1Iy-tqJEQte0I=w0=)tskyxZQ}ZD+wK^!AkX>3%(fXu6 zic|Fuj;j<_D*TYqQ^vi)-O}~5tAq2HbFh7by}s=mTQ}<&YmDWpg|`^Y)6Drzb4}%q z*~XfNuMO=TcO4TPMY&J7dY(Dqhr*-6Zieyyr4xS|lOQcR0po`O%ET+}l+epeBIp05 zM7Z^e!=)By5-;UfDuFl_4ZXx9ax!>9X?*xtL^{2`n#|+X*?DBz*}|c%Z`w zIT#NjxpQd;5yvDySU`o-{G2q%&LnUzNV#|xwuPoygE>Z!l}RSFz?ufSG>|1ULsxM| zATyKT@_?$!ZUkfsP2cr*03c&%S~SSf9T}KJeFs?B@6e6HUEhVde9wg#Z{4KF#M()! z2;+V%m8f3k3p4J=QhCJY(jy{Nh)KLJZB(+6kxDAa*pTv;$+wmlV3M1U)=XZ~hWNW# zP~a=%ym$p1P_W`4;r|KEROIj4;Ge^x%VIZ#WrBnX@-jAj0_i{{qNYtcChEQq2hFO-lVNS|1UMJV;yJLP&SGi-r zTbffASck$}Dzo;VQV9DKa>mTi*Z}t66)uihRIi-L!yI|vBq!rf>A$;VlqVz{QVYnCxL-k1Sp4MU`mwftm4~i?Qs&`dz|{bcWE+N!tzrXc!y&7 zk$5ZfiI4Se`PId4UZ3@MntXq-MJWWV*|yf(^-%0#W$FRLapz59^PM;KZT{7BHF1bi_Wkj zRT+EYm6`^*?5z@-QRKVqt;}Q&rW-lAs>)?=rO@=b(-Rgv9ix+r8LA9Awlr9$9 z+Z0rq$@V!|af;6mm0~=3`Q2ckl1y?=`c;vh@A1y+6}Zne+nFR}RK}y^DWe^>0pl6^ zU#=-o2_^?VKjSJM2yEK_rRa2W|NnWI=XLjZ*Y_^7v%4dUJH{2YN846eFIY=khMBWX z*G=_|qG6w*c=*t;&;R$X^r2+P%9qoSsh>#Q52Y0-LUlwYewHV4HjyVU$R={VrrJ*w zA>=dw;_PyTsfqgr5Mlgyn4l`uEL_D+_f^;w@Csb&rNP-+0{P~<~VSO;?(66&`rDO$e@ zXWFQ%00|=P{iv=0%$Jp+0wJ6)71u6dd+Cg#^;sYF zs#(LE{Xvc0xVQ!#( zqwNX2|6gpmX=!DiX1ZW{)tChD{vF}H;Kw2QCqQ7C^eshpfn^zKv8icF_P?m;)KMwv z5z>DLw}{xLStaf(TGyt_OhwgQ0-`3n0B?3tlN#O-)SR4DTSNQh>4f&n)AeZ^HK%8A zQFI2{>|7M-v5|>sHI!*PHFk(^my%Vy3SnHliaz6TO?YZGA*T~CeuG)Cq=s=)B>r|9 zAzEy^qV)-f)$!{Y9hvqF4dKMtL`dkDHZ)%Pq!yuDw2Pv3X)pb!w3;@oj~#$EyY=y3 zXh)>MXYDg+FDXnyw6Y4nAVllAL(TqGA*VgCXZNKB!d~(v`|MokePZWA@9W$7=|5_w zu;pt9OxbPuC{uWUs&o!&--0AtWmdr#WUG8~Le09okkb}ew_-dB;by>R-uyoi^XC6a z-@K1CJL)PzP8%S~?(-7Fyd>CHJ-g*2$tbh(y&xIo-oLbIpxZbA@HPC2(c8OcVRc?(HBZ z=B^Xk+;x50IfK=-!NjkJz{JG$>NByO_$;&Rar#^zYPf=lTZF*GvYR-FiLJy{nPq*f zPy0bfwTa>C<29ho{^~>7(UWih(i<#O6s=GB9vMTq3}n+!PqIo0Bz+iIFL1 zLq5XUkWZiU?Img}!{du4z?t3S3x%_^@X1j-glE`#MeFmu^}d=fbmhh&>B=oG`q8^zmefRkrFLV_&$?UEk1ies>K__RlGSk%a=AZ3Nv0d zjxf3m%RF;Eue!Io+qurUQe2#KiL;L5fMYQClpD_#w6C@|wf$=AYrSqAZh2;zYRPY2 zX0B!W!St4)QTUJHy~9q2rM$>Bz$6fu9Eas~HVwY68=ss63m59oBzi-~U1IVD*tTz{ipqn;MZa zDt%~jQjOS=k%=iVH`gF#`gR`ZEhgPX8A*6ipi?Yr`u{&)sS%SLokrWER`q)S-dKtm zeX}T?kWeEgF=FcO0Xa%54JMgVwM9n^jfnIW*puPBDW6DEpum*Kv@~CtJ($GSYbq%% zNvW~X$uPl=iil1oUphtI8Lmmn@hc*xp2S2NC*9chT&=$zb!FduG@f?Ug~=R8dV4atWXgkyl9#m#UNXHs{FNE4KS!#*xq&*8Yom8#XOg6Nn zG@rK;wPHB9g83OyONP~=`}EftR!do2eAg9HYqemq=TmmHTCW^>jmgsKSD4SAhMF^3 zSCry3o-ovm-2bOa-~XHHI_P@Y+0U_pyUjJRPqv-1m9r*U)|;Q2+nMGXuNtcvMu+bU zFCUirqBFk!|1N;jPx??IJEtGn4UvjQM#Gt$I?!6oBMzw+^K^YX%U-#!@{tH|!4(aR z*pLAzg;q7WW!(~Q)AkFSFBN%B|zDeJxT|m+L{kYHv zYR(Xf@-}d07mA|c9L&8-Sl3*xXnpnt$EevuH|ZC;ZlZD$6S6fdiqur&|omRZ3gmINLMeAGFeMik0rs>|mnDsQRFxGB3DqSL!D_zp3?7FC?3^U%FK$-Q7 zCsU@LT*9?tgrfC1J140*!_8tZ;LPr3kqkeDv&J7x_`bSH(fYg{npD;hmi`9tX7>Oi z7;k^CG9g~RvZD1X!1)Jj_Jj(six1LPK<%3*bjyCJXnoo?O+Y$K*FAtX>*-qVFa92G z!njO3Me8%Srl@;5gwl5h=Ilc0H3rw&Vwbu==$E>nPv6p3O&=EbZa|;)9#A%XBK5Wt zvL#8}LRQIM`lQXpRHVuMf2%O#LSt#eMnfyl98ZM%OLte-MVH_z?EKi-%(2fgfV;zq zToL<5dn4OE+hFSz>u75M%SVWKwd{sKn%qG<7|BCf+eJQneu+*uy=5iB~vSagv|$|CI=mJn`QK?>mt( zF@X^>qnP+_Nh`|UTc3jpjbvY#@0|h~!Nhy3shQ%+LYW~b3*vL|^pc^T)oUaqzmt|1 zA5_xTODZb@uB{<10Ai`+Ag*+V^NVuLDo@|ih)-j3)2gYba?_g1B;H6<6zp-NN)2b< zctLklD24sdONfk$O~6Y-GW+4+OC6ZR-lAkP<3Ah{ncP~FPNUpfConW5zLp_#Gj6nZ z81@icmdaO(hB4ec;KDR1z2fs^2N*m?5|<{8xgowAE;N*RdA>VX+;nkFA^~Vu^rhAt z!f*+|hLjzp@#G8Iv8=nls?B1U1Z)r+$^jeE43`-xj)HEqq8N4vsU+XVCz8ph+vNW)e$5O7-2Fp+O8MMEN{LTWlb?|Id`}|ChKfyJ|YUj$a%_xkURq+f!Qy>lDjz zOJ#Gq=?jz5*u$_i{6=`)uuT2?{r}{Dl|FOFgR3O(ZgGO2J!Dr&uyZT%nM99Ow7$=z zNd=Y9M1WUqqkw(hIR=BX4|Z}QbfZcrTAy~K8*19%uOA7tS^Mk#&tHV<;LjDUPr3dE zKguIQN7;9ZBUA@IQM5kgdK1-@;T|UwD6_uDQI0N}ED8ez!gzq7&$w=7KgJm$WGtU3 z3Df>%6s^y=_IWj9a1^HlW7dvh#m2$TrG$3B&5G8iUu%b&J~)cgfIe$Su|l7oZVB1G z)fKHzx~ArVDdgHn1=8$tZIFdfCauY}(PsxC+-HYA;ToFHVnQ&~a3IV&7)mA#TLxcb z!<$D4-#3rw^NrACCxA|!61q+ubc;i1_iCbOefrg=syj8TF3CVYM5~MM)K94P9HVG` z%2nT1Q--NJ2`GnXs#bglglYFb6|K*>N-Z^G=p%`t>mxxu5QKKOBt`4fucV2Rf=nz4 zK%ZSE7BYuOXFA_t?D8vN+T~Y$rWKE>4Gmr6oe*>leEOu`5W=+c5Jl@VuAoW02jg!T zFlIgeFk_WZg;4GIOwsz3Uu~o|GDKs<17+6H7?`r!Gefv`Sfpru&gJf^IYWw`p}?74 ziXPg9@iCP83JBZwH5IMTy6ize)^Qy#52hAmZyiO zqo70F z-P7C?-0!+ax`(@mxuf0v-EX?Py4$&1xEr}^yQ{j(yI*k^aeLf0cev}Z>%Qxz>yqoV z>rdAK*DtPJ@P)$7uC=a@UCUexU9((MT;p6`SB5Le73Ui4>g($1>f~zeYUZl%s^O~S zD&s2dD(G^;R}G#!bDejc*Boy+Iy>4pnmZaeYC0-A$~s&|uHT5?Uex?BWTfh)xo zvw+Sc_OaR+}~4^4M}8@RW19Dp|@{idza=oEEeBxjEN-*L=-<-h9G**u2mD zllfcoR`UjPw)rFT67xLsbn`^>So0`zs`(vrjCp{$x4E0Sz4>)>V{;vIHS?>X?lsQy z&J)hV&VA0GoZmXPIyX48ogYDFjCs!K&WX;k&QZ=(=R3|A=KyDKXE$ei=j+bK&N|L& z&R3l!okgAboOY+d@x<}Kam#VpamI1f@w;P><9o*r#}|%uj!zsPIub(s)|cSgQ_ep849YRxa18`6~raYK$RDlR0LI4 zTv7m38F8`n%aY<^>6azM#XUj2EH0LQ`I5L;`ejjZaeh!m#4H4=keD?DQ~@!oJE(kO zR%1|ZF{?Z%hnVFC#fghXg0hK=qCi>1MV&#J#YOc&8O24VL4}KpAfm__CN4~e8RfaS za1f{`;=+!g9*Ya>f_fw_ED0({TxbXNP+TDW^1ir0`sH8Z0_m4`#0B+0-4qv;0(D(n zApP>HI6n>4WpVyMP#4Ad?Ll1-=hp^xPMlu?)ERNU1=MMA-f&PS#d-Zf9T(@d1$9iE zR}<6`ab9syhsAj&P>001iJ*QL=k@{hn>hD%Q2WHWRYCnK&Mge;7je$JpmvLM;z9i= z&HML= z`9N(FXGy=@D9!?tJJyS{dVpFd&T0y3tvE~io7v(l>2IzUXG*{PM4TA|YLz&%E2xje znGHcL7iX3QwM?Ap1oeS9101uCCE|?1pt8gnk|7t0GbEEQ5NAjxpC`_+ftoE&PX#qg zoGzJXx;VWZsHx&~$&l}h(_aBKNt|v4H9?#v8S*`Gn)J(Y;xy@(f;g=fsIlU-mqCpd zrc-#3_;?2Z)n-P;ZNqCG+$Z zCwBwYN1WUU)SKeua-iN2CxegM(Nml>0#tW#QY5Hu;-pTXx`>mce%48xB=xfn;v}h` zwG$^w{j9Y(QR-){#EDWrdtIC;nWwopu>`1Q;zSFmCgKFiJdMN&Z-Z(ePG|$Fo;aZf zs5;^Vsh`yrCrJIQrubeGsOsW-Z-I&s-)jk~s`#E{p335Tl6fkL?@8vVAdZI^I!9S? zywoGhh~uRmSxOu)^~hJm@lua0A&!Un!BJcsCmFJsIPOhQMa6NifhsJHlMGov948qv zzbHzE^oXKlNS7!|hIEReWJpdFB}3XoQ8J`e6eL5MMM3Jj22qguZkQ-E2@B(%ivs+T zdnyVAKs^!1dO`gyjvWFjR~*{|RE{_n{wDW894r0uo;Vi%Cij={5ByE;w(t-9P41@f z5ByE;hVV~gP*;V2%7eNr`~wpUcS(3Y3e*MRc{HeV!t*Ym&I->PfI1~SF9Yg?@Z16F znD8tE)Stq$L7@H+o^=3qSa=4#oI5BygI>-Z5S~FV=YA8Orh?ihJRJb)SK%o%BezF* z3eCvw!XubixMjj4m{_=_!XuajxFy0P$>fWLT*>5%gj~tw z3xr(B6?1 z;h|)5L3k*c{9WOpWb!e>L+O`DcqsjHl<-jcFP!UO4-X~F}kafS;I zq{c}W9!QOoB;1!8=N;j`)Hw0NeW`Kcg!^?s#R~VO#)%g0ON|pH+>;t-uy9W@`9R?w zOf1|0;a)9JZwvQeV&VD<_spQ)68=g7^``I_j4|#F;V-FidJ2C@jniHDOKP01!e7!a zy9jrsUv?7i_5;;HxZ4_3d*LpOMy`!;_a#uRgu6yiuM2k)LA@s2c?(oC;Z7@1O@%uV zpc)BxU^H?KggfD&>I=7}W~?jRhSA8?7H&(;SWCDqHDh(*w$zN(gj+DixT?Y}7-L*z z;Z{#j6@^<(!@|O6h}pfu!dy+n?9QMXiP8>nF&irFsxD?jja*g5Y?udK zRm5!g|G6rQ*^NO}60>0ZN{QJ8L6sD)+(1#Tmx74(FYx0A7F0KKB&S&Bp4%Aa| zjUCkA;uK(D=6H6X5{h6d2Vy7Wt2v^~6+V2Thq4(JD3Rk6H-Vv@!zq}<}1)JG#2v@)a_UpnG>6cf9E7C77 z3s<1q*e?lJU}3kP6Rtonu%8hwgO%*3h0FaxofIxZAG9AAF2ks@9}_M^8`=L9E?YqT zAzT7O+7AhrU{u+E7cN1&+kX=-RR^_CxKs?(ufip075g6HB8)2gZs8*I7yD1bMd%v# zABBrmL47Y=EDY*9;ljJ1b_y4Uf%;mw&Y1KWkAgr&O+nZ=L%;elg|;(NQRsx zoRJ!5hHyqQ`E=ooWb*fgGg9MB7EVjQoG6@@e)*noS~9sPoR&;32&W~Jzbl-UOg>sT zC7IkSoRUn=3#VZ8+eZqgV9K+P5Kc)Z&k#;QXSb&bC!y2YQ-za~$&-bXlF5^Vlak33 zgp-oVhY2SolgA4uB$LMpC*A@TE1ZCd%pN10kbW5{oG1=zkZ{5Ts=shN3Dn!d@xGw? z3dg0t`Id0J22>*KtZ`=;ocu4ssed<|_&H{w z3C`nAIE&wf6V+ijO>Kpf)Dq`(IA^bfGxj7nUnjuXx;vb!>%y737{|eB`Zk=T55g&W z3!I>{;PgBOPR>zqYHkZB<|=SncEd^e9-NYozzKOfoQ{{m$ykI_@enu>cZAb$bvOwZ zfKzY|oPdwR>GvBr`L2Ld?*usU4ujKfS2*d`hEr}4s}0V#H{oo10M50W;Y_;_&a+-P z%MONfY->2fR)X`Z6V9%8;oN!{&a7MEyt)L=s$=1t8Utt4_HaI}W-e*YXEvA~m@b=+ zn)aA>nAVv-G|e`RH)WcJn);bKo0^+yn#!6AnJmUf#_PtD#{I^faE45U^J8x~J2r-M zV@WtO8sNNm8P1A(;GDP)&WN+&e3%Jm!+zkuXb!%Mvf#I{fY0JO_$&5vJKZge8;vWC z^No{?yfMKz(AeGB(pcA6!C1`58J-$$8_pUI8h$WrF|0OZ8KxS>7*Y&ThF*rYhK7bJ zh7txhbOQX(WwaWw6KQeZ3EqMfy;aCtfTG^(z4vdDq{ejm- zQMWN(Cq-SJc^wpWMqZAhju*XliaLaQZ4|Xj^I9otbIEI=sP%ZSnW9#uy(WrY|J-Y& zs6{cafuiPLdc!Gd*2fDAmtvPD7tlWxH6D(hQ`GPvdPY%$MD&!R`gZh$qPnr@F-3L4 z(BBl*dKW#SsAdtAOHuWWD2JkmF6f~TWj*)_9i-@fKlD3Af1O1KD7rfq{YKI4lW0Fh zx86hhD7sl0?WO4YKJ+U^*Ambkimp1*FBDx~k9JdZsXO|aq6<^dPZXVdihiW%>Z?$qMK@ijHqVJ1IKW1$|4=pFg8-C^|9(eNEBfZ_y5l4)sA_QS|#I zw4I^@eb6?F_UEFl6zyA#zNBbxBeaF0J*UwZ6#X(9ZKh~VI6%?(tq2&~PIsko0(VEj}8AYoj(Nc;&K7>A? zXjLj&Lea|nXfZ`AHlQqumiIu5C|dSCT1e5-XtaQ$53FcDMT=LUc@$+eM{_A!7>(vo zw7`gFQ#5Z7nnlr^9cU&+vpb;~6wO?Wrc*SdI+{k&wEbu*MN=cu`xH&Nf~HV3ITB5# zXks}uiK3Ck&_s$dKSC2IN}qtnCrsLu|RO3|A~&~S=+H9;v9^&EqeDeC?wN}{M+5=x|~%daSbqRvCmI}~+% zhK5npVG)X_sC`W|l%lqqP#i^VJZK0-Eq_3<6t$R#Vkl~U3Pn@Y>q4@H$O zq23f#j6iQv^y((mi=y(C(HlOrxJp-apQ1`*(LIVPI?!Jfz1k7orKs$u=nh4tN2A*m zy|NPBqNv16=q5$Q$Dtb(6+4KoQ&cn-U8AV*8FZDRLaosiiV93Zmnq6$3SFYeGZtN> z$n8KED00q1=PBaup>q`31$34on+Kht$g%>RrpR0moubJ29Xd&op&dFwQP^p8+=sIM zX@QPW^z0xyO3~BS=ue6s|A~%J^!G6I2SvGe(P4^m#-l?NmHiU+q^L|g)Ptf@7f^SK zO7=qCC@OIub*1R#>8J}u#jBvs6cyW!I#E=#3+hNw;hU%fMTOo+?I|i)5w)Wz|4*nb zMftj-HWazbqt+BTH=Qj{40@b7FVLw#YhZa}eiyrvU zqWh;%9g6P7q1qJPeT-^RbSDedr08}fRD+_MU!m$0-57)-D7y9!sz%Y(#i%MpR~n-# z6kR%lDpPc^KdMC0g)mf+qH~$30!3%-=v9hNXQJ{Hom`8`QFNjODofF^wWth5M|+^s z6dgH>N>TJjIx0!gp^NAhiVjXjB`Es6D0-Qq-@Zb{DcWBjy+qO8eW(~kzb2xh6zy@M zA{6cBQDJb5gcS}u9Omihp6L3`^@?+lV>x$)t7K2KZMHtOHnU8Ev+m2LWaAfxCx*7+ zli;WS$Nv**fHxchG4d|1D0qCn_I0{1cw}}b5{EInlYSgVFU?0h8wt5?;LQ3(gv?or z{tTXIX(svDZr04j`t09$SsVJ2>&ny67hQ`7Nlr)Yg+cluP_rE3bgR^Xg>!E?ICR`TQfddSFPg!IT_`lLH1 zs!2B%axFkQ@7|&4l1};ecPN>1KGV#P^yzo#uBKl{$Tb7~yvr>1AJEq(o=cxV%$`0$ zpLhELYThs~O~5-u12Y+~l(n_Q(`r-#DKusOGI@}Y4s;ld~PD%cP&`VEThy-62Fv9ws z{EF6R|9W9Hdw2yh2H5A_10mfBa#+NO2>Na%ekNfYKU1IaYgg2aAz9>TU>u?;ojefI z&WuB=65d0r>ho^CLe0CmkmCj3BSJGX65c_wwh`(>#wl9A3e7YRf8k{af-2E{f=bJW2PVUvdPTpK(J$z}5IMfq}>%+8ZsCjVYg(5)1jl_x26f|siGi{Vs3GxH?z z(tlE%G|FZ$OogfAKtt2n8&&1{LetdARsY*5`E-ryzZFDN8J0=5paJeC^nRY?-3eY# zQl`{trlgwTMEO7cu9aRX{w^Lgnc=9A_w%ZCZW6=ZDVL^ltDuQ_k|9smoc$b5amuktk;UxDFvL!MZr$_A{( zV?$7`>d54q?%rkCk>vU+t`Iba{ba6nVxa%GlE%X`g0NEI&p~p(7=Jg$7%m$!JX1ZT z-5`Q$0^5f?in|YD`8(@uWQ=@c>({lCR(0a##;))i|yK`ZKmeo&%@sj zcZN+1?g8MA=OF6jn0rWdXIr8HXNTPI|%>WxRIHW zkW42H*L6r_W_)zA^o4kSArv?wPy9;(1!><@tyHFDQh4&mt<_y}KPqI zMofHqM08|o3{=wlJruc`LBCOE0C{NmZ@axKpxjk?l2coI09Gabq8Z`50+hCbfs0r( zqtj2JNBDB!df`PY_hH_Q56w55=(v>U*p!U4p;CjwGhmLzWehD)o?FurC8xBvB$SuM zz_}2x;UYZ=JHnqqnG560LYM#XlBw-HbYv2vLjBN5C~IDxtdaj#mTb@X6wTs{c0j?i z@@C1>^c-bm%Kb*!^q|F1-cge{V_VgMXQY5WM5&Cg#cB-M`#` zg*qmAL{dU>q%`TGhEVK#dGfU=|6=JV#cK=&K$6gz=iwiq>a7 zY@M1pJo70D%vncs%H2EIwE)YqHxY7Q0rtZgN9if-RhJL`lgr14 zNIgD2q;LJW2sM9Lhe`l{*72MQe>v)lFkO|ZXnn@95B(Uw96H9zj+!uCDaXvN%&*Tl z=8&3kEg`o!FlHSFDcd-3T&~za*ss{2&pLX(nss#{_a$JRciGc}&)|6fCHG}%gGs0^ z@1baY%2Arv8(`>SAuu%AjccyR3EO4gD_Wm*q+M<3Dnf2iV4Zh4y>$$&$?3f`n$TSu ztxtE5=BpO49Vr5IS#L+kzC0#2DLp=&cnb;H53GvTCq2-lwlPd|g@H8dX%3U7m;Qw5 z;uVV4XZ-dtHRJL^ZXsaYit)li!bl0htmcZ=C)%%}nkek_3Ib8qJ3Yxs?!V+MlsoXk z7j)phoSHC~vAEB8Xgt_zHc*0*n;6Kc8*gxvfy{j!g<~xMeB3# zJx0wP=8Am4o%LLyy|SUJ$Q=1ANpp7SlYTQwMH=$|h3_Pgze1PZ3W(4+r@IpSvHq@40WfFT2k|-oV4|{qEiFUG5$3Es#Gj+r84g)V z+dUQX2=eZ9canRkI|{N1_I7u7cXYRQH+MILyn@x-72KuW#odM6ZulaA!S&RYYkah1OcbYrO9pv_MKf#v*wsV`gb=+!h1-At97|!ITaO1f# z+(<4J@)-`{26O$mUR+nMJ>)fP%GKv;a#gtUTuI1pSb%eK77h}A+8;ok!>ji5_LKG_ z_5=1kknivt`&Ro#`)Br#?H@wk!@2h9_DOcp?zLw^{=;GR82do`TlSvz&X5POg}t%8 zuD!awlD#bCLo8y?XXorD+jH9^$cuQ>cG-5;b{t-E?6>W$L%zf$+fZASt-r0etvlpRY;9|9YiO%&t7fYJ`4fxV3fbH?o6P_jA#$vD zt=Fv=t*5O=tp_2W;!oC{*6r5K)^*m^kXLbub-s0`b&7R7yc!v4O|>Rihgb(&`&oNI zp2haome!`$`qrA(Dv)onq_vo}fYoWWSi>Oi;seWV%T>#H%Sp=-$iKM9@`L3Y%T~)q z%V&^>@k2|NWv*qqWs*gNe2kfv6w5G6jAfwZEy&B*+0xe1!qV7M*HRtwGnTcKuoSW6 zvv3v@Da~R}n9O!(@ z+0)tC+1A+t@;26WR(Do%mUWhJ7J>YYoYUlZ?s(+52XAC9JI*?egI8_8W4B`$A|%WAdPBujwb#PSbYNX2>!mS;bV|RMJ$;RKVmkSTgZB?C4`X=<%Y#_{ zj^zO?f5UP=miw^Wi{-Ca?!odGEO%r1GnPML`6HG;VEH|kyRiHY%bi$$i{&?1evRc0 zEWg5XJC@t9+=}IwSZ=}c3oJKdxe3dSSZ=^_J(izixem*tR_J%Q{%r#~R4a=!mzK`V; zEGJ_*3CoFCPQda#EXQLx4oeYB0n4#izKi7;EJtJM#S&r3V>t@TkywtvG84-TEYq<} z!!i}i;aH|%nT%x;mWfy#IgaF^|7pnWnC=mU|Ac>T3FV^vIdsbv5dg7 z8kSYDtb%1_EGuDI5z7i#zKUgeEX!e87RxeNmd3IamL;)#1;*7GC!92u=HT*#?pnQ6H5n{9F}%0ZCF~dv|wq*(uAcEO9PhS zScXZG{|C$GSU$t@DV9&Le2nGaSU$os7t0(hA7c3c%llZ~!}2dI?_zle%iCDq!ty4T zH?X{pKlhBjAOIWW>+%B>35{vE*lU@B$@%$f&@V&z~}wN&J>zTy%Ui-q=ai%x3Ts z!mmi*(+jkQ!A8ozFnALSFEpj9t!B|Tb z`md+_FaZKYn?MKzs{qk}tyi#PC<)y-)JM_!(GXLfsG=bR$ei66__NBK9fUtQ%o47@ z%NZPhe?bPv$-k*NLr8HW;LIwdIDm8Dp^dOVAY1%EAAO5Y`bf>bp^)1U*uTRl;3t56 zz|oJ8-=C{!eex3*tI31u8-&vIfd@#!dY}B!hJ7#iXu||eO6S@_Zhc@sC{(6b9YYE2 zy^R#DZ}j(Os*T=M$gKyo(?Ui&*kP6s-y^>P*mGLH0^{FTR{+wN*M$nON?#t(y}PWU_4$jhsrgqDa%%(sPK za^~!xUXVF^Y;QGL2;!{;WSIr=s?MpZLq1{rV+BR)oA=!YYQ_+1S`!#E3pG_UmR$ve z=J!h!txtE1SxvXHkXr-jb_qdmkR1+$OvtzzaFM&eZr$Q zsk;TdgsTdKSwHmr7e@?X{M9o>>oXr2re+SSU=?7_Y8CW5Is3VD2;uD?C|aL*=2JCs zcq&vGh_ikwB%i!}P9Z{dTU|x#Q_i@irVPiLN&p36w%FN{a z-z&`1#y!^coy+X(<5 zKAhD9tiWn$(+#dXMuKc`@Ao4{x!+IU7%K;yUct7v_$E1Idf!kp9;jxwy>0d5teltW6Q5h}5!Scf(`Wr*ezm3HGhdy7HLGvJ__3ygk@CJ- znee_@S)cc^;%eUDpXda<+50E(Lq=aD3#EO1AEAAHpFZuSn%9>VgxromyB(u*1vR(& zHRH7eLiJjLKGh}n)E0*AZU>;s>QJGfN`|0s(zxm*gs(dF2`~2F$g~H->?aNBJ)<)I ze4H<@C!8;@*XNwIMQvo5G}-}Y_LGLhnT|dm>r3+Y-Y&i1dvA-f)U09q)fQN@+J0%f zhHvcoNMD#jOnqUBzNr^#zAg$!`ZhqC)sdc(CT}o(Y|lLW zmS2qGHPFZT>Y;h=_=a zh=_=Yh=_=YxVxbK&Q0!}tS-Jubp z-gOQ620?k|1o_0fYRN}mG>Ac$^Z)DWYwJ9Ij}^}1H+SuZ_y0~f6XEpoVz>wJReOKi zceYH({C~FnwoAF*Wi+6_6YjQe%8VW@^TCHL3QjfPAfxDr0j~Qt=&}-v~&Lq%KB66EL6_ zoGF(pH?^64!S#59hr)ud1?1m^)EZ_GD>yCmtcVivx#RFt@D%IP(?kahkRF#60LeCc{^@b#w6nqhh=7y$+6r2!xzCdX%Gf6M_TI83msS82CeakY;9I@M$FaPq-*?!SV8WNI;WNP8+MlcMCod@WZC9g^A1-94nXG zkMHz@gQI+^tI9#Xf{z8vO@dlS-38ZpRA_e$jbj#k6mNn^Wcj`mNSjC^kOfBsWanxs z3B(QyJ{0PZK~cYg!$KW0BwknWfq<-Pts&Xi^t7e%NYBggA_-trof@$3GNo2mps(R#lv@mi!RRTbfKLh#n;fj2=;H^&t}i_~kc3=^-fxt30##w7Y*~X<_ps4roPfUIf#6 z^J216Vq#O}Gpz*M?NCcT_8Xc#7udXr1#D597a`bTyuH+V-(M7$&L z^Fb)>*VU3wyUWVbf_F@gh<7MI2O-{JBTs#-vX$}F$If#sHtY~R0@$KGw^Q!{eaT9=6{C1oYP701e6K4GY zwdAvJyUKb8Y{!iUcJbSB3VWDICBfE_vq`ITWt>fV`38#*+i~LnU;K8Qf`7+&IBvws zf1=fr{|&bO%r*ihRAZqL;064Hugy+_(Fx zC7*xGC6*sfM2-ReG~wI1is?fm{DivnOSRv490e(v z!iV3anFxUCM@7=~p}P%){?BV_$*13_Nn?Q7*GQljH8&6bg$hmXyE%to-<-q8-tau@ z?{FA(1YnCljH-AHv?KIpB?5lqkXrH^uzn%a0DS+Set^NV*w9?RTR*_l#J$tq$Mv-< z(RtH3&sp8E)6v`hsXf+q-L}Y9-MYyd4fnohTP)@m&23E|nI1O&4)=_E3`J32MkVNq zbqm7;2mZaMa!mqagdq>HrYSGqBb|WTTtaG7o}VfBM?kPHq_V)YQ4SCOEg)_kQX`2H z;%$w;1cY1z4N~8LXVyyv=LDEEq(XM3^WTzHBA}6>Uoj>pCN>6+Y{`CeTR;v%NR4p` zSve_*^3_VD(pv&HJwhtQizwX2(tmF}D(hWz&BiHHU1n~qH#;|0wq}XgAuSOGvxIo> zl#E#1u3`Zj!c4p3y|_((ift3)8?ps&3fOdD+7uTPmy9o*`$NDrQA|BC@T^x}N>(oZ zPB#SX$R=gQWF}8dZ9O$NA#1v9xZedBPOT&@Hz#l_+I0c-&~cc|dF1x|CiDkJnOm_x zFxLd^=><1T8-_3VRX_)(RjL^sR|QNBw6z4n-q_uL5iq(3)t8kE{R`d;mmTGbP)ETD z7J+F2uJC68Khi<%qmfHo<7EK@2(3{`>G(;&IIpQB;3e``yCl>}8-^3T3Bj^ABrSlASKj*sQYVVZbm9mQVMBB^Oo7RDrmF8c~_n8(Ozc#iu z6zD(FSB;vW`&XDXzQ}*&haD~iF&0rfT+Bob=1;i^-axDfK0OYptm>4emi*Al7X?gc z#SdZV0^k-Eh7RFoCeQK@1wrm;Q%gSj3HDV;Kb-!Y0qCMme}zwdC`DHjd?mjl^ldD{3Q=;ngk`32WP#YRPB*bTrEh zH%#OMv#1*;7-q8IB#dpUswJQGxaJHZ*f%dS_GNlrpyRdLL6}?Z;4^=64{Kl8sLcgt zQ5&_4ebvP;q4biohpW6p`LrK@!_vZaH#tBn>be_-mR&*<;uc5Ml23fJkR^u88M1*` z)a4B78d+V46U64j)RK>SL~{WkxI&gdS5Q%z-6imx5b_jN(L2Ajze!rB(hMbuUz!skgrtUU{ zra0DriGbICi4T782NoQDHqrrH)XxUBw-V+cjP=MZr>p8oeAWXWv#gLrng*=mlSpwi zL0#F<8C&gjgueDVKJ|OsSZbKDr2@668JpI^UMA#1U~5%ZOFr~|&Fu!z4Ic$)@!c>q za6@owJf@a>?0s>ptzkhj1+YaeNP=ulm!i~1s*&W9Rn6yO&1<43tk z5Q&)fZe=cicLE>v9ZgO&%-xa!Rn**AgBm(ISNWE(SNWFDy!Rj0ywC-cfLVMO3=U`! z*vfs?vJ7Y!15MWd&*?ma+)G{Gx>`819eW&6_Mx_Ct(UCrEVIpDn7yXQjVF!u4Ug(y zjru!kknTB=i+$z)?Qi8Tt_Zdib;)LGMqEs4LTfxMq{gHt<-*HDw0DiIOe{IJGT)NF ze8^Z5-VP|fOQ6fL$Z@$@SqbTJDGc)%ayQkgF=gCMb!9Ef3}&tnAv4EiK$t#@MIKFV zmRU8rjGJYC)?66U!C&kFWKlQXYRs%6d-3}x)ImlbAr3O~2;V_2Kg$}soxj)(a|27#5z0_JqKu*VrxX?&{Mr>Mzs`W2oOF1pj+%P-4PxryH~6N$q*;wL_ZK^X zS=3eJT2sd}-S7b)!F|BT$NjM;YvKm}Vh7;%5)`>oaM@qwq2$iyRYU*cbN-;Y`WQIv z0y*h=Kj5-M3Wz<26!1AO^kePW)L(1^PEi;AQ%JjEX_4tnQ&ATjfdw;P3m_@}@!ZUm0bJH>d zKGN$I0^aKtKKPlvLE!pGf~TcG$PmAC9RQE6M!=)1@xi~=Jo$95zZjko6SjN~u{flL zfSW6x%%|8J>E-QSUnJcl5DN&nN7t!@yX#aw_m^xYy?ppw0`3U>E-Ks9 z_((JzvO6m=q0VK*gia#HsY(97NoP1}ctro3ex~P1PYw50cQ@DPt~h6jbE&h9Ztdv;%zAdUJ;6jSfD${Z@y_s1Vc`5Ov*17^RQp40Ldk?B3 z;1a9Qx)Rdkld@9cHLa{IAbBoiND83HZH@Xb_+_hUt>MjMcuB^qy<#e~#{VnFOa$DT z68Kty-sny9=6JQeqn3cL7`9^EKWYj%EEG~(W^Q(}?4UIwG2EnOCv|Dd4mZ^!@g?Q? zOj2&TW(24vAT=_?wuy0Rno92$a0g^)rQSI3T-L}{BjL69RHp1mRU+X?F`4Pvnl@IB zgd@ekaFFiRR$NIyCuPHY>@ESSDBw%7m1*Mp=q|xcVckO%RDL-$|>sc_adjoG~VdAq%O9#Ey|eKn-;IBoABmL=(hq%eM`* z1~p!bY+_FV(nu?^3OH=QG$=SmiYx+h)tUO#=q54?=(NH0c$v5)ipU9ZHKK@&0!|r( zG!NIN#sZNc5>;xVct|hr|5wp%*LixmA9sD~s_Y!+SZP0NZ(+-~?zR+L`kNP;J~iEC z9BwGopVilkN`b%n-}(pM7A%&Zg%lO8rPDa&Ac!UyK*B-=6V#F$9$IZ0!30|T5Ym^Q zh7=Xj4*_Rpo&hwZIVGW1& z%u$-H*Y5t}`oJveLX=SEglReO7=d$eJ;ngDP;bFqF1b^~nwdCXf;b-wX`it)dd{L)gL%by@$V-qP zd0Z{|=r@M5=$-w=RRLYpHGrY$!J%RTJ?S2`g4o0jyvv#`~EgruUk7>eC8wON~X!iHHIGyZS^@(Z|X{QJ!k;H z4K6-V{4caiib_I0tGcZT2n}#1>m!Br~UVfU-UiCQZ=g>_% z0ei%{=^e+{Wzz}%vgv&MDi>LNm^60;eDRZJe3l7EaOgaLX$6A3v;rTwvgRUTh*Wj} zWbu(oiVP{W{6bq`7nP?OWOFqPPc6PMk9f+$Jie!RG>dOI_SOcdMIC#)1GU!P3tWVJfs0S> zevP$v8-Hk0I{^?YcTCf6IHsI356d=wQsxB{)U_S|R!J~x^V z?tFx`c1wS;7r;jfI!Z>ZEgwSGZWzotLxAU;;R8FeSYYUmEdf}3ca(wY2pHJrcr2e# zKbFs@wkNRE@MF^gsKx)-$kgf>5@4QPi7?Nu#Amh*W|?6s(j1t@Peo*A#iawtv$hcA zSzGwXR?QVoaB8a=Ad5P+MZGz2pCO_2eW8|oT8oAjoT6z&oI=@~)^o6@}YQK)r+}AF4HnZUmrc z0r_OqH<^m%Sp@1SARjQKHZ>o)htM=qrD?%o9dw^iA5wNMbKn3?@Xjl`M?ew|HEy^) z)Bmm$CXwhYVfGYIccCfYibn-St57$gDc@?P!Eq+kH4+1Z8X-bmBGFfaV>_sGBpfMB zR0eetIu4RmzMK(*2i=YW(jDozKr2(%0H}jd*C7=KVi>5sfRk83&7*T~Y|wj!IxB7; ztubKLb^@|-gW9Ri)^RJ_3P`8FLw$iZwh?ffdQhE2#j9-8TIeq({*X#_fflx!VuBTJ z`6h|e7P2c_7IEVPo!*Z276An9R)ltpDiEB>Ls_ zH9iLS160+=!8+fd8%b9Aca(m(&`5sDQPhP-%83_pd0!&DfhGUYl5ouz%1hK=c=#cZ z4ilIVh#!(S^0 zR)U85*kD3^Y%rg?&1RMwHg1OjwWy8T5Nh@1nSim69wyjF5A(5GKgVLjcrg^PMUNM< zH6-*^ z74-*t@%x90?X_D)dzC%$y=Cl)H?GH89FBJN17`6@yHw_IQ&wW^w`!^--{=i*vJHSU zFMXi_;*WL(8W6g{K)BzGRZBj9gQF}zWZm=ue(_m13V-+$Qg56f>~Ealv)9+$RtS^q z-oP$ul1*2W0d~49*rlAm*u_78vHG6%thK>gdPUM(!fk01OYc0WmVArXTfp)|;$$@N zM=WttK4KJfQ4_&_t)p7<@#|`yzk$v4o`4^*5mI|X>QyD#^VKqvJ?m($#)XMi4`3EG z(F$>L%?YVjl&r~D%E+3mb&c^7dH=tjzPHY>#?Vy1P2bzI&{M(v3}gVj0%rk^I3ICb zcg%Ctwr{m}w|!zuvfi>jZEa|I(=y0>(VPz_12&qXjo%ul8a+`*qaN1X&@E)60+UVt zp8tMWL%@X`ISDao*{ziU0hU;aI3yn{;5rsfP3bZCPG}S(AP%poC@mokE-B1TPLZ#Y zMUw?=sNA7CZ#Fyuji0kdj|jb}P&1gL-a@ki)VjhPRQ*4bSt8(iAL2stHjeD1lLSOo zX$_EdruGQj)gS)PhM?97(_+#xVb0dNZL1D#aR#=nBa$IiGL&BP*Ecvxf8Y5r_ zR1G{S1ECTWL8Ari5e8Ki2xp*C0;U0KWq2!DZWSIIMhfUtnwm(Xa9tw=?0l+qF+qCt zpukV1)}w~k(QpAflsoX6VgV*1p1;T7>$Ms?9JLRG8!V#MS=ss zXt2O`X+yVYkid2Y2VK$qLieSW@i#PFiUvla-q1iN8X#cS7P6RCLzJk$(EV`5x;f#3 zi>O~DRv2OPj{6E&y@i-KIG~66$m{=ehJ8BEbAvJX?LO*$$GzRX*1g<4*FDWW#XZqI%-zo2&|TGSb(OlVxX!wc zyWVr{bZv00a4mEpSGsGmYlN$>tD~!_tA@+z{M&iWdER-#dC0ljxy4!Ne9FGVzRv!v zeZGB$J=H$RKHT2h-rnBWUd?W|-L_q|owI#rJ80Ww+hkj5TV(UuGHtQ8QMUfJ&bH>Z zS~j;$2R9X5u%5IYw(hZRwZ33oVx4Wxu_ju_S_fIXTU%M{Su0wNmYbGKmeZD_mUk@M zEo&{yEpsi?EK@8KEyFC)mUfngmZ}!3xzv2ceAay2{GNHId4qX{d7&AZ)6J93Bg}ox z9nDS6HOx-a-==G(^QIG~L#ExPEv7=#Q>Iy_EK|H`jA@{$tEr`_j;Vr4Z@gi=Xgp;+ zV%%%oW?XGtYMf)tGbS6y8;2Ns7~2@@8!H>lhGN5I!x_Ud!#?LMXO=VGImS8A+11(7 zS;twysdwCPTy&gr9C7S*Y;&xJQy6m`d5&bqc*hV&4@VnEeMe=7*GuZXF^;h-h^q=Vu>UZfk=~wC(>3#Z4eXM?z zzQ4Y+zPY{@ydtCgaTzRn9IGq*?Etz#wQKjI->G)>0J=`KU;3lpsP^+gbd744JD^{w zcBvz}O0|n==ohM8cpqJ%+WGzHXR4h`K$od@b~yTpYNze!64ee@M?X^S{ch+Y)edY% zKTvJ|ALs(r_RU1!Q|;X-be?K&&qv=;?X6$XIjZexg1)8NZiLQKZP!)w4b@)nh|W;$ zwOsTy)n5Gpou=CM!RRZhZQF@XQElsK^d;3^x(A)4TGm$d8r7z@MmwmM@j7~yYU$Bv zJJnLxqgSZ*XbZHBYAL(W%T!A`fVNUC(T-lCTKqJ$g=(>T&}OQ|)Iyu6_J|j4q}sz9 z&<3haY=qWRZTteXj%s5i^e?K7xro+MZFCA+L$#4#qSaIzVM8xcZFmZLfoj7(LPb;? z+6EO;ZSZomifZ?tK`W^?(2bs_TEAUr1=ae*q35X9>oxQ&)uKD1XQbvEu~tQ{pe|`b?$_gP_5%;w3uogbm%FnwY!3zq*~j~Xc5&~+tCwLYw-bENVR5b z(E_S9t%c@Ot?^zok7|vYp}ACR@F9AfYW3sM9IDm3h#sR_-4ryNYPEkxeyY`~fo4&y z#tbx*YSkV?KB`qcge0m}X^arnDixpts#Ub38C0wA44O_gPfaw9YOXCPpK8v|D35CP zeJGb|wqYoTYL>51Hr31%P!`pU7tvIz8K$C4s_Bg=gK9b-N)KqO{xPC7s{OSLrBdy7 zee@{RN?V{QR4d+tQmFQ4MU+gnKZ;Ni)owIEiB!9ugc7KB?GF@BwO{=xj%rseD3)qh z7N8ia{p>-LsrJ+3=n<;@cneLU+Qk9rVX9sD5KW}o_dU@Bs(o96##8NV78*yjGhd^z zRQq}~dWdRYeT2qP?bLl}G}TT%iAGWF3lADewa@QHBdGT2v*=mDx7 zJ&cA??Z|mFlxiQ2L_?_d!AUfjYKMBFK~y_vL-$i{|4cNHYVR~b1E{ulJ?c-jw`!t( zRC_ZP^`+VyCr}@%?HYu7Q*Gx#)Qf7bbwtrrdv!YMNwrtDqaIY-))?JKwXFkCcdBja zgSt^|(-WvG)z;fk7pg5kjXG0p*>u#2YD+7ij#OK+9d)4E;&!NgKr7r>9i5=sx@hz{ z)z&UYpHXei-RM)Qy|@G&r&`fX^a<4pGte=rt;|OsQ*Fgfbd+k(-Ge@&+B0j>5vnb( zhCZa)(pBg%)t3B@KA_rS2_2%^Q%3YY)fUZ02dVai3mu@^f+^@ds?EEC_ET+cI@(9I zIjhmTRC~;g-l3X51HDbPnSZ0bRP#NF-lCdR4eg;?!PDqXs?Dg4c2jNIM)U^N@|&Yw zRLgw{y-u~9=4fX?TlM5(bT8Ew=}`JHw)n;u$&8g=50yU$WR1Y>dR2x!&>{J_c0okZ_e-yG(Z9q1% zP_5q&$V|1qbC8K@ed-}2)q1^x3{;D*2KVX*zGja%P!!efdkE>M*6sU(f2h`VYQf)B z>-<^4UsUUqR&bkY9c=}-sMbEAppIzDz)^=t=G1b~sE%=jat#%aLB>DgA<^2Cb z*N?9Iobw%L9WCuMZKrGvt;n*^;xJD%Z8iRB>}7aL|Ea!uRJ?Azx>}4_DPPr>A~2OD z7oK&?4!k!Omo+^T?yty*Pf1Kki1*6>5jJ>83QMta*>CY4ek#kbVkXDJ4>#Z>1HPym zaJ2Z|WN(ZX`p=34{?Ceh=%EK$Xt})OfA4P=wk0L(zkSADf zxLhz1xJ6wqsNqgajDfcR<1*k)!0Fz&4E7=T8x08jjRt)9!J4BekU*3G@S+lkwD8{e z4)VVUIQMnsiskD`eB?pVti9o=L_8piIx3+-jwO9lLw)TJV(4ps@Tu>w#Zp6;j05V3 zbV)d6osr&71O2O?K>zCJLk}onq2ZuJEI^AoC_yp;l=!%sdq6m^TGW!y+uy+QHuo3D z0Ph2W?xNE0DoIxa^U4CXIm^Vq@i?JDa~mST8Eq179rTdf@07mbt#acp@` zPXNrpqA>%xR0Q&S<&4kwWt{QpF@S}I9QN@5D=LSb_<@`m5N34vwuF#>Tf#T*eH!9M z{^D^!+)t=^19@G9@NAY^@=3c-WNizB?^qxe^@B`o8!kJHz@GV9E&0&h2C~p#-iL&n zH;`jS2)`b!mVDB#8d5Ot7~$p(m#Iczzxqfm`OsZjv*v|EfTICg^g&B)z8e8Ob)Q=D zfjepLvV`gTC;%2UeOI%U6yQMC96>$#q+0TkJLWPrmiPbfi7M3@HX3^9Pv{e1=f8n_ ztGlb~Bi9JnrO$IZ9BUl+**~&RvR$$vo5#A&8V$SX3Fg1dh30mq_f3TrRVCR@AAhnFCOODVa#>C}hWZ~L;f@{+rKad2R4q)1*+?kJ%fYe8(nw0p2 z^qiEO6p}VwAfR_Kl`-FHhJeExq$aX#LDL0fWd|xy##;GjW128Gkk<-<(I{WQRdcjC zVMCoLPr%6vQfFXMfpUfYQYp&;@~bF+sT^TFNvVqcS8;K^;8 zux_T-geRZ!r%Dy(`AStvHp_rN;0-af!kPF|}H{4~G&&d#iQ_4f6Y7xn5NV`Tv95D`5Y>lk-W( z7jWZ$qHU)w$~xS#0W#uynw~aZHg+}4)1THij>>|+{6FZAe0kqY2)T%g$&#*zWAp5? z1xH#6Ys^qfe#9lE7ZY*u!)}5Ph(+xtFvPM$(+M?Ut@fB&@|ly^TOwp;DMHMeB@|(; zdPpt#%!wOWJHyrj0%lQL3yhuF$IA+~k%C%hHyeBM~iosO_0HXV3H?T8UxW=E{B!ZQT3!ZUo# z7|pdqaJT0)z!df5O#qWFPzj}{rdsl8C$r&WKXkHupcUK6*kvw(bdlGD3SC?Hu#b#l zI~ly8mItt+-cX~a4Lg${El zctj2h3}f7*04#QlQ-Eo>h>+f{ua~t5!%ugYRRV_?q;aT z`afUidBFXm>rYo#=R(Ita``$ZkA8|b-z(oXMu>ZmtKkcKlyNou9L@8=_xejJ0dYD0BJhYw`h?cf z-AR66VfPRDmVRsnLLt&Tw#BsXp=NsPNhc!HO&I1Eh9HO z#O9ql5&F)Z`1G@yvh?lzB_5zJ$CnVo+B_yc{ti>kj++T~$IX1~nN}9NrN6`t*kXUB zmF%&=t|tNQK;BX>?4aWV7X(c!N?efw4%|6PfZJVBOFr-n7i-}b{t_nui=DSA7FKuW z31?en;or71pLg1)LA;KL@g`@a(_y2v5@c&#MvyK4d6u`czr+r_VozVG_LX^qlk|wO zTYR9Fd}HTjvhc0^B{qN;8wyb2l^>bF?|QSf1i9H-K60)mf4;fD#0towj@XcewSvqZ zu_#%;Wp&^F%7r_K6^r3Gg;N6MKwA;U(^ z2z;YveE6x`Sa|p?F#&u;eoIngViQtnRI7n9)oW13R4+4@1%{#72*42;n$;(BiDBz2 zQ|tQid;@1_o=*YqFht5b!sa6r_uKf~r^oood?9r>jx+#RW zZVI0>bw`j>Lx~em5Hnh_p_B`XMS>N@92asK0c#@XEQu49<}B;*79WXrcXtjnx5EgLPZ z%x{|e!yR}Nj8}|4qeCAXbv0^6ltZ`d|5s!nI5n+&?zjv)Uspnw;UdInUHRnC@akov zyXar#ldZ|CE;ura)(WhXgwon2!sP?(5)`dTF!}HQuU{t~wwo7eg{8?UlL_?) z1I-bZg~ZkrJgbew(UbCd$CmS75~HU?R}~2Fq9;X9 z=G4F}S|q$CC8Ua;5It=SKNnaiEO}jV5VgC@GoA$k9##t%fJF0!9o$n|1wTx3gXW3; zXyJeD=ZfxXfp8t%)(lJbs=E7ip5E^Ht`A*q=V(Wf{j9y2E!Vo&TEQ~LTxj~y)XbP` z*k>^6M@OyG-GaXy?hhp5m$ZP$M>!^JgdGQQ>?1fKI8oWFNGxNoV$EAj=)>R8U(y_i z`v~4!W>bRWr;!*<{4{=y=EbcnC`;Bd|J_6WkbOS0bj2U5TQqtbIHAOPT;~Ic6u`5jSj)C+v@S)spWUt26=9 zHvW>vz+R5`=7eR}W`ojD|HB&y^urtY&?_~mQmy?ZjR3kFkHGvJ&@iGC)`^YOlF$6S z=51F7V$4Y9+hkjO*=iI?xQXinp zF<+nOCc)uSLOe#z080o(PcNA?QlTM=KjHqs!QESzd{ClqUX?dO&`^ z;2*_6=$5dK{8BCX{;~8smbJaVq%N?=MT9jtdP#ss*wm5_{`4vq9LB#o04{p`Q^G94 zzv;sj#~5CQV=O@|GmId$fm!qqjl#@CQi*|weWaFrLoa@ah3@JvsRhvG_y&5|5k!Fw zy9OiJL))k&AOESIEIwpy)&%?rWo;6CHDpA12QODkKKG(OS#IcT|odSb|sho7nRdX3QcdW}y%_bfw? z_y6@yo#A2q5Bhx1)1I2{9qs|H3$AG{n{&0ZjpKl0r2R*Gfj!E$z*fatXl-kG&oa#X zg*nCa7rcE}&-j`#+Hh3wj4Fz1r#qsHQ9}cPNND-QgtVh>UJS$~vs=sS)f7nWmva`; zq4J3d-Lay?)R-i>p7+ZqICJNEV)9br$aRAUMQm6ywgZofPs#Dd#bm|HEju8%WwBWq z`Q*BJ^q#AJt&1vY=I9OapE2w#7VQ%M8H4Aa=yid=QHtxxbq3EI z(a!RD@R~Q8vWG7j$9+xwh>+%mbVPYz-66iNK!V__0+St-FUhW4&~|~phrx-)=oNvD z!$W;YqESrM!(zDy7x6aOrYaNrBnV*%ClR*C=J|ixho;`2dsza-3tzo4D zGgog`*pX4LNcMDfHWqk03~dzXhuW19z7Kl?+5aD|^9+Xf|1P@jbxMwp9M$dPY^$u_ zS?gP-n)jOZras1}4c{7?>+_-xMA>!2)ir*&(hqT*UJ;1n++jgNA|UgWqoMPz@FO96 zGzt0f=&&GSqM#}CIAdjfbl9$O6SvmT6W9V6%7VW&j| zJHNSF^6_8k&f(}UZ9^Ucq>(f&3Iic`NW%Vv&3*UQX3!^eKnHeBcc5=J(^IbNAsySU1F(W zzTFzAMbEeKI$rT*nsAxAo*<{L=Ob?{WRbzpts-D(j4Tf%H2gqlA8nzQeCiDgSZYWk z_5!u&G-6Dxxx+g}NnuDSBZXo8XciZyBP{_}^mGK{YQjmxwn+!nl5gXG{lh@Z>;Edc zi}L+{D_uXix;Ym)PCLBzG}}(=@7C@XpLxI8V0yr~*l@z&(GQPW4uAFk!9RYucSe5x zvK;T7(M-DHAt50)2KuUU;b36V_R>A%o4j-n|C@X^lldlo$VZpoy%d#?9!%@a%}Vvg zzWOi~&W|&5-Q+}Y_& zI>TZ^6a72-5uWEgb=_OtZC(3Z1D&5b$2op>Ots&(OLn8}DO+RfPHQjAaZ9YZ)cl0G zrs-u>`F|e?~6@C|Q@(<7qME~^+E?S|I`gTr0 z>YJt#(wXIf<6EHvhn$n9_GG!XvqA?Bxi;z_a(&+j$b8cpGT_js{(2_`q?}S? zDhEh|gZ=0W0p~12Y7G;nM<;wH2(+^k#qu1VmFC_tz>Yo_aD`|{yMsdG=rf^{Tcyn@ zVS?J|Q=tP7(6s!iarwhQ=_z1J1033iQXD^Df(fe3Bru!J2tWb zB@$jlhe`hb5S?eBd$H@3tD!T`vESjaKV;iry=CodS!6zGu5ZdS?lSyk=&pY}>I2CC zA9AMz0Qpfr`H@NS8%fF{KD7Un2*`!^)si0x`Dqao3Gu^5lKkSN_>ClmK4cUj(C3xs z+Rm5pT-znY!h`AM$0s9Z`p~h6(4R|COTOuUoW#<@Mp6pUi{D66OwWvH1o!N4wd7-8 z)Le528%fE4Eq)_O#SS+v67bW?4Vb6PxB>GAO~w*zBqc!u#BU@i4bY6P1pKg)rg6B8 zG>r?&3!Wo^}d;W z>T@kwYPjwz7N|vC_Z37jDiyywRhXj`96#MP@1pDpz zeC)IJSnS6BlF5KQKzJSi2^A8=w|-GeKI%6$Syb3odIV5KZQfDOkmGV{G>L%jX`+^V z;4>B$7zT|=04#pc2nt&g*4;=g`OK$FSY{YB9tLLdgGNa3lhE$Es+MI?YjP@Jn{*;j zi`pjDx<;VyLAZ**zTQzS`Ov4Xu%?Es^9cYgYU`Xr2LiE#^0i#G@PO4*f1j<3)tdkqzX3u5e#_r zww(lg+fF|C2@N>>c0UB*;(xmp@X(&P^)%t$dYaGu`E!iH$@;&)&J*o^9QOR9oc$cn z*}u0pw`E!1vbrpz%tfYOP3?_7!-s|{`YBO6;Qs&qq3eHt8-J<%oTR8hC^0u3r=P*L zA#9?GEMil^Or)>g0LF)7N^g0SNgGE+0A%UPF{+i;nf+i;m{?$!TvXSrdzH50f+O}8jF zGuC#Kfis4qg;Rk*C<9hg_zLvuMg%oKA0 zTm0|0f*m?m|9(H={{4PF_wSknV({vmhW82dLL>)X&1vw&IDI87JGB)}b@y{cIFY8e*(^(adV2Ue#7 zt@s10N;p0^hlN=Bm;P$W_l~OvS#~(EnhEUU53DNeVKQL|_Rj~^l8^t(J{BJitY!dy zf$$)vf`7++8Ula0gIe+%apifo5ip@jhen8+Pz8ItHz+HIAYW1tUyal373oN=Sv8pFPPW;79_kQrR7pi~<@K(&;pzHuR%_bYI%A z;591xOF%ZWwmQvsL$?Ja7t;E|uM5#Fp&gF|9$}_{N`-bjCBVtdwo!=y|75I*m#W$| zHYyfsOEOcGZTY8ATPibB)|NK~q)$^@DiyM84)ll6ucy?g?S3}|B)f(*Ql00c-v#(e z@bD@7%5|an;dhu@qu+$)hu?WtjIIgI4=-yzi+&X_ga?1s;F&18Dm3F%X>+(aB>F{Y z3bRskXvQYG0#n8o|7NDE(6JJ4Ed>THdACD~5;|7m3hB6oYt#uivqlFlvNMAI5jr}` zb1(J>=Wn4Y`HEwOB-5gwBjL}XX|U+B04EI@Hkbrf^pnt(e8s*%5GE!6lF(T-?jNcr z;of2JKN5-YF>1j-nK`Dp5;rG-XZAiA*%b4}0_SE0&^S`=Q`)vpw8=n=U_1NO--A)RNC# z;~|#2wZBw;!%|d;Jd`^oh29oZ)RJ7a1|^@lx+aIZmA|wKFpIi|HH4YHA+)GDdG{Vl zK616HteL?*Do4^i0>AtL_h{CVxJR>=eD126EvvTv(n`QBYMVa9)FcEz6Hb~eAk%9~m4j{efSfLl~FJjB{@30XNQi79dL6HiUv zU@AdxFqMy9=@}Ls^1vzpx~L?S5Oll*r_lAtP31-P_&1fWskn%RZs9NW0Q7@`won-8 z%-mRSc5ZCIKWcwVj9mL$zLD=rVtHY(b^~t&2J1u^rW4}5Q!-+yjcY6;%r%zrnJbKE znVa}aUBE2rzzbvJcrUeYwN8Y!S|>iMX9&v*_H{Hua@`^AiX<6`2HX|7ro#lls}u(0!Qme%VpwF9lFtLYfp7|0aOOUcTm{#$7cv2Ud{ zeET}~u*8l1r8XcImAnYk&&=ehsjXo;nl(M(3U{3&sCS*?quS20sNf1#fv%vUrsd|~ zDRY3f!gxYkVLYGK`biM2MIdcp2Gp7?WCOHr#kTG;Y->Kw(n89x8EC~Pq$$g8b@dy- zb}2@7m0@I)W+nvdDHC9eT2BQVS-X`&yuv|FF%&s|;CqKr0}ekMMgSM}vq8b-m2tqx zc5*9gk)3}l>l(va);D01YyehKlVmMxAi_omHY>TrvdGH6#Bz;(14Av}|94N+4V_`L zp|k$DKH0O%)7t%kdz|Zc*W<35&aKW)j`tm-;Y2{5-D-Q**1)>m+S~G}CB2az@E>ehloclw@X%>$MqEs40y$NX8k3%s8(vWTA4RfeyU7%P^poC9kMV#M3PlN zJ+$KmenS3lq@D-}WQX^Y1aGeFBn?IPxeS;LrYk2|qy_>mkJL6Vp7?(K7?Z!(zq!Hn z?>;1}R7Cc3qQ64IvQGoS3b=pS5r5|1k3R9z4eBvCOao13kG<(raA(4 zE<$Va;_oEaS6jfq#MFnw*m6C!1a#Wqdc64wvB?>5f2UkwO#z)Yq{3VXa^ufdLqIA? z_}aYjxoMel1FJ`(O3em@R87FPb4V-U{A6J3K)O2;UolMy`b$*>Om{-sr-bXJDv>Z| zV2&VrOl7fS3)!-wA#$lwBwEM@x21{#Qe#3sAQK$JBh6g`wnjrL4Fr^>3SxhYXee0n zi0ypZAg<&VkWtK-k%V6*m)JHjz9IKGr`TUtHRLHd1YB;;*p3ZWN_GL6K-R7YKY$Qu7Y z{}=wQ{!;ltN>Qh70zYobgM423wCg_0ka>ZsX*fh{`u zWlB+7bRqbOacQCG!`73~+A#i8pldn|Vgf#J&0(qhN~Nf44nxtsao#ZSLu(NDp*8q+ zZ{L%Jhpm|w0559mD+C_rcfkllSO+TxA6$mP+r7>*ck-7u2WC-+<3gBYGSjm|on?@l zv|*5&Z|}C6=MbTrHUsvEb<-GcrZ?Ri27jQEZ!xfpe2X@nSkps_NK?QUl_J6}_u1$n zvGf4FTJkOK{gp)q4{svS!&zia43e<+D^g27bIVgKGnlz?gv`uFG6`zmHfqU7ZgGf3 z?%*$N1jq@3_WU(w4vmKr;@+8R$tQ2Vnk9!VsD?l;Y6~hnIf>8_+~|MQl8@bN9*Yfr z-5^qa&Bpl%Yfoha?^(u8J54iK=H~v=`oJveJu#>s*RD@UL@OQ%{q~1V0rufmYN{ z1!H3plVak+1p8icuS?Or{Ci#2)YarN!B0gEz!o*h55ZQW%Y?a|V(NBfn7a1+tYbii zMRi~nm0=N{S&dN>@HSJ_lJC*A*g;NS|5wpn)Oq^4pLTuYs^gsG*lNFK?_|rj?y~AF zea&-CpO~r|V+}hEQTm}#&%s~)fAEjLrN6Wfd>&Ev=h8KpeE2CRBQqr~@Y^$$To7I~ zwHyDl3|qze6AX{?JCdS?M=dafeF&dndKJERQd!xW9dPKx2l#2tj-7jSYVNO}WXCC+qYhf79?*nF0!+EfU<)rZ79+-5T zfF~X2gAe$U1&5#f?f@?8CqD!{q!T8NA=rsy_}Kk5M;^NPOS=JfnxLf%#a1sw$Vi7B z<%XSfc}d*GSUm%zBvpXXS5=$~DHUet6e z#P-_$8FPX#$DH6Z_nyNtclVce24+z&uY@uuOv{1CU{m5kjXpV*G+=TnzX828_q%oT zmv({%h`Kf^OatI?wUneV8z7Tz68=dy`TWtN*be{$WJll^KR_xSHp~F|@Z$vh;m7&l zJv8xEh{ksS@Q6j@v(s`iL!D-Va)a^&{te1&?mNL69ga=32X;}%CPJJhJB?-+k0)=q z7mc6Iw{~~UZ$G&Cy^(bD?1c3Aq^y+qP>YYdwbRX%)!T(InKNOIYM8_w5j{*Hj!0AEv{|6@x{@pa&JJtxn z#3WqnKmoa4LA9zM8rL^KK=S?_>I<~7zktN6pgM_4@}>I;xNnM9r}X+T8_iNP0cnZs z9uK=k9O(ll0+Lv%O>uWrK4HLX`c5%Hysdn5xoMSboK5N@v=hoz(Xj@8Dx}^5lH0UR zQ~SJJTQ31_sjW@GQykp!%>K2K5Ln9tiSD_xHv{#K)NL>V6vK3<8oN!SFsk4A9 zufkLv8Xu543GFtDiM8FPqtIELT4m6hTjl{$%%nDX& z7m2Q_u05r;LVqt67gAP@QkzKlYw&tcY8{C$875^~Y9-*{M@UBrN_LjKWgQG}9g~@v zpOuo6&>HSV%x;}9Eha4!hO^dfTXkqPtu_1r=Otvpqj9m*>3<5XG&oIJY8eTyRTGS* z7LjnI;M8ELxxD^AXV|CnT=!h?ob(*_?D1^%yx>{lneEB(Bzner26?)BT6yYuDte6W zo9;{Q)9$10cih|EYu(G;bKTS2Q`{5X!`$uM4c%4UR#&O(itDWFxa&RFPS*z43fDpx za;3W_yGFSBx;na=x@x$b&cB`4oaZ6BaLBpaxy4!Ne9FGVzRv!veZGB$J=H$RKHT2h z-rnBWUd?W|-L_q|owI#rJ80Ww+hkj5TV(UuGHtQ8QMUfJ&bH>ZS~j;$XT5H{U_EI) zY~5qsYJI`F#5&uWV@*iTh>~ZTjpA(S*BPf zT83GoE$u7~EmbX6bE)}?`KIy_EK|H`jA@{$tEr`_j;Vr4Z@gi=Xgp;+V%%%oW?XGtYMf)t zGbS6y8;2Ns7~2@@8!H>lhGN5I!x?x@VV`rBGs_w89OE45?CNaktmCZU)H`lCE;>#* zjyU!@wmDWimOAD*@*K&I@s1&m9*#DS`i{yDv%T1U*?z`;%)ZYZZP;O0XL!~yAL2Nv zhDnCuhTewuhQ@|!2D|>Y{;K|*{xkhS{Vx3`{Yw2Jy-%O1kJXRT_t$sUH`mvKmm8Ho zE`x<6Ex(Y{Tl#`(S$Wb4s%8EteNMHEdD3T8ORph)O10EI(s8Oi+Cch*YAKtgV^mAN zSNfQ0iF>4@R7+?heMGgm1JV(y#g36aq}t?d(qXDSVv#XLp+9HVGTahVEpxU!vN#m*ZOf_j7)t0>|jiuVsuF^wP zTe4dkL$$?2q|sD+(kYFi+7q*-kyKl-OBzA7dGARNQf+RuG@NR4T1XF2ZT2>47}flp zrJ+=tc|aOMHD4`hFxAioX%N+Bd?(#cwdwKFK&s_mmIhEQFInnOwVWTNepJh@F7>6_ z)NWEAs%0FKdQ&ZZh}4T}smG*fsy*6Q>PfYf6;cnXB^{UUqgvt^sXNu;*Gk=}7S~1U zO0}31QWvUCPL(=SZPHDt6V)DmTM@x_D~!lV{8|0RnQ*Gb|sTtJ<=%uDq>sKT- zp<3TIQe&$1&XgKaE&3m+A=P@uOAV-Y-z}*=)w)a4Jyh%FlIl^d%WA1E)jGG6>QJrY z5vexSI#iWvQSIJBsV3FhRh4Q`t<4mvI@Ma0NY$w3T_oL2wU&2FRjJl|gH$D;z0l{T z^g7jg?Ui;?ExL>J8r6DCmv&IC`$_3ls&#un+D^4Do1|B$*146mjcOg=mR_b>htbkj zs@?mg^b*zDJt%FVTAMx6W~#NiByFOax3092YRwNw8>rUgU1>el8aI^IQLW)d>0eZ9 z&{kSYwR>KY)=;fpb7?iz>MWC9q*|@p(hF3pnI{!dt$MLkNVRIw(kiM|-7l@AT9s(& zd8$>~A+4ZV#Rk%IRI4ywdX{SL@1$n}T2Zr>Qe~<&Ss+!STBDItMXEKJD&0jjXkP`Y z)&5rUP_4!?$xXFtog^34s_v4URIAcSa!{?(8p%$zyUxL>X?31lRAIbirJDPkWTBdC zykw@D;|Iw^HTyl1k!n^+GEmLpfP2{kHJIQT3aS|{OFF9QbJ0Iki_)RL16tufi_u?H z`@1^2O|{#r(JiXoYK%&$R#J#cs8(DR6;thIA^MYQf7C@c1KJDyo|bk6w8G!-M}JW5 zw*%+~)vn!-ey7^i1L!){e(8^XquS30(KV`F?tp%!+NF-@D%CEgpCv+U4KhXQ-Veu%XVNf3e_~Hk3oV11W z8|d%QO!E4B(MU}A?D~g$EY6j(=@g1@CjPLli9{nWC4Fk$R z;1)li1aWKqWV&(-$n-L90U0%rWrw4<1AtxpQC!TfX8uu&=PPGL^2<0YGEy@+gbQx^ z1GT6NZh|~TrPkUzFPZpCUNYZT9{irQH@qR#56DHmArwSTRGfKCU~_&{OFs1QFIZ?e z57if-#h-`5PNG0-t({$+fM-|dgFo;o18%qXh5Y{tCihl%M|}m?A=hZ{vxFa$m7z~6q_6OC>h12WC5A7YF%>5vD_%RO-TaMnS$%_ z=A|U$%atWY{@8}l^igF(pBHl6SDF-wdc&lxJ}fk=NNH~%ZFQp1v{kjXuxYCkgyuO0 zst%L3I$mfhl~Qx?xlU=EfU$@ERt0LskI;v+o} z2}cT!)kwo&)_0fYpqIe;o;))mlQ4O@5+~q{nL0O8PW7nMuvh^jLQqw-T`>aNr6jPc z?V2pGT}oB7U5`X!%n1{alZFatB^}T4nk*1XlZFUA`b8^Kmw(b=p`#3`Fc7|y2IV9O z9cOTTH1rf`WyFtK3piD(_IP!H2PgOv)U{Uv9PJk1IU!ZXXXK}+X2itH186+t|3~dJ z&C+>FJvTg8J(oP^J!jw?z;VwJ&q2>Sp52}ua2{ZTXSHXgXSwGo&wMx+fINAgOwSZg zyk`=e4;bMY;_2^+_H^~MhjRi=J@q}cJXJjvJa#xQ@VC3zecgSl-EOzlt#{pa-E>`ZU3Oi7a|WkepSg}g%wnHw51cpH=Gx?1>ne0T>skWm4(7Og zu4%3;SE?%!&L50-jdBfh4RrN(b%%2ZZCuS=4PA9y)m#-_PM6s+!;#}ihwS=T$3({% z$8g6WM_%?5ii>>*w5Ne**~)%wI8zYv+uF* zv~RO-vahul!a0T|_J#I2cAtHkJqyk=B-$t2$J$quE!K5#PGW_1sdbTcu634m2Ar2jwj%TAsBm zu`IOAvH0M8MV2Mil4zN18E+W{=PU+VdRw|%I$GLTn!|aEI+kjdiWaBEY|+8FiyP*v z=1b=D<}>D#aQ@f&!}&%Wv*(jV78l$a89Gxblr5tbkTIqbQ;cU95Wp@y=U5M+GW}f z=Qh@vUNEgNEj2AN%{9$(>71p`8_uf``8w}B<2>m+?mXf==zIsxr|f_iFgG|?J6AfF zJD+mScg}VqXPz_DIR(yZOmdEOj&Kff_IF0ZxsCSDR?eo*`p#O;s&Ib8?le07b`(3V zJFdVvj&qLFjuVb!@Uq5xaGqnAW4mLEW1Zs##|k*tvB)vkG0Q#6G{cl*N;f5&Voej_ zEXi=wAX8sc4^wATJ2+F)*i_F{!&KSiHd*0p$!+6J<2B=D;|1ecIAije@hIHFvCp{2 zxD(ErY%;Dj78;*5E-@~IGbcXdG-H-A)tG3U3};V98HX7M8habN8#}@ol;*~U#yZAo z#)?L#(QGp4^uA}Ydt)Q$FQ7@r60>#SkA=Khoyui!mU@30THs8HZ&omN8gP#_|y?Ct>+8mJ_j@faQ2B$6+}Z z%PLq_#SQVX zgXP~?{)OdjEN@|1ie(9w#aRA{Vieu?EtEWg0= z1eTv;`5BgAgB`mjK zxf#n%SZ>5}1D5NtT!-bquw0Af8Z1|1`68AtU|ED^A(pGKT#4oLSgyeGIV_*W@)<0b zW4R2=rC2_Vk9EastEFZ#h43?v@9EIgbEJtAZ zAeO_id;rT~SPsQ<2$qAf9E9clSPsN;0G9o+?1yDvEc;;D8_Ql;Mq}9%%N|(Xhh=vx zyJ6WC%Pv@U#s6!ESqB41k1)) zHo~$YmJP71kL5jB*2A(cmUXbKjb$w?Yhqag%j#HG!}4w{tIE=czk&~c1t0zjKKvDY z_$&DESMcGl;KN_Rhrfake+3`@3O@W5eE2K)@K^BRui(R9!H2(s4}S$8{t7<)6@2(B z`0!Wo;jiGsU%`jJf)9TMAN~qH{1troEBNqN@ZqoE!(YLNzk&~c1t0zjKKvDY_$&DE zSMcGl;KN_Rhrfake+3`@3O@W5eE2K)@K^BRui(R9!H2(s4}S$8{t7<)6@2(B`0!Wo z;jiGsU%`jJf)9TMAN~qH{1troEBNqN@ZqoE!(YLNzk*Z+f04>qR>HC(mUm%U0ZR{- zZY*6`IsHmS!wXSQ@c3V5!G43QL_V(LY%Jjpbih-p2A4mZeyhU|Edi zpIF|+@((O;VEH?i*RlK!%WGKvise--f5Gw!mOo>88OxuryoBYCSYE{P2P`jO`8}5B zvHT9pb69?heluERSOO5tc`={1D5-Sbl)zAuQj=@*tK6uzU~8{aEh9@?9+7!SZb^_hR`LmV2;# z6U*ILzJcW~EMLcRCzh{axdY2rvD}X3D_CyB@?|WyV)+u5Td>@WHSw32AVx zeRgt+{FX1tk9ggomi#=4*=w0R34bGhX&ONH6Ldp0fhGad0O@N>3F&J~`J{f$OE6&G zRN>}TLc3wiyQ3a~-cgSaJ!>>;UU;D4QGgcpK!X|tQ#WczZUq6|zCbPcz&_0jkdUW2 z1%O56X$AoYLg)nbl}2jGN0wT#HijpHQUF=h6G196j^C;&IfV1&H`S8QTX2Krg+n~a zz$@wykA{~Rm?qtARg$T;mXS;~Lvx4+9%e`aVo?t>sKjdYI51Fbd5+k3%X57DPT#=V z7hE_o0xqo5s!2u!b+eL~zPSY-dD=P_8FDcb09jNnX0U;o@I0a3_^Mj+sq^DmYDkcd z2Wn9X(jnALgrDGUFsUUUJFg9k4dX=|V2d6vG+VlabKN|(~l^+Xx1pgQbU_}kIbz6dJMHMCB$oUl|jr-5|WwobEZQ#$p$=y|9E zQeF!uniMV@91)Z3+X$TPhI!9+WAiR{(7ZJ~51|Giw}q3MS4t%E0iXE_1E2Yd4ZQFO z4ea(j3FH|jqn9xE(MxRZxvG^D z9MYcv+`JCytGJV5Biv~*Q7KT@cdR=qg}yrdNDmBuqz4;*jz}vVc4FfJp4U!H4eySw z@BJ6Pck|E!jC^PT8~NQjG%~nC#sP9jW|YVvGs;2v?)QWF-2Fc5Z<-oj$+18kl2;PG zG%3k-RI2_4VO4*F*s6Z#BN`eUA!7iV*Y_Oz{^hkDB!tEiH{@4;W8Sa+X7kQmMe|no zJQxkUJ-EgyWZvY6ByyeYf9_)3|J-HczBQD_1)CVf(I!;t4HB^U@)(Bx@)#R>Mj;v+ z*8G_O&1=n{2edmqBO)V{*vA*^F#8wl*zD79(Cn2w4>Ewg6<7Q4h5>w2+~*?Z{9I&n zPE%D4fX#S1aPr!WV;xK33St&Sx4YyrJG-{9nWqk*bz9N%APtyXaMdliOns`|aTcp~ z$5}S!8{sr&HP3^QfZ2sNrq_c`&1c(|V%Tj<*|1YwG%N&yQUR9Nav$4)*9}d~z^C4= z^)d0*`fTFK*Jxsh7N-C)ue~ZJ#(rHN=@!}dvLzqi%cRdKQg8kL3feG@Zo96#_E+s_ z*IZW>$kFfPxapYWC}ZDY?`FGh%Y<6-AbE4{DzH*>1#k?Czy3CPTDY&dL)F@)*g z)>qVqh0TTBfL)q_u?DazZFrOcMqjYEf8kY>Z`8t@98O8meYi7}y{a&s!}%dqSMn~? zJNpRJIGiL7)|t1jsT_{-sQU6Q)gv-9;$xCC5~3n9QoPGv;SCPzRH9(=y2Kal5QcL+ zj;M-t|Nrt6k9qlu%0LpLy{3^d)@v72IFz4IbrxWWuXCHHe4a#MG6w_1qmrXeiVskj z#BD}Ydh*SPuW_5CsF?`hkgL;O92^_vR>TZcoM;OoBTGiedVH|IxQTb7Xu^eVI)oxeWF$iPg z4dBBl*fpf8C)sx)jOL(0RY$6Qg)oZ4nk$d)h`&I{j4;5CpNBT(oxYI4;TSp|SCBor zkUq=+yKElg!MkfAP2S18ECmJ&<_1?h9Pd`sXXPU~d`L+*YRgOIu-d_WkzH8|x0gxI zV^R+(ncI-?H_W>%P2x5r`8%l|QX+>{oZs$9ss1qn$NzU}TpgWr9X~j#+B0ll+Mcn# z3TMyt<{_qaa5lS};eGujeO=vaaEDy=uq4>y|4;ej4YZdAHw!PvJpRPX8%m|hj^qx? zD)EKVvfV!LYx_DJ|P#S6!iD z>w6yB0hU)8a-!Oxjvq{X{UfDildrr^lS8_x4aj+g@G!Y=+k^?P-cedM>59uVDJ&qY zK+1OkA#c8XAu$YkrGe72ftRapUVxd`0>FG{UK!Yb&9nHjeEHAid@ld_Kvk3;);wlF z=DX%mBg4)UEBDt^O3POAvV*i$yySUk0%BeXDzyE&y)U1CXazI>BHwKFOFlPSEuBfT zgMk=BWgt}i2_ye38_3W37)bU=8o93Lp#hNjrftdw5?s~iCt?2clh|gmgkDle@&B;9 z8r>RQ3+<2EIM@5G+Rh`+SjRt(*^bKgE%wf~^AP_p3YG2ZSiZ9KG+!}`<|3wrrrO4@ zjDrn-8bpIpKUZHe>~7c_kdi$Y4sqn^l7sq&F?s*jjF|9<)YQ>w2^ld35`IY^oe-N5 z9y2B)DHTq8ghxb0rDP^&gexAGAQmgE4MoQhaS2iGOm~_)(U-d~d{iLu3HFGGyGOgd zSwq5_Gy~jIk>{^O{SM*LDS1Y8*_}zw5;DFIAN!|gb(xkKIhOpO`F#3?85|sg^rYui z<^S3Y6v5yb8xj-oW}lBvNsCr|6JD*ZE|4myYy*vok4Q|6Nsg1Q*jN>U_dX&yC3$R8 zN@hAe(v<}gfX!p15z)~BA7x<$2j4P&D`dB$Z-FQ*=iQYr7gqRyLrhXNDqpl_8TX#z zQ<5d4T*@s}F8@-g-k$sos~e2Rii)k?SW8}EJ7mvD&is(v>m!kfk6vL01OumbiD zXff{}E$B8^Sj78PON@w&N%T70goV6c042^MEa0t6yh!njkO=Q{h?8Sekz*Ued~PcA zi%JOZakC4lCu(mk%;ONoCTfFldCDl*sYzaSVJ?S61FA3YJ4XDU!W_=Msl4yPyBx9( zsIkd@b73~OXNg-H!a#G0K+&&~;k1JU`&E#eVv}ad%3&;N( zXk0y*^msS5|j9>p{HvXZpe)unj5^5@CzS=IBo2mY(CX?zHQJP-H<7Xryc>%kmbn7iudO3POJ{w$gs z;-{5?n{WKo-#vywt5jB6Ht?6K3cmncDOA8dCmRN>yh>@=zzuj9T_xrDY@UQY~bwdmferWL^a}@QzcqXS%>fR+$`( zTPBB%yR#9kVaRWK4siMAH_5oLX#h7NrhImk(z0oHsH%~HF_#IIF*CL}&)moG&)jFj zZx5qY4O8>803VWXiO(sEK}*S5-KFx$>fXAa0>=CQS2V5;&Nm!K;lzKWZL{@(wS{Gx z`GC2&=~d%0xJ9j{exB|Zom(q}?GG!WdF3(F|2?n@YY)2Mz6z5qFK`t$1Q%Ay8j??8 zrR%Es2oi7G0d~P93+J(n@pqx(UvY2+rDdDlHPwU!s%{$!RZGm?mxlP_l*1KSFy3+@BUqV_k8e)5{2Uv;*kFB@n@L-J)yKrXoC%RG>=R~IX{uk4fS zyP8e<>oJ-X5(8TRX~881=1odv4q)OwvTpn2quXD0)5P%7H3wquFCFb@#=N~&C@ovV z7gx}{upVdzyal(oWoVeO9_T607(MfuF@By;!^4cx6yUkf80yqf-_eMy?jK^6cmI&B z@(YV;>RO(MO@O-Ks`TZday7MY-Po-phVE994Simqp}~977@)a(Ph@DXsRVb?cELri zvby9`iIlYu7hiR}LkaM2~oLJ4rV*ci1+59Kz zGWs3}_tXadP=$Lizd9b?6dx1GYI=$de*6)ocyIoH`LO*O-D+L9cDrketB`Y%^99Gp zjuvnW`e55V+eDkqy3ktD@~Neb`Jg!x?thxBlvy@Ul&MH z8heWHrI&ui^OS)+GL`Y{FOWRKJVxj5OcegZb9h1AfWp24N%CV2Psv^UvOo%~v3gRu z-h{n8%~Db&aheHV6v(lqJO+o|UBVuopJK1uhnlB9=V=zSi%HmBAo=2XYfd`lsw{VX zw@wJVcv_>{K_VsK?<|mFRCx?j-Jf?(-of*e$8eS?A!kv08XG?(``eb$!aC&Jo&zD19piz_CCZ0Abcc;uaUX^~zb6+F( z7j$bZYz)DnVfCg~_#_1OIgc&TC1?C$HsR37Q%{?%jZz-y%vqnW$2? z$ek@TF_?JQ5Sn<|Egl}$W09}~Z=$|M34?-D{2_m9|M^q5*o%U1oL zuhOcAe4@^P&OM(7TaR5e5*dZ)lPng~F)A)+;R=`FB;S3w%R6gb-PYWnt7;O-jo~zCjnZ^v3_o zX-jJ$@?YAy##!I7!_nRTvwfspYnx*$Z~X{P0vxtPnID+nF;_C}Fts!uH1;(7WQfuK zuFudLbklXkv~#qj!#)UWtocgQNAe8taN9(~-aj$|K3(CmCp9Vs%6CP{Rqcg8czCA* z`i#iPNK1&!%#g}6{azrYi~M{Bq)Y6K^ZNX5@Ca-8cjV4YOLVKocb$h%DxlkR&}ed; zy60=6!6OuOQb9n^X)%e?r3mTq390J-uk!E#2K4XW>lGfU6oI`aXT-$Cq^Sq|8xN;> zkglU+#&`|-GLMK-KzFf;DG?d!ab6m2@Fa0JteE7?Bz3>PhGf9_Aie4x{)I<*!2nG| zk?>DVJ+2=3($R*i= z8d9v!TQ8j95|5<%Qv2D3A9#O4o*3Hs>uPqlg9RBM6lt11G{z&k)aEsuRl`eKV_?*v6?_p2N(tAu# z%d+y@X@?wy-%?Itj9)^4R` zbC<15b3lu!fj{sb5$I6MG<(;Fyiw#51moGG&&%V%b*)z3i zcnAv(2Y7Cg&j9!!jylZ$-Y}(QE5DSgOinA$!vx?Lcm*c{`15r4Vfwk(l$Je;68q?1 z0cy#{!zc>wiY33@c)%$9oQ9ZrPIIMYvlrh=vqN|&4%oSchXUDyxE?Y1>~EBoJ%D0M z=mEgzG!_OBg3qb^{;EHxv*hZ-v)I*#mlahNmV=mL3_x>>DF$dg&<%=p{dRw)W$V1~ zEn4S|JP)G*KPhCdZGbZsQ@?dyY1#CJPSW(C{HTyBKhPzMv1bfaS~kAx3mPAmVv&F! zf~A;j@BvG)>9X3VpJ#JB*U{X~JP#v)J2PZP11~|Kdl+kcnymS01KA^RsLE8qVsaRa zAOwp^S@S^_lW+WpNASjvY;wD5kpr{*t3V#QSw5Jn8iP;4H^^p9Vc#IT%+{AS9w=Qn z6b4Xmr3?K&v9!k)JG?RNhX5_Vlm*HaOS#Q4>Lj^<%OrLImu03; zC`N2k|z40}zp_kYUv zU*YgH@#J_fiwwb9*ylVA2wLM`U~gHaWgATcRlUJho*eJZks(+M%l!GQh4-w(qu8^K zJ&O8!C_D1Js%>H>jHhaB|G<#D|jtV8ZQps^=M3j+wjvQi#EUdzgza;^NGz1aG%^BIlb$ddzihlXNVDdXp{tlWM9 zThI0jZ2H>o(Da~uO-PlW*Rpb3D#qWI%EqsiO5?+_QUv@EEGuQ@2P`W;lMh6Fc9qQ? zK8EIoWhDac5G*Sd?!1?kTN1J6wj4j__JEWZe>y-*y}&Q z*y}%FW53Xp#s=^E7{CsJ_g&I8c_Rt z+JqJU(I&RSt3E?>SM@v`1>BwZdk1jw6U?|q*72HrbX=t@%?igyGJ%!b@eyLv(jjM6 z_-?hlvRa+b%IbMlSvr_HGJrS)Q-_yWc?o^<-O5E+-76QdO`@_YH~>>eIzWeD>hMC7 zSI~#OLOv3;f_)@vSw)p|6plot0XDZIQEKb(y?{RI4^ptQKS*IKyTZ?uP2>FkN*dh+ zokcrWTgf%cRn588*}-wzk?1hm=h!RQHrQHO&sblzT(_i{bIp^@cGJ72QpRP*iiXvO z+WN2c19g|eHiR|ToYX`pdvb3p=N0itpo+~*mQw$Hrvaj4QWI0g%1Nlm$s@Io^of0R zpmyZokzecIk$Y4`T0%r*qW9DRvhz6T5YS`Hn3$+c`D_KU@fakrW%)b@HFXF#dDu)q zkE-|nfAVY~&mAPlkBodz=9p%l0qd<1tE)!5me>BOYIYfGI@%Rm}~_YZS~mB;@cY zaz}Ux&nIq%QCCeJums7sB5$ z25>+Wa2abdNbGnJ{^F5QuIj~?@hjZpYnFbSec>)&vkcg#3wL;&22ksg-e3#2`K~X0 z`Q^f&e1AB3x22@A3Ab?lzabh|8|NIydB^kiMB65t!P>?0uK8DUHPcAr4x`a9NWWBf zRaaL#A?$Eiam^5Vm(ToXPhC%r_bNwjPD!#MkUxFYUKu+>uFECWuIE!yt;a>mDdMT` z$?@Le$SpDxz^&RmVe+e=DJ|Qb)BPu!yqYJcG>~%(Y!Gt!3y2}Fv{70%Y_}h1*gBq^ zX8@L)qfZU%bEFWL_2n}d`|=q!cGnFwc5P2iDZu9D=<~x)%S`qjb|%!90}Ml)kV&9}?mIwK&%Huf^Hg?%b8;uII@q0o>doGJe`7Zz2J|*b{?a z?8yf2c%KHZ>d7e%;M^h`1RO6gFynf zWka`DSq8j^MFBbl@1b`A;xlL;^|=z5`dkS%b-R~nRl}rL1gJwW=}D_J+B1%Ee;lv0 zZ0xpn8XNMv3IjH`{4Qc4(J7;op?F8Mo4krXmH%)Bv;S~~&EBR2&0gJ;QwZ3(olK(G zV-jPe`al@-^l+tRo0e zGzc{AljX3+PnKhow|GF4gMm0gV<5iZ5ym`rLTTB!%~gs91F?t3K;(S%00TL48*?AI z&E{@)gjO?r%5A_Mf={{39XMwnk~44)<&%NaR8`jvEZZ6y%a*}|Onu)T#VY^yC|l)C z4$&%y54#1(L-1jj$(4`{hW$pqH1`|!rMb%*FQcL1busQw)*VnG? zuC=Z#*E_D)Tp6xd*8o>%S5sF_S9wRyyW8raLA$k{!bwy&Y{G4II@Rr5$$rBl|7;Mf(Z+ ze*0GY8v7#qOzTGLa_civqIIaXr?s`Up0$d#l+|ju}UIvN@q zY8c8I3K_KeyZX!e)A|GYo%;3qZ2fHgWc?_8ync|rtG>CumcF9CnBJ(nue+u@t2?CI zW1nbGvq#(e**n@B+iTd%+6zJT#k;o4w$ru)ww<>1wrtyM+hp4)TfA+Mt*foMt(L8# zt(eVdy>Go{J!?H=-Q#Sj+o)Tvo2Q$q8>dUu4b}D3wbs?sRne8wS+zOZKeQLL$F%#j zTePdS3$!z|NSmsS)b`c3*EZBv*Or0Qaruu!XVOZ>wB%kc+CrqeMzonoxBH<@M7nhX zeM+R8acCovem{pkA<~URw1G(1{z4xU>FRW}o=8_JpmjvLjL=#lT`G<~BGNAl(HbIM ztcyM*(uK`vHIdGDM5~B&ZW~%jq_bAEf=FkEpyfn5y&ru*r0?6IWkfo;11%-e@e3%M zNJn;{B}6*h17#8EyC2YEA{~rJi->gK4q8a0Z!*yWB7OBQdY?%9Yohr?n*A}#B+{%F zD1%6E&qV1&dJCa6B2E7VjU>{vG?YrDsbMIENK7DB+p?qf=J>l zG@M9+8zm5Fd^CzD(%4lfj!2^uQ7n-%TA&yrrBy-EL`toWqKK3{07VihaXE@0((oVA zFd`+qh+ZX9+(a~#NU=rH5F$mdM1zSGRRg_3q=-Fe5RrzpM+1p8v_Bd^q`@aqeFCz6Si+U2NM;huuq;BU?cOrG|hPn}{ z^LEsgNFA@DE=20k9d#yByExQ|NNqkw9f{Ox59&aq7PC=%A~jis+7YSI9n_Xc4a=f7 zL~2kGwI))%Zm1QJYJHDd5~L@IqAH6_wBEl?98l{|$S6RE^N z)QCvM=A(v0Dq0V{M5My+paw)LR14K7lJi?sk4TP2s4kIgD^VRHSzDpnL^7X4wTNWO zK;c9(7D6?Nr2h!HiKMHEY7i-G7kZIMn(C;!Ps)0fjb0#9?n|f|ksfYCRf+VVFRDVM z`yZm`iS%~~RGCQk2BAtsx^os)B+~5>r~;AxG@3SJd zhDcXGL(dZFN*h#~NSDu`XNYuZ6e>leUyGxXM7r1$l_1iEPf&3p{j?VqBhtANs3?(s z9FK|+>4z(*Fp*9VM}>%VYA$jS>0~+NB+{`H$U&qdw~?Jlhh`%ik-j~OtVH^z3bGJs z|4n2j(wFOyiAa0PA|sLZtV0GOeO?dgiL~oWq$ASKUPw!%?H5oOk+!8G4Us;(D*Q{N zEs4S-B5hhJ`J^RZ zmPPZ3^u>5Imq>d`pgBa^Jr%u6q+R9EY$EMggJuzFdn@z~k+yz~-X_v#&CpCDZC;Pw zBGRVLXa1Ya()|5uC6KVB2G?_@N znxIKUT5$-yMx^CKkcUXia?wO0EnSR6B4sy3h)7w7kwB!yozMg#Exd%r6KR15jU&?g zrO;R+y(geCM4G!3jV98Z{%Dj>%39q^xJRUwi-fyGT2V>3L!=KPLFYv(%b!oOGJ9>yzncLW(*X5A=32o!bKuY8z}rtq&I#PE)Z$TP~kk0CLb1l zBGROi!Z{*&<_c$tBwiJMBob;ToFUSL4B-bNjVmLZCeoOA;d`I7WS@xM^GR8wb_%D6 zl+ju^Nu;zT*u@pXmoh!neB zI7p{o7m>PuDC{Isx01pRB6V3RY$sCZ zlEOA3bzCfL_3r=6YinwB0#x$P*4A{r=c)j^`<9NQjuH0z_9^xfwiUMK)&o!x;HG7Y zrM&r5b7#|!rVNw8xWHK5u*uL$e?&h-cQfqsu&$cZnrLMwiCdh>!z1x5J|-eDBVM`; zaAamoW{f*C9j*j)M`tFbf;R_+hosM>gt#@p%js?LmR@W{;a51!D`LFD4`I|lTq^0xl3K0d;uv~YmE$oI6P7en$w_)EEh8Z|AqsMdrGZxEk#QH$s}wzu`l~YB z;OSG)Ihj;{shN@P^vp=FLZ9b6i^jtI858Xuo)RgItTKSai8|#BOH`W2M@`+0 zZ_y=L{WCn~dcO{-tVUFdueAi`BchT#KHGjHB(@?cwFHl;gmj5>08w!sv%abqpQ(5! zlwy1>#Xs*373KRX1Z2#iB0LsbM4!QP-B4k^^E6(+dVjw{IR9VNxOzF4IsS6AvCpxc zx7D!V#%spf1_4g_yL2yW7lvI9tEmyyd;F)8poV`=9iFKk)Q4U26TqNx zfZK)(A1$%vQ}}4Os^T+bUeyL%ZmD_xxbD$0k?|=hBfK*R=C-y{T6T&`!ZtcZ1=4_O z0XMfapa5>k9pi&GpTp4Rb8P7NRWvkYU4;WQw|v6j(25TU6Pq%WmQ5a)>PKEPq~t13 z6ecznQd%~7Y$uu=QuN$F&MieRKe-`b4$DrP&RQBNqUCJyVA1tJxq0O2lQPnr23|vO&B=$C8cG9znVZB3Y-|I z3gFyM3ku{$te%G+^W7)xU_Q;qy8!1`u?YhjoeRlnhVY*mIGvN zXA>3YqvGPktT(fimd)C?7_DBghO#`ZL1CpFr5N*%#!Ab^?fs`8?sGhGeaj)@ZpD~4 zrYS8Ox0i*&#rywW8doRhe8)9MEBk!g6BZdfd&}{6gz2Zx}2UtmyRaoIoR8n7`2-HvhyOw86mQybbVkTbu_dKQ<~Uki8+kFk?x>vTSxywULAC0$Kw*w_B(J z+1*hv#{^hTgNj)54Jxwf(Yv(fVSZ@^^r4$yq{?T$ceP$O3|+4q8(Nq_L&Lk;5}-r( zu12ILrw3}h*7q2`*7t1q3EgRUcvo8heCWPN5%4uib_d}vHxu)ho5|)MUybI6$-O!7 zbDP`~Q=%dgW5T5{Sz<(TTqb1Fkq=T?GiEMpW;2g%Of!R(H{)sLG;>sDT3SqUR00KE zCILg2Nnk^d=}1F^qML?F(NQT-)+LQ*E{$(jTT(io+to(*qnR6ca+&~h9IrjUO3@0l zTe_Z`*vK<2u)3dV!B+REE;Kp>QyK$0w_r+ebVwETO@<{;VeXQr*xVWa(%fL%jY4MI zDUgnm9Fv?ulwAVfVYj42K6luq|4Ku@=*eja(7i%qC(+cqSZqF4aWfT8>CzB zdJ1(8$;+7@lN=qFmJqF)7dr8%=pQ)FK;J0p$m10a+OwqN4m{4B1av3+BT@U1SgpS& z5w#1+uNlM#h}!ZLwySu|P^*wwlfSPEwG4?h1@Tg$ z7Cc^7dLK^vmr!#azb4(A$}@zT@g5xQ(?Lx$4B(Y1;G*)X!3BC_P!qpZcY!SVf_IAj zD5x>_-;nlzphgJ>@L_P(D)wEVhLHyFKJe*DPS$^kM;B!E>RsV9h%>;Bzko+Ux=?od zs6OZ8dSs7|>hU-OKn=-%ca7@u$i}BSR1(us9UgD5e@ApmIaD5kEqigey3f_ZIm2<- zQQY3wHrsm6TGsNad6nsRQ$yo4!%0JVeS+>YZLYRM*bMlq|MUNNz!x)wr!R)ARHUGZ z5*Z{u+SsDl7ZY2Q?Tc9wNBLqr;L9Hj*xY>id0>MdDUP5=%LgN(^Enui<)qOeVe%C~ z=aw+(hmJ+c$sAP!D?F+OTj7hw($sLmU=UDqJ7Ex51V{}DhA>9^N*^DRbDBKJG8&jva#pCNt*}+d-?-* z2*UMVMJqE2e7Z60;FC(rhJLRX4Gn?JegMraVyxCRmWcm+(7%{@(7$ZvdBtgFNb`Fc zn7Ji=5@z4=H;g$@qqJAKuV;30L?;Y$fVCen=8~WYTG&Ib2eE>QH^PLPG z^p-R^ zBwfC_swuGDan0uIh zF{K#)g*y1p7?v5r^?UT)br*E8+MC*mTC?q(Ey{WW@&a7W3Sn=BmDha8#W65S_Am1F z#LMMf{EZo<@Qp_Lx|Jej$$X=cN@u~Mkx6{xIda#r0r8wz9^PZ}n#=wA;yE!Pv7&%@ zPBh@ti0gArGQo$@?X(c_agl2qhm+lJq{<#e8s`um;j%nB^o?>bkMc!+onldPRiamTq$>sQ z&o{5x@>J4uV;QRjjx#UoPzSF6kgX_m5?nHh$pBoIl z3@bN_6eQ%UPGtoGNlDT>KZ371dM>;C$NZmq59gJ9OVd*v0Y|V!K#2&!$`~9&qT61n3Yr zbQS2l9lFzh!6TUd3ws2crqd$;FIQ@4yj;E!OQTRP_^pTQmg*5CXTT zJOF=B64v_EFr{T{f8#=0``{K$2KW%TMSbwz#HaYg5Wnfh4qlWbX64-aTaD4XR(>rrO?bUvm^j>=w=rG4F-l5 z+)B%aUptD12P=;csg(!WreN;z@^mvkn$7>wXqq3Yn8X2p2&$OK2IIHc!R%w@3NmB! zsUWjPHN!v^lUQI6K@}5)-QW9;=|?9jEnD*+dT7nV{1OB7p_^Y6A3lc7kP8lE*L?vcPBg2`PSmB7r&1C*9+ z+c^xlL-2O`MMyC8@E?_yt?Xrg)6h`p_Emu9R(hJaJN$wkWZ9DNA_h-*kqy4|I1LWd z%1{6g!L;HBt~Qmpi5Na^A{#z?2?g)n|Ci8YX71)dMQGqYzlT zvXeN7f>*D@)T`IAslQQCgMxMZ6^wnKK3iDT1f#BM!bbh-k)MLK{1q&_X@e+u#UV_+ z;!r-+s*<~IPi`1cb33siA6t{F!n$MO&N-i+mk+_j%ZIRu{}WH^Ioy-00b*_|Hb3IX z%%~C6M7%5)GcU_!Gw)L!p@OnOA~16+8>BExUt+J0$y~g2F$P|`m<{};s(u?d_YeSc zn~PPzSj7Z6yCFu-ZpcR7+m^NqIH@53GPjc&3bHpGt}^2+*{hV5k5}mn|Bc6lP?)iT z>mHR5Gurp+E$)O>ytorv#d}nh2;s2QcwpvsSju0;-erXfd*LOFz3>tn`}0<`Wx#%E z9AIRP)m!+UeDvtOe2yONjG~EQ`#&0pxqnP#Vm~d<-HEk4cPCrRJ5)|C(DJBI zXjxursI)vs-iOS|XCJa%b)XfroEZu&%fxBow{He4U3`(49b*DCJi{llcwGw_!(<_zf!9RvW#>BX3z*Kq?_Iyh%nL z9@CUxU%qc8n#kiVR(exyOp(ar-BNXhhvnT;BE%zKS?NsKU3ohac>Y{UN6I!1P2llW z@gEko0Yl??q?ZPCNNt_aIGz@%+Vr5YJYQ?|b_I>$X(#?04K$kP$kbZ|G>YfQ{1^8q zlW!(&p38ES;jE%5M1QS$r0}a2CFH~EPS1$Q$do3wH+j@)!`*tPYwwgcokz|w>4I7? zNF$mSVSu0-mt_#V?%n}SCzqDSYtX{ea=W`+*IAQFTWh#P7-gJU5rC3Lb7=1ni8lKIVh*nE7BloB8JtD0h^n zo+tNNVCI$tq+$-P>;rO6#esZsDlX7@G#-ebmj-Zd2?`k8w;jj2{U%ds**ZSIn$~d* zPwq2-$}QSKqe9uT5i#T~{7Nnj_fc5$Wk_@ZD3fx_3`ytNXO7vR5Nd zZV>?ImUXXExA%jd788{M*XWFON2So0qU|b&>35Z5(|iOq$(;2@1+Z{L-Ss$qCA*(>(@%lraqxM zK?R?7Cs1?yw5xn2${rkpe%4HB*}%tCpY|6$xefs4b}gX_SdKVh&duwUmd$%qmFNp* zVdrTUDqhuI4byJwth8+EBirbC1GX_XpysxX$%C4>&@l8yIX_@yKKTKMRoj@#o?I)y zbGr!=!^@614El+za<$B zK>WY0#^rYIbar=~a=c={ZXanmV@a}vndg~nn|7Oe8h`kuPqbg%15 zYu9Sq+O@WKA^yMJ+QYRt>|j`g=AK6QFZl*|6rIB#V8z)H>;sH8@^I9v`b~_8j7gLn zt)K9Stf=}@4#uGk+|?;{<%ZP^tbV~kf!!`TcOxM-xw7(rmJh-w!8sC96{EYc0PYPU=gk^d@!o5s$bs{^6v~ zyz^EpS$wSF-JLH}Q5xNcJnG2>GfRITEt<+V?TE|--qq%M9RJ^}admYraNKm%vrn;oZwt2~%K=Ln zbDU`-RR8a0SfszBudkb|J*F)d7NgnxU)tmI_{$#f8rB0(3pcMJR+8*QPUF~O*ZxvkHvPS>w7S8eTodTIIh0jXEC#$P7rnSToeg@o z0}Tpx;pT4_ek*GXe5HcYvVrfkp@HGms{z2AUp@czIVQa<*Jiz(Pi@xQ^=M*9)OZny zIVWlatnxAPrQ%AmTp=1MgjpPr24> zP;*RpRAK^TySpQjqtj9nqQi$rjEV@4h>A+dOwLg15)fCs^y_4oo2|5Y|2mh)R5;N* z+RvgoKD|XfCbBZoDBgqYvd>}Wvd=M@k6%zZJ0Rh&128{j!rx;udnl^pT~BUXz<$btQIDzg6zOzL9W{4}`Ix)Jd?xpaK7Z22Qs0x?2DqQ{g5due zxBrY%bTK9`%BVNzolzX`(d1y}twUz!LBj-?x-h;WIJ@vwrrwX=bJO&Ycisxqj!NkKa_CDr@G+Z3@_#PgkM$G4+hG zy@x_Zr=&$wi9eV;Y?RV6M{uHw%7FrA-XvsZ9+8}qJT@sMGu4O_e%O=*0 zpow8BX$ZtmIhE9h4FnV{gEU%q`sjq%jPRH-5lN|V;5{7g`(+)gPgnf&G6w$VWhU^l zf1CILzZ5!P@2XJQJ1qHIuGRW?KDAmOh10;WI%xpFPq_$xTn*>B2w!q97pwbTE?eEX z&(rj<|E~}9ocI5VeaMraPvduunE9@e&74DD6=8+leEG27HM&*0CfYBxgIx1m)tnog z?Hp$u$qudkO}opMWvgr5X>DgYW*KC@Y|b$2OmCV>8`m0J7``*a>mTSR>5GK@9wvra zHOsuNfhSL94nFrkc}8*Y{~y_@)9yfY?8!5VAE%$7D`9l>$rEPs>om|ygpNFU8ry%Z zH!w+bm|x1d`~rYVy&ZkZFWHH76nKpDf9)xfC(j#wOe0adY|x=6&(wa*4!!T5|8@v{ z$Nkl#Gqn#sdD?V-gT$F}-Z$afC$Ag#c%Aq=tk3~|Gm4z>N1Pt$8-Bl-+!^HnMPKuK z59Hqb-h;26d>(tuUoSP-dI#<2KTwss5dDX{nff{U(7q?XBm6N{EB8oQ>zCYr&frUm zy-%KY{Fr0)_Dj3P&=>q>aQRgUI)m@w-)#_A6#D$h&p14$f)ytc+RgpdRJ(uBt|u=t z_n2eL({Y1#a{oDlxm?f=e&5m_JmZpdB*$|-T96qDA&Gb3} z1Gny@v`p|5FK(p4!8Jb^z&VG{C~*J%B8F~xS!vnu-9M(`8+&qJ0r;o9;N)>_hFY_b zxG~I|=&b?q)Z94?{P6kFDm4s#;T!WZDm)pEAkxv7qU6?(F(kFm3%SY}z*ep;ZjQ zgqMN#DT4`*MH`sTon03v%tOm&HmGX7L3VUsV1CN%==_+e?C9)T=do^Uoo8|$|NR+S zx3KEy1Du>!9p3nY{}ddKi_v9=w_@`?RAqC6<@V-pxpX`PYt=2M7`gLFF)DJF)-I$+ z_X66dOpksHD`2EYXTNwF58=hrOhuolJB3Dvm#!zEbAIUpV>6hwdU>T~G9N#sI`0T+ ztv!I5b6TsK+4sS#wh|*(TggN|(c~ztW=L`A4#=ESTx4XmpB3X)l{0gy=98IYRb?x} zDzqD5b6$nY*ui{W82a(Om$tE#k}z-fgp!2Fb_ z74n-&u#?ee(iK->J=?Hup`jCT~ZFSn*yO_oKLO6IlZMy4-J{f$?Rqo4xdyM}7|&-9&iXLYICNA||H zgSJTPL)UzlTU#@1cUX7L&ziKneFKUI<;m-fPS==gCWqB(-5$!mOYasvFL z>ET{gj&w`6INo}4?^m9^$Y(RuD>8JPUnEL)CHTFl=<1Vufb$!h+#~S-UnzLgSI)R7 zefjR#K))%kw{$mWV#v8qlRDcX2=F@RW2v^eg|a6mR-3 zPwq{B+))MfreEY2qf~xAsb8}BLO*l2PbC@I`ysf%ZwiwKs5tP?bN>m0I-$`|+;$JFdvIl+p67-q#9#$DpiZB#ZIB^~Ax9zUP;4EOn=pvp&V)=aQGX zQa>uEE;?DzY1yhYYOg_@fUTdw!cTd$ck;g}TbsiyNxfhR$q5+=5x8vpO%8gbyMj-S z_oxQ?1IPd8de8sA>p1DCY)`lCw3)3hTRt#fH#af8Vf@}$-7rD_t-hQtLHnsz6V^pD zH}5@u0sR*b+_I4g&XlLTd?l~XFWJD$-+gM2i(M$AvXqwTN;%#Lzt)U03zwrUG>*PNzDl zISG4zFl%yKrDfX1i3n9x4-yqpfR$IG0>w&A)fjYWYo%oa4_7G{!g|R7%qt*G1IrUW zrX2i}(z0n2FVm(_&6Ar1v|ad{g1mOdkgwnhmD#T_DpY#&w1%jTtV4u15ny>mcq!G! z`c~kWci>5-Wh*z@Nh=ouk0XGWSKyK2Rj=bQ>wv~e%Vr+bg=PjF4-buw$!-91_FJN~ zY~DCk_8Wv~5`dR;h(=yh_<4RY@5^#l#mo6*RkV+#^$h7j@xaYFJxJ#E`HwMip94zE z)^ww?G%+kH;((abqC(ldDa1Z6G)COJX zCiC&z6=^j?7(E7l=m6lC^{0OaX$Wo2~`p{%4 zV|o%Pz`z|RD=i!RH`VQ%Foz5S@X*X5RJ;MRw#T*Jv)eOjy?Yl*FW4w$d(Z!0(CyK< zZo7VUopOEc+U{EG%5uHqdd-#LiggWeb#^s%)pV726>;gEe>tx>&o~b{cSD7MWzIRy zDb6v@;m*O%?#?>S%FYr_v*Ur|hT|v45yxJ~CdW$0e8+Uh1gIl0%+cG?*3rOG%~9H6 zw?DGqvR|~Hu+v)qKkQwRt<_D`c79F~0^?3S!Lz z%$?0m%{9&C%|*<5(_f}5rZc94aG&7@(=yW>(-hMf({R&ZQ+HEKQyo)fQwfvV_`rC> z_>=L7aj$Wcaiwv-ak_DWG1)lG*xT6F*uYrLSlVcZEQni%i-r@1{f4cEHHJlonTCmm zG()tZpP{3nv7v^ctf7!WtG}zitUs+kpx>!qug})c)=$=t(#Puu>AUKi>uc#N>Wk@( zy8F6okV$b!x5qxwo@S4>_p^7jH@4TXm$esyn-%ZcF56Dq4uCgiy)D}|+cw!Y$`)@M zWb0~cZmVUhXe(wjTJKx0SNe_@>*ndE>c;63bwhPMb***vbX9bvbXIMS z_7Cj^xVvGWc8hkkc7b+=7HLzpk=nl6_S%Np>e@0|r{cG9=uBG4n3g8LE51jhq!Qvh zB8`|N&Lz_Ds^T0X#eXHfOQg71aW;`+!^Bxcie4(dL!>CD_%@LuW{ES2G_1V%7LkTd z6K4=WY(z)a#fy ziAX*E5nm%x_ejx0q^>u_iA3u1q9_un(@GH$sbdXMAX594;sheKeI$-2Qk&Z1I3l(B zOdLxj+pA(fB3W*WFB8c;R_se8lTPeIB*S2_H<5G?#a=|xE);tbDXga0!zX3`J4NhH zq(=_18(vB5k1tM*)CYC4C*3ZOp zMA~vmEK8)#8RBz9`gEUIhDaORi_a2i!`EVIB7NLke1=HtW{RbVw6>5~l1OW^#S%nX zy;>|zq*ZmrVnkXYibaXE+#(hs(y}>XVIpO}FBT%wl9Hl}NQ>u)P9iPbC_0F=pr~jk z()?ATjY#tzh*l!aohMp|G^c@RCerMEqKQbeI*3Lhz5R`7Akxe>qMk@Ic8NM7y%{cQ zi8O7g7)GS26-5n^rff$45^3@c^oU54CZJp*d3K;2B29FnheSg2&;ud~)zCjg8ovhJ zC(^j0=x-v8$wYqZP6_v4Q-8X5^3;H z5Pea;x8U7EzY}TTNpyoq0~(|2MC!K$T_e)VbLL~7VU zOea!JJo05~=QaF_lPlQp6M@)w(4n6DfSOm_#IZu9!%q8WY74M5_L$IGji? z^cE9{RJFSpPo&CA#5f{VY9_`Kslq8ShDhbRh|xqUdtQtp(sLulNFqI(Bt{Uav_%|7 zq*9~ASBX@zusD=R#m9+5h*Zod4kl8Ox#BBCDy$U;5y`b!97rT*GjRZs>_3S8eG;6R zLZ^sSw=OzKq*~|E2_l8JLdS{ZUW|?r>BZCND3Pj{M@NWMZ6!KPq^ix(AtF8h7W$4z zmCK`pM5?$7eM_YB|Dpp#DmNQ_L!`3Lp|6Ql2BEKrRC)^9Poz>mqW=)7#C)`mNJST; zFNsw6D%wjV*AesuksOuL9wOP|(dR_6G()?Iq#ucP5h-jG+Ub*^{3O~zq@3YsJCPpT zK--A)&&z15Pg>gY1#yf|g7SapGa}u~MO%n;*N8R~>2^P~iAc9jpihZ(GY)Me((mWc zCq%lDh&B-E+F$5nB3+#hH`^(5>yj%K&^jVrMrbXOE)_=~5$TtOXbq7r)B45T znn>q6qE$pXw+*c%(pf87L8LQ7&~hT3-j6;Y()aDqG9sPaftC{K_yv?rq$4}f5+WV$ zfwGA7-4AFnkq*YAMMOGq2Q4JhH<@Swk-qvDy^rJnpJ-g2oO2!L9d+zeZ9hZ3zlm`F zUt#mBrnRsqZf%&ZKcla%%g}zVb%YJme4^|Y|65v5bf1JdDAcF2vu zCkbK`pem;?zCK?*7c!rHF68*=Wt4x#Q_b_p3b>r2W(ux1y6&a*!OnYtokH^-upL+# z-_fvc&m#-Ka*8zg!@5T$#EkY4&z*;f=gwmj$JD2ZYk3}-ftXXyMF25)lU2}j8er%- z4cO4h1{%7y=aC7ZIi7mY~Iv+e!K?$ymGpQiudhrFz?&nuz4d@S2)!5JkkR%r|@JFM9Cn}I5{p{ z)^K`eWO`IuLS&5h&<*CD*+yxZ+$Tn=j@1LVE)?9drh{|%3gsBTw;$qqc9 zye7NEl&FYA`8$#rksOx^UlsB#c{3anzZuRXKHl$p+M;WE9)$rhr?4tb9F>`t7Ly#6 zKp{_Cijk)+Wg`#1KqG^aHK9?mbo)*kO+2+CCZ1Z6P25p6%|Y}@1Y%CnCzX=D_XT;0 z-BJ*WSjQAORclHk$G9_nv&UpyQ$2g~4Ys9d20POQ|4PPS6peM)0K@5vnpnC;TG1<{NtqcD841$K4y;b0n$oh>`r14i7AA!;0Ly7oh|Nrn z@yGE_8|*D@-`OIpcOf=k!m`}b*nGr1%=D+}byHd6W@8t_Im0-EUH_rJx$d;KM%d?J zLp4`5g(D4~Hav_E?}okhU5M9&ByYIY19I^i5dJ=R2jt{6Ao&xd9+0Ep4}>Z{A^GK% zeJrB=$*&g4>&v0^B)zuYexw=CR`5rJm5wNft!ORyBhmidD6Uq~Qt*>rKwrd3Dw+#^ zP7mmga&L+zenzNvOo~Q+J;|?^V(x~5uTsNy28w!~J<6j~x$#6@!M_6ZKALvGiQ0l+ zG|_#jTxVh!-+|FiFHuwQH91rR3v^eZe+&No4&EhpG@(bFe>>VmgmMf15Vm@7*tvsp z3Vxd)_k&l~=wXxr94p%JmkX{qlj5dO94hER!G9~2J}6fR`lsLxj%=-^ufK0&?Og(( z`vt#-BK`ThAJE?gU)PHCCQrP+@p*^$7mokGu5tBrE^^#)w6M>!U9vT@z6)9Rjm*e& zz*NSVWLU4irmw9-5dYVNwbQ&Fe24!O|JKvQ^QZ#&PDU2E^KV2-Mq)y8xN>4lS-3*Q z59J7!J1T|tvF=!bohUn2Fr6qzf89PI5Jugcp|nioV;xo30o3z6Dg(#`A0G>jtiGWL1Ai*#FMPU> z34ZkSdfL)kcpg0q;A2BH$>e#{5gxTkq=1R-NJ-$*^8|4Mhqf&s&DbT0FRb5T9ZYHK( zH0Mg6;hsk&ftFLyL`AFe{9x9#g_M@fJi9#23?I%Cz+CVj&f!p4Harhz;-SaL zYqFJ=jXtd&jb737s5qc=imPID+0T#hRZm(z==01W9CA zCD%Jx#jba7d`23LT*33GC?Gd0@QIp2#ycad&=sQ6vK2cwou;hnc~k@_IaS8NzrS~b zpm^Ic<8q7AvRShZ(yTQ+j|u}TrxW*tmDm7mE->h_IZDe0e!DphT-o!e5CFH~X#zga zKL*TxUuoH(8(yP9VbXO0DA!3hSo{F9E|IGPEGfxmUR!}?2IV?=D;Mvyd{(enwt~fT z*q|S1Xi!kDgST>(Eg>B(#>!o|QEA!CTOQHOkR@veX3kl%>WB#DTp*_{EXXHqVMG+g z3-SN3U4{u7%N)y0%T&v2mI;Fdu>w_{I^WkOuw3bGMzRZgA@JxO?yn+O`A;XO{?K#|02^o z(>tc=rpYD*C;Zb)iKbZ7Fw-DYUpVRC(bU@1)YQOK%Tygs{FgPAG8Hk|O-9!P*Im~i zt}CvKuCq`B;fU*iYoBYkYpZJ`)IwP4%62Vq&2i0iO@*2W6I`QQsjlI!XxC7vjnLcG z)z#kB($&~i4{9V-b5(Seag}fta#^8P!XxK>=WXW==Vj*wsF`rWdC2*-bFXu!a|_f? zSmRvo%yQ0m&UVg#8VVDg*bM|z0cD8jkcQ%Bo3N@TnoaLRRoyD9^ zr`f4>%yGw6C?Vv}fBF*yq@1+NauIvrn*(vZvaIL$!jT_5t?Z_OAB!_Lfk!pq{;^ zy_&tEy^OsCR4=gF^|nX0`?lM*8&JjIg6)j$gzb>+Yq(i*r)`UEgKdp%xh=~!AF3M6 zuuZW|w2iZ6*pi{TL8NW4t)H!@t+TByR5@s9t7EHSt70o}D-G2SoHnyfYt6C#WxWMe z4}P`&WIb&?W<6-#Z{1_vZrx;EZ(VI&W?ckzB;K)3w@$Vq>lnDjBGDRa9cCS5?Q89B z?Fe-xnpzuJYgwyXD_hG#eTgDgyVYpbSRPpJLY;{#mW!6NmQ$7^aQ0=NWw&LkWus-S zWu+zCvcRN)b1-*}e;BVAFB;DpPeF}{1IB&E-NvoPjmEW5DT@m8q|y! zWlS-~8zYQ^jD3thhJOwB4SyQ08GbQLFk~8%4RMBH zhJl9OhAxJ-hGvEahHyhQLj^-=Ls5g>V9-C(|E<5JzpB5e|51NJ|DArn{&W3S{U`c0 z`VaJr^mFwy^>64W>c{HS^dt1q`XTy$`X2g@`d0eJ`nviW`sej!^(FO%^cKBV_fU7& zs59y`I?cpxxao?UF1YE8n@+gth?@?$X^)$BxM_=Mch=!%?r4xhMTIm zse+s5aZ?#Lm2guLHx+PG9yjH1Qx-SR;ie33p2baR+&qJuQn)FJn-aJwZqRA8=soE< zPkPRko^zz-P#(*0raN@Nx+1RvL3d4=Y3nu<6Js(NWT3Lsz{w+QKlAiaZ=UwS}M|$3to_|WuThjBU^!!75{w_UlNYCri^P2R$ zDm|}wpXikIJSja-NYCTa^O*EJDm{-#&%@I5ko5dcdLERX-%8H|((@bX`L*=?N_y^> zp8t`a`=sZW(sQr${6c!}k)EGR&)w2A6&T zW=qc{(lbkXE|#8)q~}8Exj=fpFFof=&o`v!6zTc8^qed`CrQuOq^C!EPL!Ua^hDBA zke(By=XmKkPI``&o@1ovXz4jhdS*(`4C$FJJ=3J;Na>j>JyWD-vh+-np8tou_YSb4 z<^sNRd%qVDP0h` z6{JWL1VIr+;5#>&++^v8!ZE5Wgaebak&bYD{;93m&KQ8CsayBk!;W7u8VO*-X zRB$;HmosoV9hdjvavCnD;u61E3VyQ`{AMZm%~J52rQkP9!Ecs=-z){cSqgr$6#Ql> z_{~!Ao2B44OTllJg5N9!zgfyC+}223rr>e}E|YON9G6MB9EQuGxEzAZ!MGfR%YnEY zfXn{4?1#&~xV#saeQ??Tz0`_XI$Qe%TBoLh|4>1 z*#VdBaoG-+ci^%uF5BR;H7;A>vL!BC;IcU`o8hu4E^o(W6I?dNWg}cR#AO3q*2iT% zT-L>9A};ITG69#haajwOHE~%3m(_7u4VP7MSp}DsaajqM6>(Vsm*sI;4wq$dSq7J- zaajtNC2?5-m$%{aR$LaxWieb9#pNxyEP~6zxGaRr5H5qb4B*m_OCK)1xb)!CjY}6U zow#)1(vC|TF0Ht<;1Wg3nb&c74VPDO`8O`F;PNkA{)x-Wxcmc`mvH$zE`P)2MOGd|BrZ?j@;EMk!sRhs9>wJmTpq^dkGMR9%Y(T5 z0hiz7@;h7}z~z2i?!)D`5&!@4mc7XKh^>V66>GcDl2F;;%3uQQDm(gj`uqD1`BJ^V zdvm;Q&*Ppdu(!X%^_^?1^MX@x7ILg~)PS8xFWWiGUP~&vj2ztMU=*dx(mi@P|GW#G&0mfCSFUr%pyudMZW~L*YVwi7f+-4GDV(BY2WNN8)AjBdPOy+YBJvnt-YAHqUux!cwZXjAsqiH#*GuMR57EoI2$PS*HbE+pt9+B0;nHtvr@Jr zoGN*MwKh4;t!TnyjsM}QVCa3@_zD$inRkO#%FCSFwHGJu++NO%hU2)NDrF754-tQu zsne)Z#)MZ@@9wFTp5Xw8O}X<@fsUF=DH9%RJQqu)r13W#b$cr6Qv|V%Var||^+KWc z!3P7o1BLzle7WAU-Ugog;jVvSS3hT-jE$}vJ zB*oh#9=2v-Ae;w=&|1u!`3pbH5c#el@ERYEBp$EMPC;n*?WMJldiS-yJav`uwFW?K zd~BK+YThaF+ZKfM+ZJNduXt~sFofHx52VHiaLiB2?ZXM_*DujpOnm+xer!R5>zSd! z{BE9bepQ*)Lf$>ahw!|&hp*KI-m!*zCdL`z$UH$e1~K=P_Dmq~dnSnC`|3g$!Rwa@ z@X}vD{Z60x1MfOasCOL}Qty6UmuC)QeAWSK<70fr47r{<>bv-5UjqGQUm^6K5ijz3 z0@q{`09yJr84X&$pCiCuXaQ@#5C^Q?XRksUb>mO`tYDrdW)MlTA!iwYOCvu-mGLVXNAC*hb-N zH2^k6_7te?xMHk7gm{Z~XJgAsF?ofBJUPrH)q!04Ornvqoj8I1OiLX6nK*Iqp410; zXwc|tW@xkqO+PqMCHeFwh`=D(^yEq(sesN>ClpR^(1pR^Hz@3DD# zaJY+H1;EX^iyYS~Mz}xTL~9}c?p?R>{4ns9%^Y~0ZH)kL)CPW|c;I($(cJ}uX{8c? zn>DS(Sm+4(N1xGJIOKaCt;7#`lkl~QK%Q#SgqY9HN0`@Z_rKTQ;QqIdk10&{|6Ne1 zTkz??{y<6pP~QsJ|2OeW2Ty*F>t5$GjuVdh_L;U%ZAGkuEH9%gs7nFc|1d1&yTLFR zfAxWW#JDWRsk(&L*8*e+t_8%8?YUn3V}skMU4hs5+o*APbt$d?UO;gFULeMOQsHr7 zZ`TEIpP-(5n$}|Enz}^{Am3povM$Z_FPbgxm&!uq-EaNG zk1{OP+XAxmr8-p)ywr_5`<;254EdSI#r!WWnjpibwc)mjHr%Ov?{*Oq?HPPupSq z(1RhgIiO27gle-(!G_SI{YW>C_7jf$o;izn{1)MB%>X}B_NJ8LbM6VTQ_SI?Ne2%9 zEbPGU)2I0kzz3-*bik}{==g+@2}x0-*N^uT8li1zq|(pO$hTTU zECeI=ScnE-#5WQ8%5W}ZEk=$#qYZ+pDEG>6;$iJ+=2%^mePlW*Y10pV6_nczy(SQ| zkc#y=e2aG*dPj%86rA;KVnQT~pwdIio6fb9nwFZCnlujUNp~riKlsKp8?(|) z#^(nD)MX`QWF|)RQL_#!U8UTe;TuYtl$wl_N-14re0cay=`FHKXW4yYwp8UVnI7KS z92sK=P&&!{@MvvD?UzbN8IvRplT2HKl%XU8nR2HTWzp}JIh&!%xFxruqk)Qyak}?O59^?rLD|c0J@ghmQ!hCg06D*D5bTOiA}FK^b%|< z6CPz;8<5h{ghv@`y-`}obimj2C!XC!X+F&XmJ><$4rs%1Ehb7c6Q%}g>rk4K^Z&__ z^Zylr6M;nkG~Xw%a07RH?n?!3d^LN=iGZ^ZJ0JF5SDBVEk&m=^UZ!Jt~G5Qznd2~oXKN!%HWLdi7 zqjRaRR~4H^xQk5_b02?$=LX##WSVaCnT-f+Q75g%(1&$b2*Al}AV5oV^3o4Bmzrf& z5pu=~wV3w|@81@NV8;W1*Z4@%niWLjgW%a zK&iQ#W^5vip=W3P7IV*glIMm)_IrU_+95mRjy)zIw7#LV7E>>Nkf#QxojyP<&1r{G$2n{u zz@7`V7K1;c8*WgO-ZIsM*`T!@0B52lyzZ&A7IN?Uj|#Q zMr$$l>N-3&eExa@wzQ=k!;Ufe6IjO}T8p9In8-tej@)C8j^sZ$AiTCKv=(!}KPZO# zZgaTvA3qRY>rz^axj#C=b3+QA9>8sU3Z4QFF$krFT-8}+xxrPPr8b@xTo$?mtvr_n z&Xms`g<#~B*EN@g>tdIMJ-N#{WUsRts$e;foXeaItlJ%*ItJK(woeT`6e<&39c%;f z<@@>1_*H+<_lz$QVyzGKobxE2k`Uj&14Q4S;0oHkwij%5tphCQEpse>^aw)#W1thA zg~ym^4-+PgOG!+bk~ALb%-Gz21xI_Brb8K*J~p#%T4H8Ka$*t<2o?PcOx&5Qg?e@P zw9>-X<3@X!YG@jDO|j$0dzd2Q%uLr5wNy@)VTIMTqz~9P$!ql5Yu z)3Q?2Qqr<;2M5V`)AY@e&9O32hH~h(waNgn?fR)XT*hH|oDJW9;fs~z2)Cu(O#H`R zfV2@A>8T?Ub*~w*4=5Qj95KjS7Fpy*&le}kI7DFWu$MV9bxauH2zQh-Y-AA}X(V0V z_k>0w;8Q>;Y4SQnR>+Y~jhELcZ5ghAQsZPCRc2{o36%^_oTn1U?68uwr z+kGXxqdaeTobJ0_&q1XB_Ks!t6ZTfNuyu#Elw}Nh<$pQoH}H4Ea3NEoHE1ogz3m=fg$IVC zzR3VA?Wj+;@8$2xt!lNA@V440=AGu}dEvNZ67WhpF46Jo7FL9|#W`Awse3-hQ$s+x zY@n7FP_6)KW?dlA&9iAOhHv*H4-coSSpYBXbd|tsHVOjRbT_TVpo2Q{pm5lb382yr z8yIK;(~QUzOJHyBNNX|lUAl-kmBQCD0J^O##|8pTwx)!y@g7=>Is3lF4=xz#CjzH5 zBYl)Jy1^xsjr!ACOq=uwPYXu+2|z2&NY7}QCPWpXf#!48;E))(>mDAtYWP|@Aa|6j z2+_?p8P)pfv=*aI(&;Qr!fAjic@mDdWhbz$o*Hi6j|FOJH}B~#Q*VSIq_tIAi;0WrrU_WCjR9h5 z%QZ@@Gi4Can!nOo3|uRnA7XIINd;hOPB|2qGl&q(8a-((#;u||{s$+?(SR$>8#NY} znpFsEweGYQGy8P$Xu#8A6fjHkw8+QIj57qc@(Nmuu}kQJFo4s-NWhln|CA4#Gw~4K zN}AtRrIupuLSOJ24U+k3h;34y9Ed=jAa{&+DEPUMu;L?ppbY%*GXkt@< z5$wSv)YYoN!cbS`y06IM@j=DCCaQRBSnE{-HH*x^jlx0iaoblsb@lLd4^SHz);hkn z#4M}_kcjQ81_&dzm+Ss&Z63B!__`Zl4ZM;hf{jgTMwFwUX58qvTR6wQ?!$%b-DkbPvxB-L6V*NLooT||^$e}W`~zR(`QbXA0{jME#}kfy?9FR} z+@%(+h3Gvh9OlvCm~JMZOJ8YeQ)ImR+XVZr=V>j*PkcHCe}s(Ox2FTXf!1xI;?U%P1ocjB#P57wjC`UIj|>-v?gM1AzNy3mTtC+BuaOS4 zza|Fnq}x-p4quxF;8Tq=%L~W4K-YD`-mV_4#eMi{5;yoH{@-R~dlcgPuYmY}C4;Mi zwF7GdE&N;keSF{fMtd)N=Xr~HR(o2xH@kbfj=D0Pe>)#@R&{K0^t7L}Pqurk^(~t% zozZSINM{yW6@xKONS72UP2KVv&$t7uKPd}y(uZn|AQFGLRF zD}zBq`a!(55$9%DV)|J81+B#oFR zpZ=T&uM@r=$vY|C)W_?7sA6!XmA%C~4x}-;q!`I6Jzx1O79Y0%Z5#)JAXe~tVetR0P zEij*y1$49K6E3PRp`EMHT1&T>7_ zNq(F`#Y>y0;&Im(WTdm#&{{a+-7e_@Zi0%JGEv22S1ANJ>uy>XjDGdV?JYmQg&%tG zODYNI(of4YWr?82u5}1@hIV@?<6Ob`$ETF*QELE?-y(dy1mGK(WlE^)kdYxZIUzeC zBVin8G$I|CsNJ=hI6~Ng?n87}E8rV?8+5>|ZzzqtOpqraT8oiyS;~(&Am3^tGPTAN z)U-vk79-#PF^`-WzFr)V4RrR7uO_jUX2LqYIIV@u-To@WGuIDaF9ys8I(rM4Bkv`% zR}8wvu1}DhbjkO4>k&H4Gi?3^iT17d`o@RydQYGcn*0c zdHn7b?k29yu3pY#&P=Dp@ra|W{Z)HA+YiQGL$nWtx)6* z)tNB=JC_t=LL%xPC5_ZZ!-y;I854Xdek)u6aOGVYFF6Y)jn@a!yp=dQ$~!VniCBw~ z`8?WSOuVUpFR5-?k$?{1)FJqF7SsAh2q4Jy*Wzpx%qsza@r2MRmFKbNq^yhj?o|L&u-^Hje zTdo<6X=iE5DihZ4@jXjcny`K+EpxiM!USFAPM(zIQYJRN;?OAV&sgF7zO1ztl)kdI zc{Z@X2EM3u;k^MjXOVz-4V!X$e*e5du5*+{Uag@{3GSkPUBqWbZWkL2?@Jl*h zrl&#FS#ak}p9EIDNcw4%lLL)clG?bo7|NQQIxaO`-}rE7ygW?WeGTsU=#->!S)*~D zXxMaRrzB`bSCrE>^3-50(aqo%*_MHUnZ-1T#OKnqh|ZuhA#;Uy=Rd#0QE+ql6gM*^ZN#XI)DgV) z%p4ERe=fIqs=6rG742@NoI{8(UAI@Q=`5aqwon%V1@qpJdY4h#rME zKvPBG^VsKKG&L?2!ulsnP8rU$C|}GQEr>D-FNX#T8Q&o7TI|vdg=av6LD&NhHMWPe zK}~P;%NrDi%U(X;zf>7At{Ewr-0MjPR%=#^sEoqRp*@cw!>VtOb~9!|K;e?mpc5AU z$^Uv-<2R^vFvhJEseeJc_WL6FhyVE(ln!iCa#liGQda6DE+Gz^kTe2aNN1!TfT`#@ zEVNQ2wO`PHs~K3U3q3z!dQMUry)&`t+-k|QTNQL*>d(jYe8#yjJD=Q^~ z&C&V;4t+itq?Uq)&qK$v|MiWEd=1A8dfY=hOl5ajQUMwj#b0Z&#tU(1)U1@4}o91>~5%-V}J-$#MqLc**fO0etgAT8lwj z=v=|8g|FWZpa$lc)*s=}6#zXPCX8!)&|1tocPKxoHN)4N0IPxFY~!=6&wimTj1Zb z=_~Y8H*W+bjtzt|Z!fKdv_0DG~pc!khhH3;sCM`3Gq|YX)Pu%SCl7*3qw_bT>6C}jXdfI zLs*}*(pt>yXvH(bVxtN$OIvJE8v_Wz3l`vR5y z>Anwq7H>z-UDp~lfyRFo{R8_;*y92U; zX{7WE9fC|2l~L3^KM>SCKZsFx+|7?Jd?C64s=FQOh`Z1#`*IbjPt~AdE(mP>vsXMfoY`l?;It@+vW&w#HLJucZ{aBc!*Wq zngJHSod8(c;+FzPHq5&5-FAiGZo4AJow1T1Usxz~1YBtgg;-pD8mX;M5az8GV(YOqUm0BmU{&V1PU(nxK7k#KK*QOrGF zXGw-hqdjm-pENXUicYCN(egchBFy(#uG=)7wGD{dnL(^g&pP5w)5sWankF9O6y4qk zb{cm8v9z6r*n@%)Z#+tCA$gCJIlNW_d0TVHwb9o3eh}gfTAY~;ikST8WS$(RzBWKE zZR+EX$@o0%g!!YAv=%aV>#s{v2z#W~z$|T##4{)J+1v^2hbpbb(1V|h8R%AK4Rkb1 zd-OBD?i68OcS_9MT9>L2LgKUpW@%BMbOW7EeQU7uJX?XhKZl^dKSzw-v;sfe@SSM^ z=+eG3@zKe}Zo>Osd0LCPyXg{NfNnQ8O}Epz>){0Uo%ysDL*LPb8*Fm_KM~nxL;U|| ztcjt8p-K<|pn2fSK(hZ=zv?gId&$?zyT?1+bJa87Q{DZ6yO--%SB|Tk^F`wQ|%>04+E61WCTMY&n{xGiA-{P4Vl5?_6(bZ*f?UB$~{SraNB?VBF1fw zxTh(*WyA&`V-_(PMU{P*F`lULR3g$28@I?)`f`K=%;pA1-sf%5kw$jPd#N z$m>+pM6G--uT$}i%gPQJw`ZwkN^cfcw#%5>XHVDh!b%%930lqbzQB2toIsY$)K1HE^!Mwm0VlkY%gV6uX&!cy@bI= zH^NXG-Ho{QcX$c%Z{O2eh~B3Cb3A&>@bzRs&o=DJ!wu034vT+L^NqULNZ5ncAL~2} zVDN{VJNUZ$rex56T}x{*`rF^|gAa+BlK|bg#LPDu{Fpn+g!z1BS_|3R1~>5RO~coR z0sDB<6enK_9YX!fYFZ2F+YEn;rw6qkYO31Dy*f(B&-!RB>_O}AU*UTI!D@#<4~z>| zdn4V6wbT;mpXbq92;bK73=a>{<_813ana^)20qr_OTbT;ptZOIzNRr97-Vh-;#iFd z_{kS&E$l#>qRaUXz!}Ft=zwwOcQ<+h^zJf&J)t=+oTx8`-f@bDhN*r4KpS@!b|YxL z^^>6gq}{3bX}u7=_0BJN^tR#a{Q-T3Y11V^k7Gk6y*Sp9*1}%2S+|1k1-!TYOjY}M zmRJIQWE-u89ccZ>4}1r}i>ohmK$;gKBjRE ztNEyzg_=NrUy0UY_{VilMsRDn7r;xqwMUwHW%TpLpm>;p_JRbX&tF?zqsz=1%y&y^q#n&KEjyoRRbY1GbIGF~V`L zqm!eVqqd{0qmaXD|IL2fzR$kh{-J%feWm>|`)vCp`)KC z+6Nj3ss~C2{QhhH^Zq0Lul%3+-}ArhU*>-Vyc9D0BmDRJJNcXWYx~Rk3;C_S-+ae? z`+VDdANp4NR{9?E&Gt?5jrI-jb@jFK)%8{M74jT%Tu4i12xD?j} zSCXrztDUQ%tBR|*%jLZ6Jmoy#+~NGt`I>XNbAeNJPIL};_Hwp&HgZ;V-s*Ha{&bvn zeCPPwvEH%TvBL4FBkahqyEdtMtY}-g%Ut1?zQ(H}2DVyJV)%uI|kad^!W9wRL zo^`Qxj&+iCl(nDrE^9MuEo*6Oz;ewN(UoA(=E8q*g9eiHk@b$He2=NFB?>W2ccihKWaOA~ltXhgTqVG!qZ~hSX6^JXjW~ zBboU9OGr&&;(@D39l^x?4To80^Au8(nE2HNqz+@^-f>7B%EaBjAaw{6 zcR`N^GjZo7qz+=@7x2@8Oxywe9l*rx?U34^iCcFgwI36=G(&1%CT@NksrNGRQwLJ} zFmcmlr1lQjT-sfw2}pU8Nok9eB}^J$TzP^?V`nLkGigjUWigXRZ&4O8Y1ByNF(!?) zC<~c1VwLhJlahnV0wyIbR32f{u=2`$CJmXVJj|rQm6eB>G;pKxAd?34Rpv3N-)`jr zCiNYr%wHEK zn~CpNM`{lyzPk{q-I@6IPe|>?#J5~X?aIWppxs@V`1(Plc4p!V_?Pcu;xmBJiHS=q zBef$FpU6V$olIPO1*sjFxM&zs+cR+?{InetA6<&nJD9kj2~yiKasCpdwqfGK4UpQJ zi4Sf^YAYtrga5ZB6X)(kY6~XbKN6yhF>&_qNNvW%oQILxl!@wmq~6ZNnP-vOgo!g6 zA+<3R@0)|vMogS~1gQ;~I0c5i0TU;|%Uz#|S!NG;36-fpCpVPem@ zNG;98yU#-~HzxMD8>uCk*af;@f{C4>`?oQ%(-frM%EUVlBeggaI}AZ;F($TypB80e zTM%zyVw<5zEyBcB@F^?I#Fo(gLQHHv0;wS;HeG;J?rYqn1X2U+rwwNz)z8Gbdy(p6 zVq$-!dYPC26NQI~wPz#M&BR)zk?LY%4Nzbw6RSOeR0k8Q0<)comHQ&q#>9&Ik!odP zg?>o2FtJ=7Qc-l~%Pm_$xz420E0t?ZDpgpy%A^v@l)ssD>oMgDlZp>k{$f(mlggh= zx}~;qnMsA$Dt|DkP#fhElY+aH-9_BdV@$f(NIA-+U)L%}m~_6fa+pcKtX6(x(pjH!h)F-sQw}oebP44LCY^ji z`JPE9>MP$d>8JI|0VW;msO)Fbk!{L8CLJ!Je9NRmO_Xn#^uzng*G&4plJXUk4y;r5 zGHHJ|We=0Sy-(TAq_3|jyO{J$`?%fa;x$=lXg~Db};Glt;%*L z?HH|WW74)O%2pGcPdcbN3r*UH;WdNo^li%GBel{cC6Ql7GwNiQZUZ!qck^~xG1J=a2cok@9n zmDNnj9izO)q?K2dSDCcpQRNjTEe|O#Gih0_@)DDlHd0<>(o@rw7nt;JGHG5BWd)PwD#~&u&G9PFFe!VDvW!Vt zcPmSolyOdZnn@E!C{KC4qft4_ITV@`@&*?LZw;&n)bPLMIpdiOJKM$XvaYvX?VMYk zy&Ojz6YPK3AF`LRy=&`W-ESS~Z}0osH`05`n`Sv@$+S4oB7+S^qWpYoR>*;fi|mRRm|33Qd;4Do~#H%a57 zUX-h`xO=+9waNuUGW!+SJ7QH-ewF)PM7$2UaJ}c{KCwt^QQzTnkRv4hU%T^)#xH)N zR^=DDs-n3AYNLuBzRw!sVOd~T^({ucn9s<)U!par_heFjmV3WLYcw*k#d-rMr%idJ z+WS8>GQy_}@dYmMkuu-yli87I`2W`H{RRys#6*o!PRP|*>f{-Xo}?U?`vkQHIiEr0 zC%Ny4)?&;%a!l^RgEkt^Pfs}tYeT2UD)%j==cMu8(m$s=!jt8xGHsgkw&6Z)mkn|1 zE$}^}jVFvuNQ%r4f0)u7b`*&;cgc_&9tHLeFMs$i+VAGPJUVYp<%lU$VT_-pa`>Nz zh5sL}P3H5ERDLvNs)*~`s2q~JN71IKe0!AtNAHgl|NrACbXRaboV-`{r}$p>Ui3Ei zOm}a07k7T=jyeTSS9CIt$pVjEGjfX$ zrggzC8ds0p-g0LL&P5{(-g8p{-UP2#4nB6BOTdesq;vbb0SO7RfZDi( z1Y+vQ=W8S+cT3NR2HVLE3?Sfv0YdOLZ|VXvL8!4z05>i;niyQOnGsSS$^DS)`&vwV z;VM7WaN8>bh>Z&mBqr8b-Uzohnbu-%eMno_eWZnMD0 zk8-o{^)w((m;YUi5XW6^6MQ?#Ws++b<}xYMW^V?M4=>_)z&GJV)LR+ZlxHO&LvyXd zkfCK-uhfP2hwz)@fZMq6n*}Pjo*OpHWVkIkv=(d2k7@jH!!4GvfNjDpmbf-nf{YNY z#pqog=FwpVI|k5ASiuS`wHO>+ENCt6z@lk<2SC+RO;vTy-b;9|l7U}!6^XgemF2l1 znD1!dHZGWNfvQgS)l|h-U71C&ugntTzEFh6g^R7D0N1>WtueM|!u+R}G~`cV(vUK3 zmg+9H!mKh9*iD#KG!q6hFcR#`9cV2c^5Z+WAt&+wo1svv;DdoZfnxq%zU6SHU&k}a zy}|8qb#p%DIP6HUPq%Hi6|<&TUO~U2W@PIguAc)AZBjcd&aRZ(vJmbt)WQz8dRn(k zXp{qvcSc64&G$+$Y;87*%~O=yT>B6-A0Z}Reu#TiVIU8hMXu>sKJumu$e1@>ASTb% zLT{j2(E#>a^xtuz&S(b7elF1Wl zF?5|Q9y%chyh7#f$@2JaO$Da9lO=R;5ra_)JT=iT#NlC-xTu zm*s<{h7)tZwN~!7h#TUVTuZqLBoHvvV&-Z(drE^G@c)&&O6Qni-iXb%lv{f?8SC1! z#oQ%znG#{FUFMB-OunVuTBQkdt)4S+LZN+W~q(0e#xytqAo)%WN&k= z4gWIM%K_JKQ|xXUdo;`<8R=>yl|pVcVJd|(ZT5f0Q^O*}4%8;Bx+rzjZ-8J|)fORD z#fy-(_IG$}cqwgwZNk=B!{)pX2zTYav=%B!>wUTeH;r?^<=>P&sK%}LVIasA_tRR4 z-e%VVe#qgQZUJ=jEcn#hjKEgtM{6xE*Vk-5;3V{f{P%Pp5jpv&b6p<6$v+r>eU z90j0Fhz&)RB%aR+Aun5j*5V#KtxM<)$AvSY2gcp&&%ZE9#)1A5bv=mL(dCw2N#IMb z6vMC6O^INum;vzS%`G%oNK|b~6(-!J3Jba0Z2W}Rb+9>42W}H=&f1{!VJmV=EF;V% zmWi3a>BBRFs^4d-stb&`w;m%sxb>K@2dy7T&^{necvqMFL&j#xR zJ_y|9-{(*AUGOQsLU1>}iD!#v5ZrUma3j~lu3Md}oOK-UJG$AA*=O1dTRU0yS_Y!i zXbQ0muoB#qJ9=!1eKJ!rG84z8kIk$L&K;?d{{k*|L-jvNOU%qjPJ}22lQUAYQrKT$ z3!0gjG9_vJ1jucbSg(%Av8BL3hj5z^yb1?PZjq+JfENMoD}wLNSd$uL@$2DYB)CVV znAI*xngQ1@O?aMs#tXRNDc4P?fO%QDCf8S#Hv8Y*PJyV}ePnCT2%Mx2uI1*R9}JuY z$SEk?_62w8ZpL?MR7TQ-(G$ldPRvfph`43LJz}`Q&`VxJq$Fo!88=!C?(rlU-$B-B5kqo!PyNV_=lX2aZD%mCO?QVB588dca&P|Ac%=M?P-QKh>{}r zvIX5z#Iun>OcvOz7e}2@s3Z9Q?+KLj5A(h5vv}|IJnKH|Zs3~a-01W;dfAuQz61aN zOw0Qg1iu{jPZ$mms)8*i@`4icyRCrs0`r7W!%kYqs#}+r8ObML*AvenEYfNo*Yj0Dgn7fLmwsA z)`EO~Q-NV&W|{pq?QG0i6^N%wJr?}!R_-9t;N{i4C1k2u*;Y?*!i+E=k|6J>fUZK z^#`qa>f3W5fSuF>Cf#6D!!)xK6X>3EX)T6-QUgDQ0K0KG9Irr}Kg#7OF zV)9R)<%b<~yrhXb&ReVrZjZZZEymv1jmHMht`dMP@s5suz=?g9kal^L)?(tVD|q6n zIS^zK!Qqb!x!lNYLBse%AR~5w8Zj~Q62#74T8mNN)!kyKkplrB5m<<&p~hN@31z1# zv=-8~4xHf!7F_0v1Fdn12=cA^C@p7hCZKm7rnMNj$W$H}CW~SKEOD}6=HvV}YeL*% z2(88B6Q}Ux;G?iarFrHm7awc70a**c5Ui*<6mvm0y|g zTO9}&Eyv`_H>lgC{J-QwVu%U!M(++y?FHf34KXa=s6BmFE{OUbMh?iVrSnhv2TRkN zYnD36ahIJT(7Y+{YrJGw5Y--{JNEt8ozJ&?)Fp;uM)k&WP7HOeY5sf=l0Wu4lv(#5 zJXdkobUCCT?ElnAM9F`vN;lgiO8^BK2IM%==(0CK;sQC7Eo&u#4JdI zT_dYX+_hRVyGB>9DdUHOckJlY3Ao9ca*pTefrz&0(GC|N5r~|R0BsKMR3eR$SGu|! zPY&8zv+7TqANs;5em9If|dI-5#Epi|QlaV1mZnVsfm;qvU#Ka&ncPFhy zhLK9!>)g*7Qat?S-kZCojVMijWh&eiDx4^V%_?mjP%qa zv=(W1nby^H%F!$bGV)1{xK;o++p!buDK1)z@k_kVD+(N|)(3ov$EpNBvTld%2tl0G zjMie*290@CIBKs4s1n^t7%I2*WwGJ1))4HhHDc^?x*#f5av%#M0>gvk*@GA$2w}!s zv=);l%;pCeV(KIUsc{+J1*Qf4BsWpJ-aAozy|;DKc04aEN9q8tamx__Z=CreZ4(*f zv`ykcuB@9cs^>tSO$2rn$?6cbrx3{TwP-Dd?Rk+OVVIO_1FZB(Ii695@Q!_!)?)6i zV|i{EYVMp3Ip+iR zfwmW{SFG(U3*lG)ulN)3>%RvcgmDfT1@6YM?nJB)u>rY1OeYWI!*tODskE)DoqHf* z*bLka;KpqR#NfJs-0QRmW9x(w#wu;Q(2^&HDX|9-8~5E26UPb2{l0dC;{EF4kq+L; zb63lOoasgeIxdlcUOSG~ zV*IzC;HeYG$23_bm*el)z+{Wz{3mkSmcXW%p zLYqHU++hCrLKj>aY?Yk=+XP#shONIDNk;q`?IZKd4L&l(-rzL_tb82--ME0cT8&V3?_a6geH=02k{64%U8I{>$F0l5nt_?X?! zVl7nuVnL|<$Y-b8dVZMU3R!!=HSP-84RB+VL6RX}G>q2bp{`zpXNOs(9k81)tI)Hx z=jgdP|dE%HX{ z6X^l(bWWh>X}Uj8p!=XX+x-u4@LtbhRL=4Z^86HfAmj@^9#{rB0N?bt^^5^u|M~91 zuBEOT&Uc(G9A7$y+5fcPZ!ckc&eqWSskOJ|8{cMMH}5WQQm~?B2s(@=7HAmYuK^h1 z1y|qz@xczTKhcAP1WVip;8TCe;h5$XO z$qCsB842Tbt@knI5s%mM;~}-TDeckJc1Z1Ih-X=Wql?W++{Oy2Jq__J6E_%{QkeY; zsrMM-uPtsOK2@} zMiHdmA$Ka)n$+7fklI$RF4I=ynIe$d1~zjZJTb~0Zn}qI0k4rdz?|XMSul{=+LYlg zVCwkKE~}IC|IbmVGwl6;43zN?@~!ax;H}}A=zhy}!PV0Ffa42CG5ZkPi`FyN+bt^k zyue-lfBu6=dag(cMwy4CT&gP;$d%Y%4wj|0(0H`H-B+CbB@E`?6kwKlX2&tZOP?=2 z*Y__G?(bg`b2k~xbHiAVFmJ3`NLj*qfTZZmJs?ccS!w${GkIn>%}54j6HYUXHJ42m@4HG5<_PSj$+RvQIx_BcYQ#YIG8LMh?h)9HuhCizUF&Ne8dm5%0osHWdh8J) zq5Y^7tqZ1(Ofc^}!%=&^51{gv)hJXrxGGpL@OI!1|1SSfZ(&caC(*sp-P?7-HQD8N zE^$_LtZ}rkZ?WHFJ7`O_*{o0a&ibbKkat1o5o;C8YD*Ke74;`3fQb$`A(dnIrI#PH zbA)KrhM97k(`;qY=4Qw-=HDnt#B|xsYW<7}5^(k+Ch5zi?=H2?BXx*5?P+Fp zr2e=5;&QZC_kw0;WTd1e!*qlfB2!8HzmAdkf6qYtzuWyYeV_UQ-rk<4-G|)OT;rXa zoP`|y?JI0YY_+Y~mJJpg>KNysKMY5!)4}*5@n}`NIVPr$>j!8pG=XeSs>zu^BJB5> z#U5{mO_;9@rgg#W5lh(}fAZ{LbebmD=)`LezfC8!e{0SIe~X<5ww4~mQ^T?FRG^l4 zEX-5uqWBZ+E1Ivym9hm7cEnazA&#LjC7rT8pWJqj_pLLYNHH5>Lx? zgI!RrvCBmW{N*BIcy}5P4;f)50labPgYxYw;=}W~#x6Zc$S*x9CNGxClY@?Do2cXY zbB+C8j$r>@PK>R0eSn}1S%57u{D^+Q`CMZcR}tcitHi{&ZQ=(Sg5qTYv2j813Q`f? z$>BnIf_kC67}d9#M+I%pkgLtiP?p~yNQlqBOlvXua$SBSIJKS#6h`p2so5 zL!qw0Cj$oqRs89`k9n7&xK2(ulK9cM z7?t@RxGthJwT$6Moma6Ct%b;2@7K9cCgg+*$$hJI$h;q4Uikz(kQ?NL zLqIHX^{FGyA3iv*Ob+2LlOyIHq5DWQ%Lxa8TVg!90=Q$sjpvoxM(|5*6XW-Pi68c= zIpF}{OWauz{Ky&(%#j4KWG7mSQPcS_CgJ)yVLzZsT)8pSc;UwLZd*^VZ(A?M9#Whi z;VL;{A7C37ZoGimgWJ01-P)Rv-r8DBI##zdu9Xw^0;$CH4jJIcvRFUK6(g>jdBxrq z^JZ@4N49QG*aN&0*E@_i&U{gn7#Q=4-oU^(>>D1sdQR94(8h%uFF+m0B0l=c6(J^p zydp1)M|goQzFLEvunSL#~)XcA7EBWWNy|b3ld-lxe%D= zxF80vslg&q!-3cem}8`u*V>i@$( z+h5xEs;{m0d+!*p-SeR5R`<*97Or)!2F~}K?HnIFTH80-TiZUiT(C?=zoDr*BLH=* zDkwI|G)H*izYe@}Q#<}xN0#MbizBR<)ONh9k4SyS#NJ~98mJSg%L;lRNfRba&PdHl zNsRslykj$&9i?8K#&xD7CXY)6@2-TK8u)Y^9 zn<$2adi-A=C%XlU)Td2+mEvBlMCwz9gl)O00f@aCiPR^<$N>h-e;YsSrd!V+Gi`~P z1YE#R_EJA#$V+`wLqHRZBK2|eCQyBXP^2ynI~+L?U*$fTkhl9Ehm^gk4wJU&1#Vra z$3-SS_;@yRq&{Xy?(hOE6xyziT7rtKAMAIyw zNoF5L>LYS4z>$_U(=Jly%kgbxt;ASmk^1lm2N+iW?R#2)eiDN!QXi6YX^3=-w}m40 zK{>9_tf?4{oHxn=mPkqC7qvhl^#PeLTRh_-Qs>I-TGZ}`)ca+2EuP5^sdMBmclFjb zq|TP}5umGUouLe=v*cVYqpfi^E~Mtjxw{hE7Bx>HH7w^oX}$)TWeKTjo_Z;<9bPsneb$;h8>lkidWjkxDYaL^G8GiBq>ObJ>AFc`(8sn}h zh?jBN?8CN9#6r^{L~Eg?X2aE7&QcR@o)fMD>=RA$m(bYt))T_rj%1e4Yd2ra|D-NH z2Kaka27a^rJ?P9IC)70QMO&>GZEw(v*OU0CaC=U;67<42Z~B|kATDS%fp5K>*1|`y zvCw-wJe`K&61+v z`%!l(*YmE5&Xvwej+Ktu_P6X!Y;Re%S$d=WD5(I$0QCcqcvzy@q_|ZhQrDYsKt#_d zbTP1z`k@I2VzlXul#wKm!v`id8d+I^-x^ZanecG)ZwZjP!i0xQSHm$6ce#lt-f^?U zg7b(O2vou1Z3d9~z6po!Is&$eMCyAcXdP{wPfPQzA@*7EH&$ymdJy@JiO)LjY8R<* zoA<0^7ph2o%ZyWQZP4Q_GLiab*y_l!{Oe<|n|kc=qdy~ct$C9>joysZH_U64Mqfti z8bd-`i3b~>DQOc5`FOrQ#StDa`4Qt*BPzycSzT?&q4-U7H=1hoH4`RJ+|`(TtFIbz zawqO7J(GXMgo!$GRLFmnUN+%L>fHfen&}8nm8`Up79%=Km(~d^Z1RgHD3bp8jJ&Ha z7!sgTtVsHH@lyAB6PBEDPu!6DoEhIh!D$&%pEd7Ua|c~W%`?Q8LHw-AIv+pdT=QI` z^94X%WrA93TN-}aS{XV2FNQKvs9jJAYz>6`Lwu{er@gfy|KGc=tFA`QbjNG<c9OHZj=*lZlc|auI078GBJ{j8bE8YvE&n74jdqF_8*XI8*W0JvWwPY z^2$&17Ar8IHwALD&XVYu$J;&<{1FXlE$&9CmV7tBfPOo4!z=^3t{d#VA>_lg!v?cc|3>Dkf83=L8TY|I(OTS%!iD&5fciHyU;QK9;4@AW@_{6ETi(D+;vO8- z9j3zhQ3L3KS?5QZ21R-h|NLmc9MYQsbA-LvSViTZL%W=CeX##qOtSyeUU26}v6E5% zGNd2<%Lx0iVf1CbAMib^2T#MS6C~P?gpmnJ(TmT0hY|9=!^Gq@b@4ucysr7=)KEc) z`y8aTnEY9tOHJdPa3YW!7m-jrhsIhv2y$-{^DM8oIOf@gVzYR4X_^zR1L)&TQu{b2 z6GGpsFs;P{zvUC29zw(<0KIV`Vs2vKHMNFh|47CBZ?%ppEOEr2&JK7n}5i3NxNcPH_N^SX=U4R7dnfCq*ZPE7zdYlWjX zBN6bfBtLXsS8;ym4da{h;Go?#Ow?}P7Dcc-ucNh4yEnY7^CxMY6Rr-}Q%#yu3N&aD z_D)(KI;|7;;g|jV(8C*A4f+WXu?Qk}lIY2KcZ#DYZzx}kgO8m5@3E~#phTaZ6A6gQ6AT%{JCNwbAHPkXxCsZy}C}as<2p$c772F(rC-_3}$>6-;wBXp_ zpkTLPt6*ZVe6VoP8n_rZ7Wg{wS>WBki-D&C4+icFj0+47bPu!+)D2V!6bab;zxjXi zf8*ccf6xDt|7rh2-dDWKyz{*?z3JXz-g~@vcpG>tdy9FUoc#=FlJ?%UVJykr#JudfU_bK-Q_YU`m?$_MQ-3#2Rd!l=|yO+DYyOF!9`&PHx z^{4B!>pR!yuJx|ft`)9FU13*-E7{fC)xp)+Rn2vq%j5jZ`LpwT=NHb8oUemV!$N0{ zGt)W3*~fXOvx&31vxL*@xZ*hD_`$K$u>rClu5vu)nB~ZFq&V(%badSAsNpE-@Y(;i zpS2&fe`()nf5V<@Uu2(c&$f@W_qBJjH?`Nam$Lh9S8c!84%v3uKDMp(Pxp`a5ApZ# zxAE8WSM=ZFxBGtg9ru0f+vu0;m*34GRR@xS@UbCLF{%GB8-DG{!`mFVF>;2Zr*3s7f*3Q=E z*4oxG)}ZCO21Tiwyo$iY5)~V_MqsyyiVbHW*#Aex z1{MUH>8Mz5E`sf8RIFPZ!KN=N)_D%W<|!&B+>T%;5*2H0L9nEciZ#0hROL zOsv)j!5S|5(<-?L)+q*bX4@G$EzZU$P^Wi4MGs?C@LP=j3AIu zR6INwL71MXc<46-@o%Ey!H1A~or&L{LFzRoem4uLSDARAEK>hw;=bufy~4zAok;zQ ziC@n~>Yq&9dkv|VnYgDdQvYD$u6L1oiHSRBAoX`9ZY+t^-a1?wUK&=iO;M?>Om$h3nBFfCO*9osoyj4sq#quj)_Y?KZewFC%pa6O|4~-Oj`rTamhriPHxnbt@C6 zy@J#&Oq|*nsh=@%@@}MVX5yqmNd1(FS%Z-J2@^BkL+U0bPV9)(kC~W$0I3_9m^KNi z8<;q*A5uSJ;+QwUdya{t_kl+n6Gsg|>IY0r*#%x;OdJ7&^F9-Y?*MNdCMJPiz01U* zVWhsp#KAv-uL%6Qsjo4y$Jc_y}- z4@Y}UYzyMEOl-Xzj=z}L3g(<#Cboc~TgAj?$C0{{iSS8PS1_^3BBU;7Vq-hFkTJ30 zG>8er#QN~amNKy(%o|TLG4W9dxWdE)c#ocBVr`gJmN2m&x ztOB$5A|_Tk4DltHSP_(eArs3dAobCx_-u(L2yS)K&(pKFeum(pWK=A69>KlCs91C) zf(v|6vB)L_SK^{#VOUXAU}C5(g1cMMp9bb5xDFK+eP1ECU=$U-_aeBj6BXSbqHt*@ zy80rxMiTw0V?TmR8Bx(b0l@`_sA#hxxF`@6EfW!V-A6?PONio8G4C3D=!-G&Y9|EF z)%2J1t{g?+s~i>onuZ|ic2v9!D~iHQ{NrH+p`oKcy;KQ7+~uhF+dBxt8Arv79T0>E zj*7p+X!x0UegJ~dw$Y#davVYY*r<3m3qg3+sQB|G1c6VZVwoI>hrz^B+aO2<6H9i2 zXcA1k4Zed9Gx1iK>K|faF?gLHWMa{>NS(*TA~1VDz{J8Zd(UNJ2)?2BGcm9hZr3x> z-x6-WGtv7wTu*1B2d4TQCc0p%4>Qqm0jVkz?GqtP6%(!3A&e9g!M$3Y5fyWoB@-{h2nr+y@KD;Y|GIDaZuL#INA_4rAipaY!A?#NEF@UPC7Cf*uWK;!gPR z4PxRK@Y8`z+yVU^z{KtCklLS#TVc)6kBM8FA+;|PH^aMdFB3n7xxEiL|6hVaZGy7` zTLON67vE#x@n70A(*3&YcUK!{*s;msw0E-2vu?BcE#1%(x|5Vzhapbr-C$EOE>38C z!y%3CGCn&C(gvibMNcIj&~8UP@TJfa^wAjIF(br#?*Y`t#e0uW%~B3wYi%?aI7!#mCyl_*NfW|vaP;8}S&{Gv-2h(pogxOW zxzpt5pY<8xpY@rL|D)?4^ZcMYT}{v(mVih*jpK5l6YLz#Gb5*=5P$tCU4k$;8|ni1 zvd@MXK307S&op1vVwtPrSmx`$ewQD7xTD`0=w;v0XY>)xr|?n5SG0KMia4J6`U87; zc2JzVOjR7s0G$ti21#?4H)E?!S7@$zV_bc!=J7Nw4N>wXubYeCXWw!208-1 zad`&fPx*YFA}$$J-ZU+q^|V)nW4`f@IXrZuoba6hE&beIkP#|xYGX3pOl>SC@9`r~ z4#!*_fL!_^E>8~EG9vfg2=3(Fv=(FcJ;r0ha;80C%U;g#TEgds%A2Gm3Yt_%Ox;44 zoed5{+X1!o!%%LpM2Ad2k4n(FVZH3Y4L( zUt(OT33&PeT8leyn=ViWxaPEm4w&Vdqjew?wjSAR0h2a~pr=g|qHnnL1wZz%fN2Hj zvKKH($v7)@B1KQh%;a}Xes~F>eUr zHw=u8ZqowbWp6uT20mVpq0##Y|LA>U{?oimFP#5d9&wbmhJFqm3;huKCiG=!Yv|+9 zy3m`US3}Q*mV+ObdGBh;QFLY0+bEsXYMW_+@22=}`50wZN3Hd_y z;ML%z;JM(*;Njqb;NIZp;4AP^@ZI2=;7h^W;L_mY;QZkIK_xgPIMGolI3}13-UEGt z-Gd#2ZGugM^@Fv7m4ju1#e<=sJ7@{~1>OW_0zW}c!fyk+0^0(c0v`n43cMD0KCmM2 zWMCn97t9Jw4`c_@0;2-M0{sI$16=~`11$rM1Brp^;B8Pca7(}+aQLr59)t7#Q@(z_ zdwiXJ?R+hKjeK={)qLfBC45DEKA+ut6;9aCc~5!|dk=W`dO!DW_I~7j*Sp61k~i18 z)Vmn`6Ylpa-YMRRkOd*xJILF|+uhsI+s50}Ti;s?{1wW0i+e*}x7XtN%X86l#`BZs zpyyl9F3&d4Ch%W)%k!G&dCv;Zlb(f;L1C6>x+mL{<{9M~=IIaq3|&0!JuN+rJ&B&` zo(i6lo?ASAkHdY<{fGNJ_%|GJf9L+n{e}B8_XhWS?l&O&LY{k>`*HUp?z!OaFx8#m z9_t?A9_+r?-NW6<-PYaA-N0SjUBz7%{2vOrJ#MS(it9JmS=VvbA=f_FZr66#C$0}& zZ-YO?3$B%}r(BP@9&*ig&2UX}rMpJEl3W8^yz zJ1;wbb)I$}1%HXJojaXdoEx3*JJ&j2aX#yO#`%PEf%5@p*f|aSC&oEboI{*_op(F$ za^B%=?ri8xa8`AebKd4G?DRTqj=vqhJAQGTaQx`l@7Uwm;rP_C-tms(b;pa~U-7hK zk>g><9LG$@WXA+Ys$;lgprf~=o8wMLYw)+I=cwsF;{VS7mH!L>XZ{V~L-L0IWq+Q3 zng4PBBmTL5)j!pr;UDWC;UDb37kn%_`P=%N`5X9a`>XiN`fv3Y@_YPN-xc3)zO&$S zamcsNx7)Yf_lfUA-`l>`z88EeeNXuw^F8F74L%r?eCfW?zM-K%Ll+#S9mO0$hs%NN zf7&nDf3_d9|6u5pv0P&UVsv*ml6S*Y>$>v+X0>yS6p9mu$JVrMCZ% zy!Q@_s_6dzC)@i9h%`ZZ525$odoO~5gb+d?1yTrAa&ICCh|)w<5S4(6h#-Opf>gnZ z5EMiZ6)cD-pn?tkp51e2XYTH1;PbGv&*%5~J^#Et58}M$?A$45&de;c7zxDxPosQ} zath@$l#?hYP(DTZ1m!qNA<8k7qbMJv96|XAUpV#G{Nxc>rY;%1D&^QSL(- zfifKBUX)=dLs5pH3`QA*G7x0|N`I7oC|Vu*pw%0t7fMf*9w^;Wx}kJM>4MT3r4vd= zlnyBEQQD!jMQMZ58l@FVOOzHU%~6`6G(~BG(io)?N<)+eDD_d|Q0k$?qSQsHgHju% z7D`Q&8YtCKs-aXxse)1&r4mX-lzUJrpp-|s8>JjdS(Gv;rBO8 zKZKHxl82(AC@8rovr!&InT0YFWd_Q0lxZkaQF2hGpk$+Dp=6?DpiD-Ygp!VuhLVbs zf-(_hf?sm6D!EvdT&zkiRwWm!l8aTz#j50DRdTT^xmcB4tV%9cB^Rrbi&e?Rs^nr- za4DN6r5j3DlrAWpQ97Y?MCpLi9;F>hTa-2^tx;N`v_xrv(j283N>h|3D2-7Xp)^Ek zfKneN4y7JSEJ|IJIw-YKYN6Cbsew`*r5Z|Alqx8dQ7WNSM7am00!n$5yHU!altn3n zQW~X{Uz9Z{&-?HHGgKwUdB$Rfr@ZsM9?w&r%I=NsHm>(wLt&ki;<)OV;V{@Aw!2~F zSsxdFd)Fs==AT1+6;_WN+EraYyQ7A;)C(_dQVQ@lK|c^o017#5n(6Zc2Pw zQZ{V0_(GwOCLDzeF+!r4kO&)vt4_3HGZGWhA$UE_U)}%aeU%bD&Hug$*%=v$X$i^N z4}3C8&B`CJ&Y-29ka(M&uCnRbX<5EfWBs={Vw?UnB5!SdRyCha{P@WZ>&WVbrLsO*SAW&3F)|!{@H$EJZmjlE19em0OCMLn5 zCYe`RD)+bU z+OCPtmmEJi8rpMg+aUkHwIvUBXf38*#>Wk3V5Of#wo1+WzqS9k600hSkaRIb@~sj0 zG%EI}Fy+JaiWhfL6{cD2em^+1eryzSTzF#cLEHfRy0Zws?yMO80{=#Y0vTxu053Za zkVSW3{7#J30xt->HixPhyp1lcyOFAl0q}Uq?Sz8+XE{D>--v{~1=@2*1>)z9c8}Q2 zXGB4|XgqMsP8X%zzDbhK+s|vS>O3!gRcCkKzj%uUdz+N34l>RFZsafoV1kmc$Vwi_zmx zEf#~<{)P8AWa{1r;IcDy#Zhepf3hM~VFmU~d?u&@BcfUX&G)*{ID$X1ld8A^lSc9t zfWC4#R6urL$p^{!_&Opl*B-xG-cg9YyWBb+9a4?&1$5b|#yq+%bd2oFzNRW>uc$k0 z1a2P|Ww-P3XGC85AXPECG5GDkp@1&?>SLYTLxb2zzF52Ya`6|!8tl5JyMPgfsUc7U z*~3)$8ek+G@fQuID#YLI(M{o@-4Bj-yXV8{$o%L{1@StErH z`R%9*k#~>dk4-xqBgs86dkx-v?;W0%kX;|^dINIUr$H9_LR&@ai`G__cPvBU7QAe; z!?eIu!uXuAo?)w@nX5D0S~tq^jboChV$5E+7vK~b9d7X+p_pf8R$SuL_|!?Tw2GtA z3~fj*;+3?&Gt98=Gv4;Qj5jSgD}7?3@7@5o*DOLID?yP#uL8s6X%Pw=-Mmb8<22mS zHp>jp2}^Y@KGr!&ySHBV*3Q)kZCMEF9G{k+HZ3(hJ5yKil?b(|_=K$3G`MeKN+N63 z7`f4QXkb~Wz3X^cVpLmKWZ=oUpCtx-btR@Irb2p4=J@1E{;%gJiSHQ|QEn_33B4q7 z;~0zgMTh(~{ZZo17b}Vj|KSG7#bmS6F9IKJ(XAH;P`Kex;(ilW&=;{{AISxY`%SF8 zp!WKGiWvgXx8DaA?M@6-_?ygk(mzTqDiT!5Z>3i<5M77cETvacn=%Ad@_dBG?Qp*& zjhSg3yB52FyE!EeCA3UkI2!K%l(=0x zxCchycG@Tu%)JT1W}?4E=(82LnLYy#x9mo!DGLhIzuXQt`9^5gEBaz-Q>NPsa7Au} ze$HDemF*0`WxNquMcq=tTu>kG{f$t`g5TEn>CjYI?tRJMVdZ9qJpnlbEbXuKdjW8< zaTLnb2BE-E@L$a<$Nm5PzW4tY!%6$fu1x0}POGDneU9yjt(0}RWx4qab6r!Kag*Vi zp;^pKvOnA^|G)bG`L?I0L)0ab`$vNI8ngt*n9B(ZRblMq_(Ms2cnhM@(*Qh@n*cWl zXX|)G{v@BO7~S<1j}Ecisem5ISgrs)Y#)Kxh5t|$;un5bmB(+QDmj23$qTSRY-iiO&U+!NL4a{IFbo40%H9%4S9F3r7Gku z{8D$#TU%Ah0PdU!2GVcJ9VXU@=(|c#6;|PRgGs#W;X|Dqy`~;6V2RW_mr)hc7yfaD zr-z0!DZ&jW-0TyhD?w3D?^Qz*t#eP`udI1RK-4D8T^Jb5*7Q{vNtw~hHb(p%8{{dj9 zF$L-%d#4fWphbd_bITd3V%`n9Tszo|o(R0MlQ0->P&gTxU(??1d~LLteU9!$!`iAc z0oeORuyZfEZ^4)};%?eQRg7D3j&B-p!)r3&%D&+hUCjr!5q9HuRK?IctvobLaK{65 zBqz8+A9KwE0@g_UNanwyM^2%NC2tJjk@( z_?xk-VNuMPm^$z;N8*2w!>`^E;omvj6i=I5r0U)rzWxZh>iQ!>R~5eBjQ^d1*c&}! z{aeG=wAs+LDnjDpcP!zF>#3>-h$ESg63)l|jRq~Qz*66T-G)y7b(;{maM#Z~asyR$ z19Bu&--|@{g%!p@=a8PksDIJ!VE;vY2mA4Q%X#YBs_FvjNDgU5QtRFnzH%I$eC4>% z$;Zch&*RotRVUy^a!4x@H+d`^2ZwWd+@XleBM|!X2r+bw?uCJ>s_FpfP7$0ogoEZM z3_pE~pg(;p1T8%CI`7@Os%i(&NIrU81SprCf}oeOsEUEF9pQnY_1dD)dPCuXt_btl5g23YsS_tWfSz`8XL6b?<0_?KCJZ+W`(kEXigATt? zMhIPa;5FXiajI$t=;4yTJUw(^8u{HOWd3fGkoovPeqN(AQdJW$%Z_|$%;D~1{pu=^1pXVX>=XpZzjvOyR=()Cl=O+2_0!@qGZNzBCr!%9NX|-R{{WY#WU|cc z2KAcOn;Mspk__t@$W##&$9=)@_N&CSD7s;iojE=>D?S64EbzXp#I!G3B+X1$%0?&~ zO5ji5>^pdN0?*e*=$a-`!Q93%--e3GcQ6f9!9%?A3!^b6c;+`kmzjlgYH)Z6UJ;H^ zDr%9X=_5PvPH}{C--|3z3(CL~$P&95zaw?=6nJAf!3-f0IlUNn8tZnF%nbu>7>Fxo8<@EQW8B&3)PMm z`djT?5_>qUJbJ)RDJe0hS}UuFuIEnqKc%l^KGl&ZB_fnk9j=?z7NJ353Zf8+eV$e( z*IIM`mDpOf;`pUS?mzNphW_=j|I;WVu|wA?rw<~K+#3?V5L%?a%L#5cx&Mt*<8XLf zVtr|E7q-4iY25!GN4)Jls{63p?z-2x#&N+>+ddUuo%2Bc|621^a|_eM@J?A}Lsrbe zm=a{%%~$!s|AtaiRjWgEq?fD^D|aa<_d0SxnP&cw2&gb5a{P%}d?*L@`KtkJBr{NS zofiko-C&BOrQV?`CVrs?PYfG)Re@OA_A^h+zlK~;@-pIEfzyn4E<<@ATL*pl9$<)uL$bJgBS(gn;gVgt;?{3otS$7SoThg)_(_$ zR0!@~NLB3VxPc>+nzpHUSP*E!BNX&^2WMPlFdk8Ug$m?j~yX_An* z@bEC6xTUI=24dM8bhK@Ro3J9b(MVN{zgKrMq=~AQ0{lp3MC)dCK~2Pu&lZVD95b1! znEZGG?|2x`?*j5D^(6EdRG_sG7eW)45c+r%{$4Q!W=$mlTH35h?{3`@oPV^0p?_|Y zFw|=t?`3G-cSf&yhmFwq{k-Nzcd9~v7w*tC5@_BfqSw5G!#qg**Ey;}^5ZRaXA~jh zsW_0!&Un)L6(4!=m2&SCMDoDiEGn-QDB?V2F> z?^?RZ?>9*oxoYS59rmN7V$4=zKkZ%Qt>oF_e!%sME6<*2``fm}R?WK0+RO5pWrFz+ z^IY?trUFw#YNx-slfGT1Js+kt zmJm3CQ6hBiDso+go_Bi0F)^8$D1LZ z64|XGS_=Oxm=Y(U@v+CT{5#x%r?GGYvz~*o^^Z$soqHOc)m-iDxu5dOQO$qDODuQ4Ri&u z=em^2?n2_kHjyczAES3K(?z;2fCCAL683u8BNEy-pnHRXC@mypuJMxv{@DbgG?&ng z@ulfrIv`3j$(7?DCm>2w3HbrK%7wlsK$IpDhIjt!&~H%?rIO^Yk?k%JrJ{uIA?Onf z+87|pJ+S$j65&ySu0*siFt8G7C82)od)G$UpzpnT*lzeQ zB&p;6|9s-@;aTGT!d=rf+4-i^M+q%kf!P3w?)pXEQ%s9%hHs;5eR%Cwg z?tWx!U&OFAL{el$3~3wIucrN>lY*9yQ5A-Mj-9-N3!V6YTSWm_|Is06i^^2Rz;l;IP-)9KdDm zweo{2KTkpA#&`~^pt1NI*0C+sd1TmYZ3f7)_F8#l-DC%u8)?Y{jbemuKDJeN8zs28 zX_VZ|&zKOo!Cb0h2_Vbbj?%d~blQc)_3xr8CVz4+x4k2!xLt@-lukpB5RJ8%%c966eqTxcUC$KkJyDxIq?knbeMz=RvT~+G?XE#Zl zG;TUMJ24}0Hoc&x=F*xsap|wAyh|ZfE)Gy-rOHuMF2suttAF)R6%1=`jJNxC@JU6tFIuhFmiwTE@y%D#Pmd{X0oX>FV(WX2$+)Gs( zuw~s##jrzS=SY3e6I6xHK9*6Mr-nhV7EsHY%rWYq06el*uu&B=PyLQ(h6YkIDh(tw zijTN=&!H;Dp1nN?yGB&7weOMJ3P9Ylxc^^JR=odzY~CIY8`u9Y`_}(U-Cw#Jx>V;; z=iQDB`!0J4TfFsktJ^Z%yxH`dsl9Qr;VVPcm@(w#$gKDO$Nv=t8iwyR$jFT@If-M~ zF@GABq1|0-d~%BZhJ}LrzeP{qFT4({?9xY{<2IE5@Sxv;W6PfU3b8gb($`K8F*q5A^Ui! zieabk=V2kyy&J&FO3i1mVS0yN8ac}oA2;F^*7k%aFdPGe6;BcN4 z+}laId$svy825IWh|paoilLu4#6!cbR7Zf8y^W^Lc(kox1nqR1su1|t`?~X$FhT18 zz_KQ2bl=avuJ+-wL82pG8(GkCteE%wDBi&kl4}pVvO;o{*SDh9dAI!*^ltktV%oD7 zo))%7+5xSs9jIVh`dT8QwrfdMjC^oDj|`!fwty@v)DnWsGRKj&%>k-n>SMYK0AY37 z2B;&qI@Qk|La4d)bHr_}&EH##=kLc3uj8EUfMs|^LowoA=B@16?CIn_r?BF3$?v?(NhCR#%V@^b} z!$h?WK88k=p|sb@Ow7pqk8k-6MCmH+qY4-E zfryy2N(I6-MCmN8QsE*k@SadaMo|6tL>FuNAPG@AO6b~YS-SWJ><>sd-9(GxLK8%3 zACU!Ec>mFYXjB10^AgT223PCT z^~p#O%kw=p8M#RQ&sgnG?^5!jfo;@!>;HMd6pLB zopoA>zO3tJ9vyZA69GMPyMbZRwP8zZ8!XT}vmCO|EGJ}MI`ku+8A7LHfjM%a(_3H; z>{v`sK;-EOLgZy5%kan$giHYB$OR!q$okk3;!gd5st|kW;Y=PI5=_Pbw&Vm8I;kn@ z2AF~zC&K4A#qgI>cz9^q@lk8q+aC zCsiTp(!ZYJ-3xiH4*+W9@>~U|u|cOPkvC&LRWbK(y4PZ%_ZS7-l6wzrP8&QLPWl;< zC;co$UN)u+?`mktBjvYb4Vk;q8d=j5sS25wPU7z`@+Ae{56qH#JdHVAkC%$qMirz^ z7h~_!okoF6ukHiv$X$9RYSl$Qc2$sKL8qr!#PoT(E4#qyBckVYUECgVC*Ui+1rvm? z^p;(kGmvlJ(3K1a?C5kQLBW6I9#1Q>>E*&p<6QuI_hz%Lf~Z$nsDC6{eL$x-f#HHFvI(lw~l9v zr-QrDJ=XP;>mgTJ=Nr!Mj2H+e?z)&2kw~7fFz%|0nex1;bxa}Nd_Z0WwIbQ58U0)l3E!Q*scQX{gr8}{eJ(=}g3wrc*LPXL`!qyA+*8DwZvb>&CzkNrP@$!BpUr}sSPs%pK=GpBgWfbMMq8@x5 zC$DXU?sq|yNZuq@U!1?0jFmSH)JoIGTp=1GZ|D(h5D{gJ^q-O2+kqfuM6L}F+g5R{ z;{W+Z$4sq^U|eld1lxUnGVd7ccC<9eUFIP&!kfoVlQiL;;|uGISsHSM=L3|?s9~cHxPK` z4Kc8(LlE%P=mBd>bOe1`du;FNg+kz^qb~BmumO?-z>@d*sE5O?^O623Ew$mPo1``j zxSOYk4Uj27FL?t*N6&%<2)^QOs$#d#dVmLqJ|r8!qtl0Q5eH;lzJ{uhd0F|rJTv6Z zWdXC~+&RtJx|=^9uZ6si*Anygf0yTlrkxqJrX4o+fz(S^Qx(!L?ffZE4^2BGYE3&h zfP%nFDpD1KFRQM*WD&N>^u;dwbaAXQe=NC{F6L;^yySToprT}r|?%)X9q{D=_5O!WGszT^xp0zwQ z0`Nh)C zJkN9*UjAEPIAf?ClSOv^kJtNh{({n2&GWt3DQR}9zZ{vqi04nGV~OR5zeb-Q{#xks zC8c#w(Kb-?d~bC|?t%+l+XxTNU!Z;HL8LzPpqRSt1g@nh_0&AyJDrk333_VoIY2~x zN4qQS9pPPRWtTM6CC=4S^L&qUO6unH$o%!$2VO+#122jl+%4$#vAjEgww;{g9U3j) zW9+YvnER`XF>4&;+d(xo&kLB5yBv*?Y9R-uDRadM~@=&6>Php;K@JtfWqXUFYl{<^q>Fv#xCSR&??1twI+st)y$S zacZ6ms3i@}jM}%66M%-$HL~t%O;ya?LU-Dvp_=CeW=X+1#;oN8g<|j2vVeDrvw)Y@ z+ZohA9P%0nyUJNx`i0ytykiJDd&dx=vzK`4^VId#JUdWJnjSN1f3v2{tW|IS2BEiq zBZOZ3drux3hB_NSOB(7Jw69fD=0Ky~b{LVj9Tp?s(7o*g-G?MakUueUrTrq*8*T0_k<19cBM;|l+H9X`Q{jIUX#3R#z} z+0A>nu9{~8R#_nnE;E;V#uGs|X-CsGEfE9ntjz<%oXrTplICo@bLmr{NW1X`s$$v? zs`0ci#V`P^q$vhZt34-*kgt@XDu#XL7aq2bnim7GvLeh}TNoF3k`y^#ex0hA_r*7O zUYJ}E;FUDF;GGNo1D92ftS>!FRm}X9E-DUD{Mpg*F-uKH&KKNN#k{Y#;(YAzv?a%k zYl!1z?-lRY-a_vI?^f?R?-SmKz0kJ@M3C)wle1MQvcjqTO!ciF9wop8Z+%J#nPE!!)$XKatza&41sV{C(Loo!8Q z)orD0HtQeOAFQ8SKd|nyZnUnpF0v}t3~PdQu(gY|skMf+wAF6;({j;r+VY`gx8+sK zvzEmc)skr$YZ+qcYH4PvX(?lInEx{WXg*{9$o#f>lleLG5_6t8%baK)YVKxkZmwl6 zYj&FcHeE7(VLD>kW7=$b-n7(|Z^|}}GYvC!H?=U;HkC8EAamj;<5}a!#=XYZjB8w} zu2HUjuJ*15uF9?wE|c>&=eN!i&cpEP;(F)P&PSZHoN3Mnoc*00oDH2-oOe3Sj%$wZ z948&`I(B&48kZR#GEOlj8SgdrFt#+-G2U%-8~!o;Z1~b})UeO6#ZX{)+%U(GV;FB3 zZs=)fWvFW?Z}7zY8*`b4U_3^v(cetgu6moOrI@+0G*Rzj=2P>CT9TP7ejw_d%zPq? zs3n;B_*X^f0B%zQMFsBUIHa*n7jW-hQ3)yd3x zbBXF;=3Mxf?aZ8$K~x(v^9zY;WoBMFQ7z0=P7>A3%v`8~iJ7y#L^U#V*2_dSFmtAr zs4>i({tQtGGpEH8`GqcG%L@8uu|Gm ze3Y3DY7pgPX2!illq1Zn*P19FF|+RbMEQ`Jbw&{717_CxhA8hdv*sN{d5@XZpC`(@ z%&dBVD2JI@r3q0EF|!g>{~cyl>_(J>%&f46CX4neU0Rmzkw2 z5M>WD?}GZi&CHT@h_aiRCGv=}iE$*5#@DenxQdlVW#m-qP)gTLp7poW+s_VluZG%;NN0I zd6k(r;7>O)^KbamSD5+db41y|%s=2yUuNd@0Yq8P%-?<_%1g}r6FnIBk*vYeUk zjVH?E%sdQT!7^qZdXOkfnfVU5eF-xUyhxPA%-mm{D2tf6cQa8QW9A;H{-ey?y_F~n znYjzT?njup^9WHEFmuNcqReOJcKEvIF>~8tqCCvZtrdwfmzi7O_npJc*P!|jF>})r zqU1Ak;|oN|W9BPmh@vv{W$1wwX1??+93o`q3(z)ZGjr{5IE2T{HSq1vV&-$76J;hd zpM{Cv3}!x)PL%1)TzLb|6*2Sag+!Uk%%_}0$zkS-yNNP|naiPr%4X){wTP0%%%!X0 z6bLhyfa@}txd{GrGBY3j3l1|dbKzXrj%Vg0CZePGGgYe(?l7^%$d;jB{Fk*0#U{?^X@rBsTnZWP9jA4 zgPCbCc>T`I6llQLnK`j6QLZsFxjs>TV`dW6=vQWrt4ow$m^pSgQLZvGp(|0YFf;yD zqFiR?=oUoznVF+tc>0N%Bl{8M5;O0EzxyLIN3Iblm$IKk~7RE3$8@}#%W@g<3(LWz%X$iGbeO`TcMdb{s^o+nVHlB?owuEBKUb2Gskv- z%ZHgcW*{UnFmrSgQ3f+})Z-A5Vdnkc!d17-ybtDe1DH7+e(wIv9QGL8+se$LE~4~h z=3w~KKFl0c4DKXl=741os$gb+Xd6A5*>@4dw3z98)~P!)du@dKf|%Lk65Kxts|qi! zCMNG9%Af2{yN`hlB4&04Pj+Tzmx*xgA~QR|x8ISO9mm49IWyaDfjb77*{&t*kTJ6j zd{%9l*&4jjhM6tF8?BkyqB2ohF|!#swk0#0wj)XlW;TZTMssF1iXlofW;TFsvney{ z-$j%r%&fPTD2Lp4n zGb=w$l)B8U1m38_%zK_7N^NFVuo0yep8p>}ybIy}|1F;G@CIOx+vzHBHFEBA4tAV( zWIAH(OYD_wZ`uZ1uUh9>%URZ2nwsA=-)H*CG{a;wt}-?>>@^ICIUh4KrZ{@a8Od3R>>prTDw91#+Mr(3dQ;=VbtHUY z3E3GLiD?PRT4~GWRxKf2OMvqKbdN{=#JR3&w6NGfwiPUABmbd?FB21`V8JZ;_eS1~ktn?#tpS!NZ)Cz*Zz~4F+MdX%nT?sVRh9(6;NFwrsCoP1_=Yd#9 z$8^2me%H_rn9D|#)k}_85+gplF#T~ z^8ad8Dyw<5A%Z0-n_BlM59VE5A3#-@f3f7!N-qDxmsMX2FeRlLGR&~AWdEi;n(&+W z(S#-MU*M4|sd+U4xs9Ckx4@G+FquS${+dTs?AUW2o)VJuY5=9AB)tG-;CdNkysEw9 zeD#u;^>-aBBEj8*qY5dvS)G9a(qBm?r}S9#}FRr9I=a3`5f04E=TR&ZIn zsrvFwZmM?a(jOs(tSW#?N+CnfYO|y;&b@R2oqXwnur(~TJ{9ELDzcr66Rm)A&uY12 zXWc^3B{zZ|^~kF%+qv3|FpP80j6~<287X95TDk@AT*!f}1k93hAZe^pA5})q&;Ot* z24E=Rr4wUtfa%n!LT$)j&411lB(Ff>3{R?h0_$}fmqUMiV$KJX-C*kbEt}; zXE)`cA<6%4fR=Q!DFm7e*CXvGrKpOjvnKM?&{32FYRMgiHg;%%c;qacMODoE(DoqS zvhsPg?pVirO!M!tQexhu6+CYvHLnctO1c9~y!(Lu{dhT5A@{ORbfYtHmyQOv=4ss) z2J#*$O;yZ&`X}Ds(Akv&Zb_XTA8h9LL6G!A?FF3==L?CK^wM33152a3fLPMfh$q%< zrXcbM+G(2)tYYNB3xk|oGCEG?cVv+Gz427V#IgJlX@{dMsTlJ*@viXJ^X&Hwc3*ZY z?((k9_AT~-w(~X>-T+)>ZEShZGQeDD9&P%?G~Eup|)oSv4Mo{|^~8)9saEMB{WnNGdKJV60Tx;(^x@D}(j6s)_l zanEfADn;c5=IfAMe4D#(H!mjm87xR)mS1MjdpVHYe4Dqm-af5|w`W8wJ zdzTfYYiF6^iJ$*G&V7p|Cyb9zNl8pg!prBkO8hwK(k<-A`Fa!z4)eAPB)Z?`PWdgk znZC;cY4o?5NxJTLUw> zdm~bh1T(~mnL}=~QQtz3$gU8D!&VaKfZF)RT_Fsox#V~F`s;t;#F+dUOV|e_;c!|M zD(k<}mW^(2Mt+wbKW1M@F{nda7u0emX4X%O%e<`&J}fJ+vjKr;C7uY_um9P%BJZb*YT+@_n+-&&U&^_ic_*ehG_CE!7g4;n*CK5ZrHy?fI zmc-h-Uh;=yK#LB?eA#h9-|AcV02173*cMnLai`(US%cU42wbubRWW!O-A%Kw(b@*U zBeBtX3*c;sN7fRUBCxhZo{+g;SzSmJc2imdb0l_CZh@JbCm?k3;#7suy+68(Zy^wW zZUxYhh@0O6w0^RIymw5cD&+3-vF@#bmTF#0;Eu%A&$q%|L*e zgWFp~(e1iv5AwRVQ5AEa)CJL@Lun4&QR+~Ff_Mn*8cJ0N-tXB*_;%h@&1(kWNfFri zzJ>M@5(z|P$5pCA^gd_*|!SiA7 z#$Rjw0m-dD2+8}!Z{o>YsCkWnJQA;M+#-3{hp*RKFsTYuOuy)K5PhR4(uawTqR-9c zsS4@)yrR3e4fYos0(~U*7jMD$G{lOe#y6=7iTkeNufBp;sPY;Bag;_1wR!N>7 zam?tK>>??s1wNL+k~%zieHtPguUP)HBaCy=QV5 zd&B#Gg)x;$>VF&nP+-9|1pFj>!9~BF_{_|l^bFs*ZNG=sHs3_G=pWa&B)|Vf&O-_$ zXAcJGNF-;A1~v_v|AN*wYlgthnu&o6>+!%a{Tu|qvR7L4BZBQ+y0nc=NawD>U)$sz z#BcJB5Wn{*J|jhe>E}Semp%RD@cAuqByQZ9s*t?zB3(;?>E{3-mp%RD$iq)R8}35- zhP#CH{T}*)Z#J#ey#7ExS@N`k(sR?#;Al>R8pz+EhLFEcSKX!EFahlc{IVyYls|S{ zYn?>FCg~+{={^gwv*~h&BITG2&H%0cXW!d}VNLyzFRUviXwz@=b zm}2$<>PSp6Z%WO-(6qMJH;7y78zFAL?tOVD!@%AXaAgnd{&t~z3msu=-a%Ce-RIyc z9vTiY^#JHd9AXmr7&q<_u=?{<#h_kY&jvG)?f@!#2IAWS4epAo9zfu#2gJZx-FVMJ z>+KeW*6RbNc{zw#r3qCr?$60QZZkEnE8r$e9{K!R%tgFQJDH4AbT7p`**!6EgR+=pJ2x$W}*SmL1vBn8WQ6mBWnxwdDjE|FG2Rb7BJT zYnVWH0B+e6XpP%9T8E!Nm%+Ez*OvKS==DDTe8$s5^KKu#=FO#^V-qP|fvOO?UpqcH zuTWYIeeZ$(( za@ca8`6u%Xxc`2osh)91%=MTBG3CgsBq20UJmog8pwN9Zx0(H;`)|dkPD)A4jN>nV zV9!>-#iued$G8hYAe%*Z(ZpAh>&BjofNNWCGlwv&A2Tx{<1#)iD-M>^n0a|tVt!cI zz6b7UmzaMn=r;ZfhfPAiwEt0ZTG*dZJ5{4Cai=6^B#%o@h|fw+$JFvKZZnhi7Rux@ zgU{S%9@(vw26q(F%AJ<+z3UxH!(=eJ!$S@dKMw5&)DO(?ScJr*546aP#BshAJ3K`Z zg~EJU68^$YO3Z6^!kvL#!?I+wk7oKdHZiZMd%gg_tW;fqL_nI0u#tYBG z$nP3bweT!FJ|n*{8d-&>Z6uD6!9h`YIp;R7;uHOZ{?dFchs87DZJygaWOdU5wNNBH z`y;W33ymVeyF#~_7%!?B1_0r)B8k1IK6VE$AxZqD_^=y1vNXjEkuy2{NRbgUc+5%0 z5=M8b+&}Uil-Lfn^#m8Ef>)>{PI~p_`Kz}d_y2Q}N^8XW!X%WXf{ zT3GWfg_dgODW(IaQpWLy7h`^osYi1D`spda9O+4A>d=u;nIot zv@nhz(hB*9v=Z{S%+l?y!yuy8-e9(=1<9O}Bk_bDnq!6~>=@NX~fPM5tfR(oM&qeLHYkZNke*sl7 z@gM7XVrUIxCAJ3Mz4S6*#O&9Yst~t-j4mz@8H5Rd8;K0Uo3#f1nd7y6b|7t^9YWfE zhvx9kh3(QYKr3y#lxq$wV2q%>`%o1F|1g~ghK+-G0G75d#sTZ2&IsG{bE;zKO`q`4 z;N{U#@-houBWRCws$$@)W*!)JN*@4VX*;FC@o!}8_77DdYt!ZYu8ac1^eAAJHB8g% zle7RqP@orqyUw601n)Q4$U7Mlghm3m>;xeVJP<8L)Xrz93X%I>ufik42JiiVEPI2O zA_qdw$l9p^RUvb~S-MN;pvSlmn5Fd?`q&(el?CP$9rhq}hdn~*J`HqdTVYpv1VGE) zmDU`s4}K$W`$1HN+#&pRA)mWKj1_|LkT`95I@SvK1ze|mgURHA2*u<&67?DaO zgrxNK;({|o`S&)j*9zA>`1MfW&60Bxe5fmkd$c6#$s|R8eYf=ZTsS8N{buo5@nhmM z;k7i{D3yOCY)9w|)kTwtazjGsxu^oUdj2gTCafon+XB;w4|Vtf0=DoW=NY!XeDPPrucKNe7AN5m4Ed%?`RbF z>st9CrCyPcDiGrDk5W5-?T6KM{ugJMVdE~c8`UAdE&Ly$8+JtbLF&Mx)i!A0 zxe$%7HrzHDQNEXueGqPkizwekGP^uXMmT*P@>>~ML|j~++gBpWHxk^(uT1Ec5K+$K z{eP#3x1;AF_aS!)*C6K#N1@|R`@OdH)~nVQ7S;TbxuR*J@m0eghITOv$SJmo|G)d6 z;M{&bftZY}Z6NmP`?6H%tQJEt)1RR#48^o~uNfaifb(oWIxH>Ok)Qn!5J zb)FiID$WFISw|I%q7JNnkv&VhU?59;!9eRtM|gJFw3q?xvNkRB?EGv4p))&C6*|1t zhF5rK*!rFh(6Y9^8FXMBj+B!%7f%+uxYbI+(?Sis#TeQIqLmyT^@RZF|h5l~+=mFl} zunji_z-4X2g@A{Ci4)5r_r$Vd?#^zW8@|MB;FkX-;&d7U97vg5pQ@0y)u>FK7CP!I zpq1ZIYm@)rC6OQx9T&E zM~76+Nq`=;RLyXaBjk>Mm8y`xHPPK(0fT5d@XH@WwdSv1JB)6D%%fWfnOk1Z;(ZP$ z=hJ{$*2(#hPc}4$h18?8`$9&E?+a=1=1!izxtf;>^b@1?#fAjJ5PoDoszTSdI(3wX z2iK=W)AgazG^D;yYwY*EDx_~&>U)kJ*Z)U|x1XoLeaYRxHO=|9)9%0j?{`~s>uk$z zi`Cr2^oa2zqsK5P=23FwfAy+gX{qM>9$=I|bkTIK&|L!jHJ+MBwdh~t*D>2a9~R5~ z8cKUL|4zV{KXhsMHyOHCXtyx05ZuD-tHfa4wfarf{1Q+J`9qghiJ<)o^!pQ8RK@-u zc%AouD>c73pvxb+D0-Mp59EIQE2?7t0r&F!E!6yCz%PFo(D;iQ29{~wUzR1N@28`0 zuIAqX^zw%RjlPIsV5tdRztkj#?~@zkdT%scU(_(LSX;I%9xJBr^#)JhP|f!Mz5GSE z=K7HE<73y+>5pA68XHzBt!wF4Dy`LgH(<*@k43S=ZSNrXqlr|Du7Izv)L(?%Sj~4q z1>{E&v41)uQ=*j_-Ci&tF5$ zcL2Yv(*SJ3>`O=t#1iJsMb>$9i)IC1x4KLBo&@Y<*nw64PKG~uQgcT;@&kK8+7i?M0W*_6l9z;!If{ySkch0PJqk!vmPgjfk^erYb~j*}Wx?3SD&!pvv#6eVfiS z^%g;ATB!k_i*{ex-+30ZU@ zMFxHL<)wanfvrZO-Yua`vdU>&4Z4r7oYY@XD^dRomX-PoYDEV9f@LJ65QjK+Om=b# z_SU5(G#J*m;4qq868$9Ih1|8bT&&F{#<`TEQXFU!vX-jS7bbZi(uZ(D{da zRCM+3?>#(Hv*9%t145W=c-1Xo6bPv;Tk-qr>x#x_6fQ_fR3|$Wosk)rk{*ehHd%Fj zlU#od9TLv7>WiTv2%_30jHy9o`LiPYQ9YvCBrNuVilZL~o*1`EJwNMTm(T*4Q!Nta zV?niK9|hLajQ9UdAl}ZN3d@g2F~6XBMhAN+^M_r1NJy-0IIA#4jn2VG(py_+6&WL#V<_v{8h&c z(aGw-EGs&xXVyn2Uw0w+>n@>_d$*dxw+C=?wWv8cD-m7VvT0ybk%{C<8Y!j2$(j^f>4_yVw<@eCO;B}y{3%L8$UI_haFERAu z4!pZz->x!1%i6c24)%wi^)X?jeMP&W=@sz}O})-!@YIl}RtczO<*5}#%?Fkdf5T|1 zLZ|m!zmLbSrRG-zd|A2p3_lQ^M#}YCmdJW>mPoG$b?5p)LtKZQT+N?uYYuxBtuS1dEl0n(-PutHvI^6 zCF>TU!`CemJG_xKs8!z`l~x@H`y%DqI#k89S?76LXw~JS(yBva$B4V;5LGeu#L+x9 zwCb`^Y1Lr@(8&9IW2!>#p08cvxuI2;iAt*u7sW>4XOB}AgHL;i2ZuRSX#kf$QPsd{ zC>&W=Yd7Mq?jvOG<@l6mhVi8oFv}WW*s2%TMxytM`iYw2%^V7tqR2 z3DLr8!9jUsURj!I(d@oFxZxu>cHjPgMME)SOf>vz$oDSr-tF1s>EQkx?*F^yn&Y~| zx!PIJamdlf{+T_=_K)pxTby;Db-3jROP=LU^GoIyrv0Y=#7KPlf7gR{O2Tu zGRG&zr(})yB>==u&Q8oujLk_LGd>*xY4uVi#7sg;gD?VIat5~nK|3L8Cke5y&?4iL zQ+$hQqIQ(2^Z-mWyDV!KRG212KJ0;e&02b;5%AMYIauO zJyW%@go4;e5SUsLwULB5QE)+g)PblCC2X;Vlo&M5HIR@QA}BMKE;NW*UqT z#z`1X^~D5!MEu_B$uE!wy|KVp34>`+4KpVtCIp@p#!~A_7)*mo<+cNfT1V>V=-++} z#L}>awI$4pf@;V;iTh_nttnwx)s+(XBK$)`4GB38`r_!W6;Z28uNwXK z{8g(aA>}|{HEIR+iilbj_y6Y;Zx_#F?$6w@t~BRX$3Kq#_UCQaZC$KSSk76Rne$AA zrV7Rc!^<(h#k3*w|Fix7oBb`No|@kQqA0SSj^QRX7(>vVVLGz{gC}QJ6dgQ)^E4f@ z;<@07Z=1b6Aj^u-hal5m(D#KS@97#;#oU+P9`mN&6dr`c|4b@khepdINr$+ zpl=DhvI6uRuYT=~tjA7M6*E6qjAw@9(=C8m*70eM85i)#`0)X%Le`GM*72<1-{#Tr zFZbmIdgvqCL$gQP3Yj}h?8P&~21qktmbC%G`Im+g(6b*Nr7EU9)tRS_Rr8wyt*jTa zI9fg)futX#P!$q)O#Fi zv3qw3dc`@v0bt9|u+XsC+A`3s9n@YyJ}7<#xp%oIcz;9MQ+)uJpY{|29*7p9zxQje zBJUT!iri~%A&(EEUL4@d8ueJ?)npm^8fN%)fm+rKKgic15i~^JwTh}3 z{opdr;kf=^NW8s0%V5{PGOYjKfcyUj+1J>v+4@@7S*}|;!7IAQO!pWk8n(y$9n+mG zyxB_rKmKzC{OEfHQkEYB`}lEMs>-;8)YwTG=~I%&CT7r{ZC&vzem{Z={WxHc?iOp9 zWcpr!lr@PDLHC~`3osWOfy~852$=_N8O#0l3goQ}0cKfwD$O^HuS%7&L01HHsL_a$_<`;ySzZM;A7$k0Rv zNo*oKazb`SMq*k*GRN$yh|I2vV&+D(cxG_(z$m#nAsvqFWbnw2b%^X(Cq!=jK_wm; z^6v)#vaI}jotr6gtp7=zYpMckc-P7iuz?La{e+^$k}?g?pOnG_Lj)W0s*wiuDyI7 zIWM0Va(0-ZyXUp0n%@gJdr9&qp;N^>2MCf9Qn7Y31!3GGkbO-7v zMBMz_PXXEsAEJ*hd?=*tFtRf5V;CyB0j;c|g7YzMma&9eZR6>?i-`T*MKSi$lyg3Yj~qU+~P3_}>MXWd&QpGslk2PMs8JBj;-)`1#sG@DBeZ z1%Y>tCU|Nx#1eg%HL=0@>k0_|bpcxYgLv@R9csZ+Xwlo{sLL?s2YvTu-~2 zJ3n$h;JDTuYfhWr1v*}7SeT8CM_gu4o^o9CNLm{yyr8V1Ikit(aKj5LQ41?fNl$}Olwau*H6a=WXXPZPB&X{O9wQ-*C8Wk# z>64NZ;Oil3yo7sYLW@hBnw1JCG7|Jv9W5d0F{FFe^>Re*EFrTiw9NnN0Tc;0=Y;u1 zQxY?ilhX7*=mQdd(2$}b?>#diBYBKJ1W43T60TJXEi*N1lD?`VCFF63Db_bM6ZQUR z{G^$QX=9TzlE>=nd7p&iOd<80l$|-=U(pfK_%Ty6lUg*;jWWX}WI~5j(l`1iWe0sR z_ex0M4JkP&Y);f+(HLWB#G9x?qw%W-2djxXL_*W$14VqCnW%#$_>?bA7a}I=Ajy^E zqq{^MC?VNZSGmx@EKvtYm~DnH6l1DH?JxT`gaD4?al1bFQW6ThYG{z0d zOpMr-c3Md^v%HUlBG|;rKRWc5@OV5cf`_3rR)@ow<0^*-Z$!n?>j&#QW8c(c5z-f`Xsy!Uzsczb#~d0Ts% zc*?lc?`h#_=&9qW>M8HJ%j5OfJTdM+-M_ehbbsUi!hOR1vHM;3 zKKD-d>+V)fl|E8L6S^WAywneJ?Nnmfro+CAJo(A~@3+18|81>n`DT zxy=y8xbC{_y5Q{X?BZ2_Ki|2lqmTygy1IOjO+_{8xM+;p(V z@uuT7$IFfa$12Bi$77C%9g1VRBh!)MNOX*H40H5%^l)@^v~o0d#5$@w?s1fM6mvKn zM*H9P-|Roxzq5Y{Hzgdizi&Ta-(}xsf7Sk?{W<$n_NDem><`%=wCC6-*^}*K?DyFR z+xytN+S}Qi+Z)(x+pE~`wwJVf>{dIm{b9Rmy9l>0p0RyuJ7PO*+iTll+hW^bTWfp9 z_JnPbZJtfF&9G(JQf=dG57_Rt4Y2jJb+Wa#HL=yR)v#5xm9Z7KIc+BE4eK@Q&(`m) zUs+FC3#}hm4_bFy->`17zGQvg`m}YKb)j{Rb+&b?b+UDWHNkqnb%?dEwVSoQwS~2z zwT`u_wY>E%tJi9?##sKe{9^gh@{Q#S%L&WJmUk`tEITc)TVAoOv#hqPuq?LBhua`# zTCy!^mL$t)%W%s;OD{`jOB+j5OPr;qrIMwrrG&+0F`NH^n9*hP1@qVD&&|ipADZ7W zzir-b-fUiPUSnQqe%$=1d9FFvJk6Y8o@gFx9%&wG?q}|9?qF_dZe*@&u4b;_`r7rm z>$vMf*E_DaUE5uoUF%(ITq|9VyB>ATb>+IIxiVZ6U1MD%T|-^{T-{wATrFLVTyMFOuw2gnZ7lhHJvmaHN6LSU%X}73NK*1V0zZ{q-lw1 zfhpfK%QVH5ZW?cjH;ph2GW9lfF|{={Gu1cMGF3K}Gu>%&n=HnEjlUbO7=JLHGoChn z0xxSGGVU?HX?)H2va!Ip%D9{mi;);f-b9oMD9I?}QIb%`p(LV=MM*#zgA$K28s!0$ zQ79u(?nk)~WdzD_lzUNzp$tVCf-)Fo5XwN50Vw@Z`l0ki>4VZ6r58$1lpZMEQM#dY zMd^al8Ko0SN0bgI?NQpHv_)xy(i)`|N=uX$D9urtp)^Hlg3{P8>hCDmQLdr&cg7O;5W|U1RucB;3c?D$y z%F8J0QC>oM5#o4VZ6r58$1 zlpZMEQM#dYMd^al8Ko0SN0bgI?NQpHv_)xy(i)`|N=uX$D9urtp)^Hlg3=hJ5lTap z1}ODW;!x_L#G=$ise@7*r4~v}lo}}2QL3R-MX7>P8Kn|RMU;C`Dxj1{xf`V%N?DXL zD5X(Kq1@${JgiC{RwWOsl805v!>Z(ARr0VZd03S^tV$kMB@e5ThgHeLs^no+@~|p- zSd~1iN*-1v537=gRmsDuhf28H-V{TJmQlp832qx^;PC(0ivSQQnk zqGDB4tcr?NQL!p2Rz=0Cs8|&htD<66RIG}MRZ+1jDpp0ss;F2M6|16RRaC5sid9ju zDhgIb!Kx@&6$PuJU{w^Xih@;9e)rc%xsGxTx8-jy@>f1XD99OV?sXDBC8PM~~> z@(IdultPqaC`VB~Mmd7=5z2=sAE3OC@*c{&D2GuFp}d1~5aj^Mew2MEdr|hFyp6IO zWf#g@C_7PhpuCB)9pw#_Z75q&UPsx2@*2u!luanFqHIKY1!V)u%P8wnUP5^h= zzWx7W#@C4ViuY@8q4$7yt9Ko&_aF97^G@*I=k4un1MB;HymxqGJXbyEJjY=@zYX38 zT;ZALneLegEBHR1ww^doMNcu00aoni-JiJMalhey(fuT>&}X<)+#}t6-R<1kzEnUUEI5kEk0kE=e>9E+Z+rNjE^n3Q5 z_6_z`_DAirVdWfeA87AnZ)~q-zsqj5{cgKpJ7s&{_7=QK_>Ao_Tdr-gZH#S@tuw5I ztJ_N1Y}P-lKUhD9mG3U=M(b+pBCBG}fR*lGYZq%%YYl5@s~uLh7cHkPA6j->UbQ?6 zD_PZ&X&Gx7V(DsW1}oPx7KiyS^N;2;=8s^dy2<>Ud5JmCoMldgm1#F~b8{_oS+mph zH>?T2FdZ@NF>N+IZ(0g#z--ev(=bzaQwvjVSo67zH;g|S&l*2A?lr#VN_CBbwP|}- z16O5N375(F8>~f7I1fADbgp+k?R*5*o@vepoc*00oDH2-AWC6&TyuQqIO%xTvBS8= zxXk#Faf&g?c(1XCv8Az&@ouBr@Q>kV!IG&xI}-JKX4nCt!}ME#1HHx>}}OJ@G4CjqMl;rFYsUfjG0&F5%nZ9FP9?f31oP?Bh?!qz5cNZ5ZnhG2BQrN% zC+aKAe5D;xH!$<%;Y59znJ=9p>Uw6rIFhI@F>~EHqQ1z?wXKNy0yEcaCF(k6KHr$A zYnl1%BSbA==4vld*D!O{BBDOe%%}e#>T}F|Y9>*iW#)>nh`O4YPk<+%Vdmq9iMooJ z%Q_KtB{P@2MbxL6xws@zpJL`?PZ0GP1HPQ z4!)PDDl-RuPE>`N1Evr)mzn*6c{Vfqjv(rT%gnc3M%)Es7Zgz8UWW`{e8n$661&@*H)v#pJ&napgRP1Fo#w)~5z zlbP89d^L%g&EfB+GqWkQoHS-O0dJ%-vr!yTQ<&LcA5kYVv;I9qoxsd`(9DvV8QYww z~R;oqR(agLD z{_X?JEdMiP*D&+$RHBY#W?ATS?q_D1c%t6N%u?_Tj$r0pWr;eRnRiYg>b=Y?eg#qz zm{|T>`P+Wj zC}rj^Q;FJ#nU~KKwKp?=t_u5v%)B%V_VSo{F$H$onCTm0x-;{;i?CV6%x}BFW)d^c zLvPlFnO{Q()tQ-JZh#w&nR(U?Hx4uN%nG7*VCHG)zS=YMR31^=G4muiwkbuN5*@viynfd8@q8?)ACtZp94l@f65%nN5kHH-205d;cOw|3%JObas zK4yM+kf?i^`9W!-?qTM8n~3^0GvBRF)ZNTH^ej<#G4mjFs&6s#0CbEynYr(KqV8bk zUii~DnfW$!*V~!78;0XIn7OMaQU4!%=K&{G(JcC&oM#XO1VscSGb~7uyyPSxNd*Zq zyF1G+Y+?h;65VrVcR_-Jpcp|xSX2y{5Ji;FfG7qK6j2lr1rs7cG4X1q&N%y83ylzVrlQ-2Do}uas?TNI7s?WVd zq^GI+Y&Rl3Mb#}EiS(qVKJqRM@6J?x2NtMKRDF9LkvdX!7i?@gQ1#6NQ0T_j8YEIQ>-B4bRs$13&sVP;TwnJeysy=xg)U2lJ=C7clG*us;0uO{!_0eD9 z8E>j?x|2u^san~VNLNyI1N{08sQO52c!ij%>tM8BPSx->uRc}Reng~tR9yq}=rXE4 zu!Bf-sd_(*_BvF(7rr>Psk-_*cw3dKcNfB=r&L{a1Rf%#>Pq;pmr(UiGrZbK)#YjM zmL^qi2Wxn#x-3W}4^@{OC6b$}iyiP(BUKkw5Xni^3i!(os+Q-&tAtby!Pu}-Rfe%) zrE2LXM6yuzR_KD6stbJZJUCV7Jw_xWRp;7>WT5Ko2Z=#N!5aWr1TFD91LrdBgEIoTjts8sp+2LTJQYc+1fG9{=DrsTQ{q0*=?y~ z&Vc&?2IF;xd*QGC-}R>yuJ2?Cyahv(BO`akQ4Ok(I!10}Z0L}rO76{!k=Osm+{`G2 z$J(X?xTwe4C^%$X`PBq|1Z|JiQ8u*aS4SD$R97qx?)^;zU{Uw}^uW5TZKQ73P?cOW zk4~D;ni($bWD2~rqo-!FgpsxF7FF_@7du#HxRsv)%%X}P=$TQ|F0pR#cR^%-7cTOs z2m7+faJ_OWAd9+QNs;l^59IeDW$Q;&$)z3Lpc_jIgCad4gF?BZq@RAR&_%bQm5I-M zi>{0yEObF&7IjZC+QQ-Y0_eR7G;)hYs^o%?92ot^Y8rrxy2}~^9y1A>*Fx;(wfNYN z=q?O*l|re2oh|4NImNE>RvA(^%}^zmepLPA^_1>mR#+e>1HbqMQkk%E7RUxCu>%cG^1(y8!a-1{ zX%c`ZtWHxw)a^86z9L(dT=voK2ibK7N`p=Wc2T84V`geWws!k`L;a&jT>mJScvSya zSYjCF6B0Sh){N-$sh;aPB zp|KV*<(r6ciEp{Dg?F3xI?tz`9QW_;+uXHX>s@~5Hs^H^i=S>kV=uG&Y^!WnTA#9Z zvh1>qG9NJCZ2I0<%W$uu0mOBy`t$GJHihdw#hlOfD2v<`&YT)ZtV#FYQt1*d)6&TVHUr9uUp+^nEKH7heI zI4h8y2iwr3*sca+cc&1)7J4;V>2~z~4C3TMs|RS!V)cNzi7;=xT@gh51>91O`DL~0 z0kaeFV@B^qAaOxx^#J9^jI)h^90{S-1C*9yss|J&Vr8P$17;@TSB}Rfk;tW+ZNPC$h;0?g2Mp2E_VuegAp}Wn4RdQ`VI!6~nh3LRsU>6@9(AdLU93;IiN0nUSk=rk4tqr4P zP9jH3ymK&e4^bYW81f^Re^g*N%Ma0k*}yM8I-pow7abTp2hj)5sTw&P9hlUWMTP-h zlE?ubeIiHZK{i!Z%^r>pw7P<2hv>j8U>6@9P|O|YSdZ8P=Bkp5KdMrfwF3|G6a&8a z2YD3yDBl1g_jjq1i$2nOn6*5l2+RcZgndg@2LrP9U8+hh^Qc{WS!NjNMTs2g(OwE< z?sKUsx$Gl5+F5p3SPFq%{KA5+fbh zTDX^8m0avm<8*JY!pP1~$jC-)&FO-yJ&IJxWgczPJq!XR-Dd!^sFLpVEEQp$IO%#fvUk0k&wkT(c1A)zZZ5Ek&&Q3htEY2n z@h-~f?qcUsk51R6cER&aIY2Gy`KG9mqEhSa-FY$EyYpf``Hjt4d&6Vd*+4GpvFs>v zRO!n?8#*bcpH2oo^sx6C=(eZ9AOUV&j)^e@fd+WpxD(H~6Kd1yc(P)S!J{R-iCFH$Pk3&o9A8GBzw} z#qEFctZ_{LAo9xTy-Z&Pw*ZhMXk+^4a`0=JdQY6GyS?`$;iG=H(b zP(xnS7$?S}#$4p&pA9T>JE`naffGYPR$c_wo+8ztE0oz>!Jp0jUdUjf!532tphfK; zRp`jtsXhx#*UoZ$IAudQ|KXH=8AU9!Un;8!%%YCdDs$L7sv>Jv4k=Gar^$r_LtX5jZ5iB=XB_Fp^_oyz6yg#>S;DA#~|WeCRnNSsMei zF9FbMntC8VGmw%+?~BZAiqJEg@}U>&-uG+?H3tA%*nJW0t)is-U|~L8lnWK_P+=OE zwoBQotchDlWgegv^`4xTmsSvYkyM*=`JbX`^FQUoet(>WZ7!9$0d|O}JZ@@QSSU2s z8B>sT#uPqlCA&R=Cu+-Fz$$G2tz(6dR$d^I2$&zt%gv|kxysfmm%p{@@_a4U&Yh$( zC$J0K$?Dm2{293gh5jh=>e>-6N_! zr7|nv7KvX-v>O%5{M34)EiX5p#-7}Kn%{%u0j$BhOJx@5fw0&QouWz)lvx_fKfVF- zk8i-`?{cUq%MZVRIibIRHdkYNaFgPsxQXwi=<@5ys2-RS+5>II#`fTbKk+xX;ZN>w z(6#k2wg(V$HbM^)7IKb#T@IV*JSZSrFS=3PdhmdNRK(~8)g|G60eQ30 zZN*s??h`pcaXS}T$nO<7K$UGH`>DD|+)MnPwLXSX&qqGyB_$glyt9&$b2;nJ48K|6fRaL%b_J-+EfRXS-f^Ih{8+D(xrj zeQe9%#kZ!GIp%lFbxbM77Yu(G`jLgPXZ(x*H>I7WGCz1xL}eOk`$Z+uFi=#O0nZ@j z2MRNDbHEhnI(gz(RdQV@eM}7*7fNXdsjLm4i^^?^LC?$d7Ze5xi)gfXb24&oPUdna z_xgq922Xiw;1(5IshZm#$jZ`e{@8eAe{4LLz1OWfS@vd9Su0>4B*^uwu`6E`MBJo= z+cxpTZOK=C%c4ReK}$dtoJfF?LG>g{heqWjWUrjWHE-`>D_CX-8MgptQK?Ki^ZM1T zKZV|)6z^J^@0YpJX`K#xkqnDE2#f$~1m9gX}*cdn6pZnv5aGjEKw2q&1)NAzPEGgubGzC(@c_q~yBdf^rS@tA zIDAfs^5!7!+9j&wV)t(T7;9)q?rH+q!jrqg*y^;?R^l~2L|)_LBKKOF<siMq@x0 zm8hY!G@jX!@_{>4$))Z2n9jf*rLsmqE2;*ZjyA?8g~0cnS0x|(v@Ta2GEA-la8Vg1 z8o0JIMaX-VYa{p0<-#U^yoenW@cC#6u);qd%GsHE#}In;5moY`Q|@A+AzkB2fEJam z5oO`{tH#~Eko@jmT=L%g-eSoi^R@wyi%Rs4CXZP-R_#LSRlB&<$?bI`8ZvLM0BYfx zx5^-4*N&C_5O`%jE^zN-QMYr-E(c)Y`(*{VisfU)%gDasWiETK{kq(ASU&0lyYS@$ zy-V6BWqECcU0$0Dn|$ZB?0AOdqaMHtUp^F9SoHF7yOPLoJ3o;jd6;fE!;a%JfEK>v zP@p5Xa1{?d+IXpgy_ApL>z>n$tug*@C#IK8LyeysXZcq7n!*czBRvN_>F%H1^WeSo zc`gII&{xOtsH3g@Mf(uj9@|9g5$iO|Y0G@eCFb?!Rz|yFt)Vk{mjpFG0J?!yFTMb0 z9IQ#RN+K@d{Gv#%DZI=gz-5EYC=*g^>2+Z(DL<~((!T`wOSR=3T_G@6iL_Ik!?{3> zOVDWsFX5zF;M`Na{#mVGs&{sSxL`!|QRRO@0*Qd4WZEyLIOUWP;xEXYngjl=d`y&i zRpig8v|Jbrgf9}oBTNZsEWC6_8hb^6A3xfrQHN7_NJ@Z1J*LrMK>_$x!Os`WSL$`W zoRDVoXJ)1bsdp3}#uAVk6x&<2S;e^tk8p{Mnk(a$*^0w6Ujj;QM)x%@m|p-zW3&8e zfx>`4H6xfhJu;NHCg1~->koVFuZgtxLIS2vc5do)e@;<$3iLVB=<^9MaCR`#UPfkK z0TjH-oEb{H?6PY@wOqfXAM~j}oi**V3NwG~_5)1rUnc0~bq<(syrL%DNlmd~GV#L7VwN#Aa!N-lBo8r^M62%7W+V&Op(#l}&mStNdItt$EC zWq+}w1F~Ow0J(5)zDgc_Bu3^p4ylsM-Yf0TDE96NWoHk#+DiDkQb6(b94>p$3+GvO zxN_MI*hO8rj9ygWxWxDbl#L47e5X>fa_4a_f3I(Ku}uiJbp?Lm!8T>ws9OWg>aQtQ ze~oYTKAz`TtM`z~x&XDPDy`90kMAZxv+q!DS?=K9vP|AuhwT7-K(B=k2#*OVW~aUe zgnmWIHhAR@?pW!$SGS(S>ev~e6SX=eVX3Y)brBedOOMI^fg1_{H zDy!~5xM=9)1#AZ(y4(>uAUwLPj2AY#yiIwBcw57&fuT}p@3U{P!0w@y z(8ybrDn48JReX9C=$^}kteR_pU3gZFVr;z=2f<%xuS%}bdmd}a8Xbmt`vea2_?{pH ze@?0G^BljnPwz)3vK{Cpm9>Ko6pPLwWGx@ZorGO@wwo%szd>>>-6GjXDocVc%=?dY zLFbY}`Yjt($?Zk&3|;amB!RbuUL-6DJe6YLPnj7&nE(GW@s096 z>^bKd>|WwJ=xX6Ca=h;F+9%sKT2EPfS?(|&F(;W87~eHsZb&CD{||8hkWxsX4L`jo zDuFh9pi|2YYTK_txzKf8uZU~aftj}mpe3u zPWY9DhEM2?04?eh8g@korUupYfb>kJX4p@+BJfYQa)JB){yhr}*|RqQu&C_WDBzT$ z)agups~^rG@(<_u$Q$ltks)V&EFg=@Syz!GUdFJ6Y0mohqmlRf(Olksqb{(#;Gq}; zyrO(6I$ks|B|fnSiBIg|68BxDb7DbFrO`kvs-}`k9L}g#FN`AQaV3}YI6s%O-^Bf_ zfgzoG6ySIsv+A+l=dyHSI zukTLXA_3?3>j7ER`90de5X24YsE_`J!{g|0+)>=GRzG%FKz88>pca)~7(<ciXk)K5l#sILQR(I09h4N|vkd|nfQKd;FJ?$u@r<4=Yo@+ZUj z$cJaJHU<~SAV3!A0)d=ifOd$uGq*lF8yWY#rAj{Q?C~rsY~cC> ztEdeeT2`OpjhK7;s*;a8tuzX^pKx4#o;YHDuw0dV-0L1;aKrikjf}O3=>^kp<2S~6 zzD2&vy-#}kc=mhJ+~?gD?mDhYSF&@zGsE$h<90_A`!n_tw!^j(o7=kH+Sl@_WxB;~ zUT%i}2}7l!3weu7g#SUMqK<$xhN4LJo6>t)Rp(m)sg}B?Qd09v^1>VZU_R`Ki1dws zln`Bm@aRfz&NW(l#{}3Cod(Ks2)opD%s%;Az~u&AQ#pZbOzb`?pz2JVb&^PL{{IUo z$}9H#WKdYM^$QD;{v}|b>qdjlTScU=1mvw%(H@&7ek8?G+NYXRuCQ4xY3)k^No%wT z#_NaE_zM9yhnVKFa;IWDhXa<=rIb`vmM@)W*V7S#|RgX|I4C4BL`6Fg_GGFv495 zH>5gOiS&Vh?R0dv7{4fy-WO2PG^RnurAegs1djc%L78c`N3b=qDP~l@D{#e97JhAD zz9Vp8Ds3^Q+%2$Y%IdH6>}`QPQ`%yBwoAai7tcZ*e;1M7!ubC>;=9iKkmsbQulqjN zPp)px6^;XrM)rK$PMgPilVzj%jQLuK|L-=s3^$N<36B4lLd-GzBBZF8qwd^YfN8pF z*kfbu1retTNUl?5$cRRaQziTqV)!LUQ86YxvCcJtw6%7sl27f;V5uS9KMSZurTfRD z&dyB(2W&7+^{gOvO?+-?V@>{ZOM~yN!Qw-X#dN?Im1CjD_hc-0a8DQHK-O_*rw8C!tJGZZ z)|dEGbJM8zd!zdp!n=?0;SaGjPf8&)k^%6d!cTg5e_E&TztC0`7kZU9y83dFhe*0W zI|Ndv0|?y#zcz1F`>iNxgHRj;N_-`WGxqZ$j2qDjUkd60BBK> z)GDBWE};Q~=5pM66G%icsPn*!{81bteNU2)4I-(SiD!GG}|2p)1qmq-M4eQyCy zQFVPOC*wN|J2;T}Pp>NZwtY&sF@-y`lYv=O890VnaS$Wq?<-Zwg&i9FnjHv@rLsu? zn=Eu7z+qjp>3JoY^{%<%&O!t~v8ecJv^eyz&_C5kH0B-XPcOP-jbYJ3H z=W65J;T+{S=D5}2vahpuv+cFz*^JhEt*tFDTSl6XnI*H+aLiC*Fp$;N>?vh2! zX%XNw!=}{W3_VT}>A0|tDXpm|AtL?1pJ5_;BH)F?sEj)zn*~JPam1*RciALtm_(vn zg>aG!VwF4DC~R6sno_)zIIRr=5(=p0{9&(4dLR`p>0on2aC6$NrATwq1p!firgvKY z!r#JHtjI5xnHJ0`%q+}|_^gQZmw;>u>=o`~iS(y1yM=dkH1zq0urGAD9h_6)Pm1)r z&J#)nCy-vne#V58cOmPo$}Ta=W|DD!Kb6E>Zcw%8?5Ix8Tp zfHj|=hJ%Q7MnH&8*I0PP4c`zCuNaV%o{Oobr$t*-S)#Da2TX`u|X{X>mMh~#?EXwWMh&OVUwI( z*df!_vapb~Fb`nGW-Y`XS`pR%kSe*zgInuDWDvob3&^4(IA~uy`66B$EOfH54ZqOI zpm(ldEepe7j__f?9-k4mRS#8iZ93%c`7A74G@T8wqAr?hHl=59q-^noD*3c+bU9^U z+LDBrRz1igWOF6`qd7nQWAMl&tZAWK-ze-Ncf@J^GnID)w6(?Uz8%#*!+zz=JXmvcRzH76Gu>WjEHj zfv8vQS0x{LlrF;tg1m)*EGo#$js|tdqiuK^W*~9H3@-7I&bs+5bj0!8 zEXds8v?{smgHt|;8X)r1kf5 zNe7qrV2umOZFxW{_NbwpkyWn|a@OmuNmWH`Y1N z1s<}P-J;?7znJ(&!ukIzPe*r|Yp<)eGw68EVYZL4-DN#$ZEKlp{+GFy=@#SThF=Vw zNO3hB+)KMk<>B`zv#T$+2dc-@M{feDskucth3a+YKu&H>Np@~gLCkWMVMXI*SUE-; z5STaoclK8XFGKi&N>N^hnecv(>SLHy7|f5nw-n6F$}PzT-!MH~rYooS^a2ii-^Kl% zy23D>r1J1Xm7;bzVfe@?B0rdyTaX!kZ^oaJAIO2Xq9}QqGFH?0W3_)LU3zX?sk|GAz8 zyw5U&d#5%qi&}HT%;Ccj9Us~^Vv6E5nZmE=*6)oIEN@4t{8Hc*Red;?7cL>>6zXQ; zWMwZr`2v4%?3=}c`=#<)04{2urh>C$Lo@ZHWjLHCE#ngRze;yfZYP!31Y%JsZee0& zD;yVk0v0LUIAISTda15<9xNM|0JO+uL-``d8PYc^L;7a^knTT2mvjyvm>PgA@&glt z>`x081|tu2X@g|kT{uX_-Nm0Go)Pp$Wq{nsA0UG}M+18k z1+2Y2hrl;XQYF{ILmIVaEetEP2Y^Mb(0E)@EUb5|jQIjKNs+dntpowhI!*wqT4tUOND~u!VgGl!otIH=LC3B z%bgxxd09}i_x0n^?$?j!A`d>el0|MMl{)}g)RiC|vhGUI@S})3{3svyFT&!sl*;XZ zE7k?8Oh52eXvQ5j8EJ=2=F_h0$;AcKZ~h}^7tQh&Hj#`_8qxv79sKJmT=M0N_a>E2P9GIG!>M!!=`?LIXSY25?xt+WoYnP4W2I8kG=C0BHT~R%6 zk@Nb8O=^!vvD4>r@jq+45CDsHS;EPfYR?_k*7P2@TPa>~P|a%Uad5rHyGUzH67rH3bdK7#C-xcb5p7^D(XI9I8aFA?zxGvf60AP$K(8x23r; ziR=|H^K^T3)dNXnkMO1x=OK~Z0!E3xSMg6gE&+2v-!6685!o4z|JNo5iLa-(%(Kr^ z+kKPk0q0?76UQ|B7TalCcWb$2uce+j+qBjAyRolf8T{4%JO03vd*$J0C95%16?bz} zRp!=0#do`q=evc(0=Mp64hR>AUy-cFaPfZu8dgR0991YDuL_ytK?3GAx;K+LNacQD zuEr8}JZ8Ob0=diZ5%rB_hxpv-x)-G(1*Hvei%vmN21xi26@8vT`jC=X5Sq%TFVJO! z!|-mMxZxd>cP3$ll#S93KJ=sav)0J!KiMA`1pV;r*1S2C~X^D?ht4S85s z4gQIR(eu2i$MDx4JjE?{zPB&vicLyx+OhIp3M?!s! z_Wt%x_Gb3FcDwDo?K|5c+q<^ywkK?BY^#{*3Yba ztgl#~w63)-w@TImYnt^2>p<(Z))v-!R;T3;%MX^%E$>-&Se~*xWLaU6Erph#@tuw7Om6>Lmrkci?hM2mUTAQvgd5nJ>Pa3~8erVije8#xmxXM^= zEH-8s#~X(lyBpgW8yLNY3x=Onr;XQS!%bJ^ug8hJovP>R5cy@Qo(U28C93{%ipblj zda5UpU!>~E2Z_9usz3fsSAbUEmd27PUKRmwrE4-TdCS?5s?>A_3B@UJfEsf;76H9)kg56%%y6>lSH0F)hjy_ zc{WwAC?awRRqJmi@+_)ewwK7oRIPgnk!Mo1wv)(3RITM8av@bOsYT=hs(K5FoKICZ z46_+jb--WFqpEc)k#nhPI!NRksv7M?&eqh8e~%?{7FGY)P2}lR{SA6FjjCsx5IK{o zr$-PugQ}+n5_u|BfBKBb=~VsxB_ao@dIEm#G^!r2LF81bev?h)6smq*N#p=kk9vqa zg{nt_M81WpU+g6EWU3zSNaRUW{cIYMCsOs`St3uM>VZ3md^1(|8;Lxgs{3+@JdUa# zzCh%gsQLkP;YO;y2V>&~s=m96$YZIx8>ZD5s_v>s@-fZRte5j;dSXHyTRS7vKjSLe=MB3&w*DfJ)cd9;EOyq7ddK%f?m*SsVTfKs)uk|i+f((n-9&Cj)rG$iIf<$jGLhR-wd@d){ZtK2 zC2||8N;`<$nyRH;iQI~+3$_rsB~|CQAaV<;&hPU-8c5Hf>WpSYzKW{3PZPNzRdbSwd?i)078AJvRi|G`{U-Mb-4VL|#SJG+3ZkQZ?lSk?*8x;A$eTpz5TDiM*Vu;{oyxs@@0_=XR=&h3+q- z>L{3HOQ||yFp-x~b>O2!UQE?~@EhGm)!qk*yojnjVD2xZY8P1QE2!EDzTM?iZ4VQ+ zjH*c=6FEfHw#|twQ?(5YQAtxb4hK6ss5)#iq)AeBD45+w)gjQ3m8ye|5ZOZ2fhkZ^ zn5zAuArn>m{zPOWReL{4WCK;(e@$dU)pj{Vx$WfSR3DZ7dP#996H{Po%R{ZI}U-DXH4vG?7kI z6}D>9FI26+mq@3mTCX=0NTh0=^F%sH)!GY)^b=KU?SvYDRIO=%!hBS%5rVpTRQ0|C zHSMVCK1QSyRCV=*+TB!jY=!#TRJDU~zM-nMkVwaP6Mx>)uC2QdcX-$O( zNQiWVs(&pe(w9{I(@Uf;sQUX#A|0mc`IS_32 zK1kJ5i-`0IRey$|@-bC^x)mONrRopo;AK{-em@#sPo?UKJw)0^)#JV35mKst1ON3y zsvd&^m>*E}=x^}SCRM+x2hU)J)L1s9~RMd(ir& zwV7qA`FXR!G|0HnaKLai{N;c1Pbs*01|-1Eqol*c3z$5uL>!(r@qHw>%Z!f%9w035 zp8$uN%AFrfr&qY2RGtfalJ{H~IMn9mMG^N)AhD7)gZ`(@PpOh`<2v~)F?j0x0D@$qfPSbXr*_W^v-o_ZaAbm;Zb+mQUx+xX<|buoDez4iuj(Rnf| zIn6#o*vg}-TGXw`1RC*>56}`BuRiX=!gmkNARYPS9FmGjxC6?^M% z3E!dq?Crwvm$Mu2iw;Gp{Qh)5y)FA-FYahQ8gHprO|7dJyJ{ZduA0Zk-Mov%g%5itz!m*ruc~6~ zO2x)2ZG7lkX0y;&OXVE_x}V?$53X8hvu=e_LT^P8AGGs3EGXep5l8>9GOTWBUDsK-(=K4*&KjHAL)-@eA)3|sE1per4kjQ$t`#_1wbXwaMI|8C*SA z<+!Z{3kouGBX6R}gZ`WL56%i?=Vb*8lG?ZJ+;&zH6hAA-%?kQ?&8gD~1}B8e(k(C- zMBWyTG}B7pI8pMd`&U^(aVbm~8>yhnO#i+HhQ-2c%DkUmCI%cLgM8 zh;K~wG(hTyz`aehlK?VHs^^`uxYIJyT6nn9^F8FQR8PsEsvA_F4wX9#T;XC*)sT0S zYJr2XnAv~_Vo2r@xQgn}vXChx@Rwqbp^$`BJx@2r9TQcaAR*aF;Ko-w{6P|xz;PIR zy&1B!1RhuP?L|K9Z3R}tQJRb1g!%=3@RTOQ%U1M#V903`|5Gwoc_C>Iz)3b5|g>fvt--z`4jePp<^;mi+ zS2_;ptFiX3ZrP5Z59SnQ$ARCc#OwC)<8>v^Y+>QS^fx8a^mrvGcCdf=0-FBA7x<@EH_^U$oH1`v)};`-2*M?B}0nv3p46Hvo1)!mtB{!Enek z&Zv1$i6y+pk0q4M*u!=JZU&Eq4v4xL9Ao#?T&U%zuk`-zF0}l+yZDyB?MW6KR`)Rg zp0L$DB^Mlzft)yo-~Ao(@BWU@pQ0<34Kb0?z%MGIr+7+}W(M*z11aD^)du>mdWgHL z9v651L%K5AEu`{MfP0;wfgYF%U(bm3-V|(^*`oLOud; zhbLe(q-O=DYQtg2Fr?ivj8FT~y(}%nONRrkuy`pm9MS_bGhym!z}uCVE4M$v2R>BD z0z>$G7yt_kpEJM^T}aC;^rr^$(=_OplhDd9C-I>_^s&%j&=!6PEF(bo8CyR?)~%m$S!dn%8OsWv=^?->>NBmr zSr$JgiNG(6P$d_9-qRCVaL5oE4B(3GwC~w*+W@bXH2)m_Jm3-*rbqqAd|6eDja#Ky?W4@KX ztG!#j*L#k6W_fD3H@I87UT}4XyXPYvpEz!@|7$OZ zsOA*^gTJT%Kj?5%Sb)P@->7c;4tJ3SI5(?mkm=`C0j?^2v+S`JE>(+grbd4r;9ju6 zEQ0teJ6t{%7?Fuyl;Li3^}KXYg;xdLo3M?6d+$PLyW&U9%t414+^e5q0oO(KhDYdt zRGQPRFR22?N=%DUvpq$CH$0|I{mcsp9Wa<$6B#g5gsx;t4o^{jmd<|wRTKn7^QlRd zW(&X{oijD6<;e>yrE`Q0S*7LtpzIYVo<}eadpf{g_t47iw~FWT|n0N~0YuY_#)HZ_Hp( zAr6oQsG_1RI#kUk6aj_OdaC3DADj>cJUwB+>INM_|4{Bt{lULCRg!!)3k(kGX#gzB zL9Ms2y5Om!V&iX{k^Q&Ld?SZ;v&^tcX9BbMRXXB{jdqP9@!2M-vJwA_ovP&HcX*A(?=6*20{l6`H`NM$mELfKKipB3{7$sHk?jP$kTMZE zA?k&cnBO4ErH;s-O;aTweZ?0HdN}^y&{&uF7W=O7KIQH2Iqb=DpLI)akL!My-}##J zX2%zf>GqTMd3LjHiLI7(wY9P3VM`0BbwAj2&=fTOV!YK@*Ramej=Vx{AmEpTV2S`Q zPYhOT;;!w_jm5*i{_k|m-)&+yEG&=9efqY)=We5=q9vC?vtA4PaVLTHFs zX+P?F1}{|z4K}H*#tjkA6B@!)nvNH(TCp9s7|U76}NJ>6=jl9`I0& zfNyG4TM^H6MY@Hsj(q=5K8EDkAz6*{n!6g zvU)iFUz_YEzMPMh~uTQlS7qU2h7}kx@&wLqzVgQi}LWsV6$ga4xC7*qC7R%mE zsvy8F-kq+nSLIHxY|#esTePVf|4ho(LsQ;n@xh(G0Pw}T(-r(GJqHNiY>_If?gUhg zF9|-zb^_e#^Pv;s-RVjvqTCONeDyD?>ZTi13XYi%c=wPF!#Ye)wz z1Xl6spb;;GE-Sm1aww|h-~;c`U8RTAr~&{MwMVC;Is#0+ZfM*~l#J|4{vjj#THX2$ zIg0tfEIvmu!mO@;G^yEJi1gkJ0Y+Pjc+;AoQ<^S%V@LBN+Fpa21iXOStRhA8BqgCc$b%e?} zrCjUGJ*7Lzz-i!e02g%{;DGz}$Hw9d*p1=~eEdTvm>;*axl~af@I|dr6koSS6)N9@ zLjLz)?jBv~n)XsfJ%Q6l&#Gm0(CIS+AEK+Aag=Z24Z3QDKz&)_s0)Me5CiNWD0S}7 zI4*L3=2QQW&W?-DQbk>$7InaivUNdTFf}thGc^#-X`$#jUPRCF^3jhy!J@a5D(V2b zsJ!GT^!%cnaHT&AJ>7uN(+zy+?LV>5;F_!r(4scSQP7%)k7B3KMeOvseC&0)2d}_2 zc`0CvcTM6KO6}5m{)I}X?ZVZ7SV#*0s@=g4dlSKt* zWKBR7wb9X`YKxw>n+#ly%z>-<%+KqdRBR(vTmsCZc9VK$HTHv`lO9$jANY*UDFa5X zkuW2xYqVzM@ye%r{6BoUUpvAMj80O8512*W)zKSS)wD<(TKPu28C7{B|7O(OH*`<9 z!3ymKa`7v4IE1FHb(*=yjz{>hOx3TGZxUH82*}j1$Tjg?a0hqxgC2 zb5H1QW5D**4bqtseb%ZKR*o2qMjtVlZ}iFotkEH=;R1Y7Q4MNz zEoT@h2R^DwKJCG_EG>M*oj@!8Bd%P0)uy9=@V-NncLKzH_skGKP{#ec*V?ARIE zTe)r9n}6GO?#Ygj2?XfI4jA~m#Mm1*PY71W% zyct#5g?}?@?twIhHk|)|m9aiCu+h+&{0nXX5V!*%pqyDoFpyQ4 zkrZBsW)uaBf;6q>aRCWLF|BD!30RxRj|s@kifIyuWq2!0yZ*jAzY? zk>8O{IQDx&R#Sudg?PeOau+KF)J%zKHR2(|39@mT zrF2v^XSy-%1+nO}sz)k6aEEvM!O@-k**CBauOza-M7 zwE}FXwvt^`81d3Y8d@WuA-WKwt3J}ug90*RqZ?wKA4GmYKr((zi}V8*>E-=Gzo;>h z4=sQ|hjcPxlPd+R)wD@;3={cI0iRV}E82{REHNttq{r)< zQ{AydUM{?A>fDQT?G6E#Q}kU^HO&c1(}JU6-zyQjL2yE2@AI_Eo`j%AJ-_O`O*A?7>G4GixaCX#PS7W@ymM19ceZ%KX)cP=@@>8g_L)KCJP1hliBeqT?YS4Y9K4pXl-b;RrPEYQ?oMZ?+QJe z2CtN%%Y1q;viX%BhQ^v#&xKW8W7Me1Mrvkm4*at4gHrQK5;WdKXyeMo`oiMOtjt_} z<0;ViRn_BJ)AgMBZS|ftsSmW6FJJ(x3oZV#jGLR3oq;BEFYY52cg|?Ot;n3w?s%1b z1np%B=wg-c%aF2Xp~=jPI|{_@qS~Y~gu)A<`a}$rqe?@^Oxc~#diuqUBDM8Eej%N# zxCA_q)Ak%Bf6|T zv^zP)QrhR=_d~^Pmrl^|a$9x@G&AwycIa`Np|dj14n6cUv^wtMcIk0jr4uvKD$OpA z{Fb2)pxGO%XFbpjSGN8#Qx7@x6tp+CdM2m7J>~5tWpd_aaoov<+`Jxkd=s?iL0E*#${T+u6bF6xgi6Lllwz4u>{}U7WR*GVXre zO9k4_L1`BLV@7W7bbmqS)SN(JQGUcV7-|iz4;E1GU2C0&8baZ{?*IYCC+M1_bhR)z zs}SCn%uLm79^~(!{k{Twn4 zvpp{EOAxnNx>UxC9YgsnXt&$NZNuZXtMx9ji=k^}q_Y{&XqSuI%EWC{-B&0Bj6Rh| z!()4YH1+oWTvN}n{mybj;%qD67L_;~ zV``cfg|wT$Qzf5zh%UPttlct^*4B1znzc8cLGF!b_}qMBmVzkKX-7cA!97cymA(l@=a@u4M-y?0S5)zH&YP)%rQDXR^?(rHW<%Jxb6e zUj~|{7$NUNqg2T?^6Xb0V0mG&ZVJ2!*ox@$l#um)lPdYlNAF^p;gaIjz%1&LB4cAr zc0$J0?NrHSos&F$2?qQbi-6y+QnpV{^BVblDfG)ay;2~pwgXbUliD;3H9_i7 z6YemWd!!3X3y0SRKr8-wh~kK0;%11u;CEH>vCp?=up{~ZhF^*4CDUNzr^e~NrM`OJ zN4%XquX`rAzjH5e*L6MX8s+@fIm>BvEO#`qKWiUod*3$2`kgh;a^A8SY6Gq_w*kMv zTzDC9InN&u6F0TM-HzDWlma|h+DRx$byDW$Wv0Tj z!PKtp*$f)_bpg@7m`;WlfvH7NA*g@RR5ZvI%gUWz(C(sNc8+N|JvCeZqwW;2=*6@e ziReat)z=d7s|NCN3iQ2vRlv}Vv=;QZtq2 zUJ=~6)Lf`BlCQS5T|kT7Reg)>cOyM}M!@W4dWIWozzC<%;Cit|!0e4_QH^pE z`Dp>CmH5r60ZJl2m54TVu|*<3DIk?1rk~pGAu@KJ!1({{aQ(mgJwJGo-FLfAx_Ud8 zIQBa(w`agje}i>^Wx4r)xvpt~vC?oHZu!sVo$~+d|E(0NgbxOXNv0rApVm?J)L#&F zw1{|1HaSyO$@QAdPu|RUO-jK_ISANAc`4(thi4v=+CNk!pSVs}mbklAF%XDFm0OJ^ zj&sOCZtH1P^7*ek%ko1=cL4B<3hBo1D<>sHwO}pnO_niLBZq6TryO9BVSx8f*hMWY>@k5o$0F(kh-ne7;zf zTr99e=AH>MGkc;&)L)OQl8apOy)N?!O7QgnWKkvfbY_k{mLu`GI;!N8A6>%^ z5Qs%}2XaxdsQBb~wnyAEAyx9Rf6>);g>l_2QRA9*5FqO>r&P&j{wc_sx|LMX6_~FV zw2Rf78odmNd8(%>`MBqF=~_*siY|cLM=UP7DvbAP_ z$G?&D$G^Fpv)|J_RntPM=nS0K39={U^eavig!}Y1>^we~Zb=~Fs!r9D`Z-3o>iEWZ~qvf2Xr+K02 zJ=0~ziH7y$XVNut#t$d!Plj%a`o_?GY9s_u7!KL1MgJoG-PG?HRdV|~|FVyn{)UtF zCjqwj?KNUYZmrO>dtWy)_jU7`d;HBZL$>NfU>21+9%X78x2N36ZyC;q za4eVr+~Pev5nEGk{W$441KE4d;Isd+iDiei=Vo9Rwf02WTn&;^i(iYgdDFH0**yP- zrYtpVS;qsls4Z(1)Ove&`V{Tm=~J$~=Z~z*l0$m%I3O359vnrEY9zvkupKbxYf}e) z&e#0mx&aQCQEmcgQ8jAgL+h>W-+~?RZ{b>d-gyseZ7AV>BY=x4;ZDKBHD@Agx4O^T z)cPs}ZhaLOc>bU_SYVirHvq8s=@$x; z#@qxqU7MOL<1SKUels`m2G?aO$AvcB~ z8{J6RFj1%gOrb*I+&}H<-_79(^Cn3=7>zU>3j7Da>(Z;N{OD z_~p-W!RMXRJz)a7)awCU{4P}ikC}w^@C}7c^>%Zy=Ua6S)vi*-2*A!3bgZN!T1ioj zt#*XQu8UWFHr3@{^_kyjAv;=tet073W6LEW{iR>4l5hKN<5_x`pTmG&{GzR<2P@gg z$a={RRq~kwx?$c!s<;lAMLlB~GhX7BnLzLwcprIFjhfsJ%=^11Yjg-t4uuXREIe5l zr%na(d#_L>mw$en0W3c(kVAl9`~s;Anm7xjdo+T(NAtm(uyIwV^B8GpI7_^1z3q*8 zo=Q(=_fGd1=Uk`PvBuHXzSBO!cG#9_{moix^;*_g{N^3z!KQR zn~Q((;5(s7&RW~?3c;KZ`tzy_YMh^UkI=+prO$DK*hD@mH1SwzIV%247=EO$FN(5$X^IZw2Rl8dcY_0VWGcbl!ubYp9@Gpi|Qc# zZlO&-6FP9J@Cy?8kbrE^sGh1P0qp0e0`j`6Xpjz{g97TgMKy}5k}Cg+fTYRz?a@Ad zTs?)LbZNG$oqxP|0t&skv|f;oQ9iIhD&5Q-6tSHn*MT{tA@yX zy^V;M?lKdx`-y+W>l>l=Rlbti6|ZALmsWMl6LZDuYoTK{%BMx-4~4Ed@!U~F{y^wP zAl8#a6Vc=6Z@eIi9JWDW373(Vpu( z{XIQBojpmO7M@0)`kq=Ix5wiC+x@HiXZH!$FxLQAFW0rMcCMDL#;(gXOczUq9@xyAXIbG`Ec=UvX*oeQ0%&e_faXO=VQob0^GInp`A z+1J_K+0p5DHgh&~Ugo^S>2#VLe>%=OesX;4_|kFEvDfjA<8{Y&$McRS9hHuU9QQiz zbS!a{Ip#Zx9eIvSM~Y*DW2|GiW1u71(Z$i;(aO=pafPF{!|Sj)i2c0%7yI}2ukD}P z57^(g@3OyU-)4Wt{-qzmS zewDqRy{6q|H{1TQowJ>^9k(5^eQMihd)M}c?G@V#wx?{HY!BP+v#qo(wUyfz*k;*g z*rwT1Z4+%b*hbg}*?QZ$+ODy+wq0#&V5?*E+3auwkrmr*2C71tshw5w(hjP zWPR4U*}B2H#=6?N+e*mai;_EFW3+Sl+bkuxzzFZF$tP&T_wHm1UWw!g8yn#FB5BZb`FDvfOC7 z-ZI$I$I{Kx!P3Uk)N-Z!EB7JyNA5lDH{CnjTis8)A9b&D-|t@KUIs5!-s&!K=ewu7 z)7+EXH@dHP4|ex)cXM}ew{bUhU+J#vuHkmLjjlgjXIwwJzHxow`o#62Yq#rPu9scU zxt?%sbggyW<67Zb>t@#&?+i;_OAU*|Vl@9@K4bpT{Ehhw^C#vH z&AZM2GQVto&isUVqj|0Q9`g$GVspqm&pgwdYtAqS%r~3In1`7Mn0uM8HMcXjG&eS1 zZobs)F%>xV7iMCtBIIM=yw$7QT&GD zR}|+^oJDa4#c343pg4u%XA~z<{Dk616hEN&9>sSkPM|oB;#(Bopg4x&YZOOOe1+l& ziZ4-of#NWV&ry7a;t+~YQ5;0^35t(V96+%j#YZUiq1cP!LlhsNcpt@kDE6Ru7sWd$ zcB6P3#V!U% z!id6vf<%OT0ma`a{zCC5ia${Nj^aFu-%$LD;v9;zD9)fbjp7#+r%?Qi;v|ZnQ2dDE z2Nd6<_zuMh6vt6~i{cv;$54EY;wXx*P#i(=C5kUl97gduiqB9SLh&hzgD5^h@iB@6 zDE6cH2*o}Wdr^Fd;sX@#qj(R+9u)7Qcn8I96mO&0h2kv~Z=!eu#p@{kg<>a)*HFBQ zVh4&>P;5u>GK!Z_Y(w!PimfPKK=C|^=TJP0;u#cMP&|#|DHKnlcml;{6py2L48@}; zHle6Qu@S`v6puti2)h!(u7t2FA?!*ByAr~#gs>|i>`Dl`62h*8uqz?#N(j3W!mfm{ zD|i>`Dl`62h*8uqz?#N=WI-dhF3U6c3|#2*p|y zYfwCh;sF%*qqq;ny(sQMu^PqQDDFbB3dKqkccNH8OP#;(ZN6&brCV^?JCii};6u`4omMaHhk*cBPOB4bx% z?23$Ck+CZ>c16an$k-JbyCP#(WbBHJU6GZpRA7(FQIw$wp^#BXC`wV>iedqZ`6%Y0 zn2TZ#irFYiP|QM6jAAB=A{2!v3Q**un1Lb>MJ|dQ6xk6GQs#RW{>$korlH70k%3|= zigXk~6lo|@QKX;LqZp539EzJz+=$`^6k}10K`|P|C=?@6 zT#sS|is2}Rp|}pkP!vN@3`Q{s#XuATQ1nO94@F-TeNgm9k&L1jik>KXpy-aG8;Y(d zx}dlgMQ0S9!ukKT$$H`&?p^Nr+|$^d>e}c$~GqwwgJ}VmVK7m<}s$_#t)4? z!xZ?d3I7wW6i@)k6~gk!wG!`c))HCr0x5xlpkM2W zX7HKUU=L{n;KsCQ%;rKv*VGOb>GW8My@z+ED+4#$R|n@)usu=db-M%MZUm zZbE;7^vwKV6~93KJnTXKJbn)@|0SviISK87He+LdgS^(*gS^)K9yFTG_5czXv!Ms# z(=QcwY^>)UsdJQM-JE|&)}7iTiaslm^i`!_X1$2L$a;}$`}vMOEIp)OP6vAN>6eP_ z_36>m@DlK*X{Y$i*Xq)vA^mb1FpE#WRGH%?cA>E|ln!M4LkDVnz#1JE%}nTkutigQ zvR3OrY<3v(-?B@U{2w5xJKj}F@)^W@7^$!8x|k7b8iLQ{cVd@Uix z_89v?(h28O$tQMgXNh67q$hH;#EYgQ_l+b~YL*|axCDV;{1q3);<{QwV+kUU zB~>GbYYC+lv&b;O(-Jwr_~@&6t^(PCI-@RJwGNasNTIbD!QIW77f_>f0H+K;ZG$WZnd z2D9_B0)_ZstXn`;RIN?z^iD!90co32?S$XU4cGGwC*p;i0&-KM+k;Jq-k1)d8BNMk z8hfrH@{aTdy=SZZ_OWLUMeur1}k1eB;|8>8iP{}lMEDY=Wf zp8X-PJ!QV>+WTF=H%N0V6(r>c3-cqBO+GK+d%!dl{>Dd!#&78scpWYFshlL$??wM1 zEjP6wDL5+tU#(z4Qv0@@+s;agTT`5A2Zmy#nO{ZZJE~66f{1Iqph$7{YOZx6pA+!) z(f7`;cxahM&x-G>=2m5zJtMwZbxhFc1(8n+SX&qq)2)mAOYDWti+^Q3h^s6rCoOi&e>Wp3GkV9qaFD zFD(bPEB5Om$0s^kM#7O=qAN(-$3 zEGoJa4IJ|gN9MIYRr1-d+rhH8kQQ2iT~vWsja}OaAmjsis^r7wHe_MjNej&YE2;=z z6fEO}LfF+)RLO^)yqAT(Mp|eBXi+7eqM_L>3F6-Mf-3pg{dC2yVeK#iw(zw>*)zwi z9ji=8y~@O=p86?kY*;%CKrMXjP^j6p<4&x3yy?z=sCoSSJ1lTpX(0h%Q7-xD(V;rW z(6-ChsFH8v#n-dQPzrMaAPb&_aXf4Yd;3?a>TT+L)K+u zRmo=#En%4<@;(okMMd6K<|tnuk}i2om3-og=`1m16V3%|2Omhho(_p{JY z0<#35g_Xdhr)1UtiIinZRmL)YRmKvl?kfUS^Jf9As7;Y}fQ5%%(TR$%A$)CRQ|KRF zTdCKWHEnaLq8MO@h);<{Pb{)ZEmX-J1|{x1mKB2MGl5mqPMI-mcu|XW=OXj1T~*0v z_pN8yp>}l_UwmO1YUqTg7?4;{W+d2&m_+XPqL>S+{mx# zF}csUkGT)H--5f_o80%h7rW=eP5b+uOP%wbxy~uhQE;=qgY#-@30mm}O0=PLJaEx~Jb98hxb<}a#AV1-R{Zsop_LuFO;b#2p_FL^U>?!s!_Wp1a zzL~wQ-EKQ?`_6UkuzYTL4{oYIWqHW5!XjG=EkU@MKFHF=($Z4j z;xhjUcft>w-#5Q%e%k!7`A)b4USv);-(((a?rLrYcfQ@Gzf3=wzJR=m*Gya7+3v}3 zH@&yJy}PlymfP$)3wO~!cI|S#=z7$3pKA%+Jh&G=2%UGjQjTy%A#-YaU z#x}+VMz7(5;b+xn<2BiE-~Z?X3rOe=s^0G+q1&l?Z%-0hM%C2^NoXlm?;b-!OQ^bP zBMB|0>dLkxbQ@JytS6yGR9)Vggcefu_U$B8LDgl~kWe{QmsFBa8C4h8A)yde7tJ9d znW_tGl8{8z^7~1sl&WP7N$6Ip%J5$o{2%t-J5H*idGzj`oQEWcWRUETGe{65Nsug= zO~Aq?c4q^ygq=NSWfuhl7*S9W1Xh$}KoJ#D6bTX(5JW%)K}5uepl{98In#Y+W*hEh zd+z=G?)&^xPodJ^uIcX6T~%F8RUiDfbE!JtOQbneoqLK%c~qSIzK zDk9CKYA)R5&!uYia3bYU)%y*RvZ9&DH<1QYwRQ=S22r)<<3t)r)#|SkX#iEL)gjV-RIOS} zr2bT`vVutcs9L!mk@`}#(i$T5p=w1Jk$O|Ld@hmhrK-CHk$O?pv7bmiscJh+q?di6sh zb)@Rwt%=lus(-#gr1n((Lr0``RK4;ek=j!A*Ek}zq3SO$5UDj)FPVwdimDgq6R9Ot ze}aG7f~x1?_iawqb8iu;8CB2LCz6M%-@inpyQunIRU$Q|>gmNqYC_dhMj|z)>Pc8t z8d3GcRw6Z|>hY#TYCzRvFgEH_^(f52JE{5={8ja+diWfX>QeO(^r#M14@@LdZL047 zf=IQfy3a$TnpEBM43TP3b@vZMs!r9Z)EuvQYIUSQ*SzUEwB@iK@?~ z6Uj)`r{HfkQ1yv7iKM6MQazD$RDFCHkz%O&=yFImqUz$)kPSrDMZ-zKzf^tb1IVYL z>cZBf;2KqnR*-^!sQTbTq~I!5mZzQt%g5eT_)LpH!XS5%L$PI(Gpn_?@b= zUn2#-QFWFXBJots`G*wzO4aOE{s6Z6bzb8g3^7NlX3QZ4m#CWFlob3-)zrC=)<)Ij zw;@PI)oGVW!3C;L1@$~tC+;EzKT>tV?NEV=s$>5k1!t)`@&GCLfvUp^DfphMLtZ5X z-%)iCnEeb@`|p6Nv{dc;FI0`CYM&uc&6TS64uW#4RPDJ5YN1l~9tYGa4XSHX;ggy{ z)#R^)r@3SZ|DL3K^HouuG6Rqvhw6bv;sWgsRX` z!BOZhBZl~(s zIi%n{s{VP76l|mFAC*bLyHx#6A_ebI_1DX!U@KKGLx}lps$P1Y6ud>%i?D9IN!6dA zgKtpvJp7l&q zrY8k2Q}wA9q+lggm%Ky@UZUz__mF}Ysk-PSDR=?n|09X}KG*Y5ZLhsUvhT51v(2!6 zV0Bm?Fu!WLZ0cy7Yxvke^mps>Vs^xs$w>7qS-Q-JFi|b=hzJi8DS6&(m}vhO=my#U z1=kHStE3U*27wX-3u+2<;RM4(3UDbQ=6xPy-{;}8cN)vGxA85g0qmmQo(N@+&GJt5 zWO`%0S^hL>1m5$ED*50I^elK6--7A@F6!EBWN^63nUt2A=}AsXNutFacK?7K*!=^) z11t8h9q8&?Pz^eeBgi!zu>v>OfPnA#$N2&%Nin z9{U5!4J&hUco2c&}2L-1w{O{~W;u;rpE`NS=2vc!-I=LTZosc?bd zul7bK;%>65l8^nUreF=^Xt@Aec#f7ITb*{nm3V{lt{7-)a|zn1Pc zq93jMMdx!ba@TRa>l)%b<;-w8psspddx^cH?M+)psAk{Ka=3lJQo4Gm+P;@VE{ph5(t!>s5+d zfPMua0w>_by5M-%w&%%Anvx3V`3$sZQ*rm6Gu5n9Z(=Ooj&CCJ#(Kzt4?!^jcY}jQ zrE4{W+x}0~r-;Ju=Fff)Oozq-uI&absSMAMn>r9#7I}kHZ4@0ua9T^u@cK8q5W$X0 zvl-b*@rm?|3z2dG*B!%5oX9q-98n=EFY?lxVrXV3262A@@1chFH9avS6P!)So`hI$ ztS5eIVm#JAsTYNnJ&8eSpY_H-pBe)_38qx0!!KNxC7{QAus43XX2gYJ~k$YQ`_r})wmQ}+mMs>&xtD1%yw=v*AnA|jo9I$w-ifi1 zQOqg7wEvqAF1@zk3lZhg^G7~orzEPbkhrY)>46^%eN0z=R3+CFGCTDW;|cNSEVKb+ zQ8^1LvU2Zha#Fy5fuO&}sge&ofv~_}u@o<6mAtLkBTtrCWC*^s0%U=~ zH}DWC+aqHe9hCkJT#Yl`BCL&l#J%l>o&%T~0ptWA6inggrATdlyV zToTpbp6`v==X>)_>(&fnz-=ZRSDAGh+;fWa|J)6n|K|Fvb-{=30bJoebewjSI!*zaFbB_DdxI2O8-Z$VRl7FFOnxV_UtYrM9I z{hgA8^4$%RP?}9(@gdIH1n`B&ITd`x^^3%(7pszQ@V?hVh#NgR^U@_YRpnYN@_izj#f%)WS2C8f2B;n!$%n32k+nLkj&%S!TB~D-a~z2eDSN>~H`oi#JalFM3^SiG&o#SDYfN3>755CI&G4+D1LOd_9MhTXCzCWT zfph`xr>snfX{c!cu^Cg+Qd{}|2qr#UX%^sq^6yuIaqIMq#L4J>8Z02gLDN)fYzoHX z2MI8urX@P60!ADt!2eoGdu+IKfB=KyF;#o?gPYL8TGF1{;F9(K)Z~;nV}6e^_Pyc| z2|CK}6W}PPO?c>-$LZW(z%Ru#mz*{Q+vyi;%?6Q6ju!K` zLw}#Zn$%l>vmYA^rv5>#31JJZvI2#4s+X`%;W`wsTu))0QWm?APTeCQ*suD|mA$^= zJBI=v0+Po<+6ub8p?-*f&4t=p!0+qt7p@ZB1k5c>Q`jwRtgC>}q1u>#Dyx+Qp{R<0 z^gFht;K1l2aA5emmHpxMC>_e{f*76F4xHwir{k71%Rn^$+%}jliBMZ81G-E#QoT zhXv&u;}5)qMh~Ijl7Iyao7DvVpp=tCySFzUhFLi`A!HSFM6a!~f)D#l8y2>%Z$V#x?Iv^}z^n?|v@+i9U0a!dw>NKQ=vAja z!fooG{OSn~ZCYuKD)}~@{~l{o2pRSUSWzKE8~}b;&EWz`D`FMjwH5hQeDg9i7xv)V z>AgTK>e?w12hWm7T0U2meA_P8kb(!l7m$kb;IpKW%|Vv*q@eK$ZBb&*~@UujPI$f>`iNnB+@U@^R-`SX@Z> z>jJo<68>0Rp;URRz0xXynDVD== zIsvk%6oF6!GcFXQzSc~Yd_&K8o*foYWT7Kaiz>1ZM$PzP5clebs^nuQbz!k#dFue! zqL(-S_|PuLYyMW=4*B~AZ->Nx%JRbCXdk7)fxOx^W6hs$pq2l8gKyQtp>7A% zqCeDHw-SQ>p;ILv*t>`U#`Ax^|NXzk&TpM99JB2^?YG(DtS?(GS~{3#ns%7V8z&iF zH<p6_Z8$#qw|4kKzQs;H!&uCJwP6wf zi&|(kz)Ch8{qPR`EAS()9r_m^`Rhq6GHewl0sb2q0fi!$R_fQ*mU07**lQ+xgQ zY!P|jPpae&kh~E|EHWJ5#sRXZ(=nPmhb4v2*jOMH^%-MHJ>InG ziNP{?Yx^snlKyMBytDs4&ho0LDLeqgqPCG56KBR}%uM$mF9Hc?NZT?;m3-=+nl%|N z4U7V6QI`fHQKzIOz-6e!1TB8^4v62p10TOZeRi0D8)YQmi}F%w@jX*Lv07-)Muhfk zm)Eu2O%-oS(-U0o+2=K5rGsz5aNwRU$c3%p_J0jC z664e0=G;tAd|Cp%iMF=MNHltrk$m`Hiddt==WrOni`_4&4mVFiTYqnYD@vnJ5V_GO zT;#m5=U8O;$P5MKsC;BJFNUsd@GtT<_?OSyX$Q*-E8q~|jmiob7hwggpN`b^)49~M zuZ&=+VF|e(sH3ukX!3*+w%$=ya-s8X_p#70GzJSC8t9!@+?v`*O#LW3J2wp8r z0RS!Puu=*%&7DT(>aVMk&pthaVYfMtkvcIKVzBC;Zjdw08RICjrCR^BO4f>&RhCZX zedcMVYbF^g{;f53H5@f0=&$J?*Ee-Egg5Jk*iN}0)oph-fWIO$#zK~rg>N87$s`ew zynxfK`teybC65?5j-1*tSE7qOQ z@`ic?5Ze2VD*5n7H17?8J3kBH#k%uVc;&6TpuIEkVUD$#{D(R6+O}ow4L(pWAdB*W zYQ~4g2Rh>nT6o48u7&fucVKZL?=TZ^Mdcl8aN)BUG;W$Q9@4(y(>B?{(!yZQh}K|^ z_z_1Frz$fsbvPG(_JJ2zc!e2yNY-CCSR(+Pp zIbAXEbiRS}?B`it7#(TR8XZ`cJyONbwMqCM97w*g|G1Zhhbv^M059qa8BRq179cnU zr(z-4wNvA`oO$MPEGG<#6ybv+WUGRMV)AuW@_FlO-UftOmkhjOXI+4oacUuG;v=f$ z0?$7DB5Po{qcunWlFOXeN|O}>%+sR8OrL!S4&=B@WRA<^ zGSA-kCTnN7SC|CMqV5$kcGlc0oOBgoCtc;j<~^WECV`F6RDcz`5ekfA&1oD_Cnl?s zi#+>!=vBxmfGp}NB-)qFupNIMF~^_hV_sxylI6oNm@Ir4uu&I;9H(sR$0cxK^Ac*X zV-|L6i2y5hx8{cphHj8{%pO(pY5Qfdv|!qVsF+rb{~+XOywb9EbWc8PxzQ{vlm(0j zSW#sGgTpnj>Xwr8Gz#CNUOS5a9(CT`53%HsPa6m1V)JQ(ktnqBNQ)}@Hg12NA;t55 zd*Z&|wcPo$v!!D$-2bm)n_yjUxoYWSe%Q3%RKYmd@TC5GeM4PR%xmNq(jLz4`E7hf z{`W7-;6+Ku)`Be?yvdZ|ZJwALo01MSaGJ-)$ERhbdetg_N|i}9`hfj>O3B}O>S*cx z{h??<&P$r(YbRfk|0&EeNV~ilaL$3{$zj-yCx`Lzt2bkQuKc#XBL9P!WiTaf7C(L} zyjz`^I)yqtmaazfrK|bmj|^hTJNkCpjbu{jrs3`^Q%D>F?4Ub3MKy3(%KAPWR2&UUfnv>7(sb$tR9) z$J)EKugDCYznrlrnINz2Mq6A*$&h=*Q5`iEZO(>LzP(s%F`8Gv4tZ#6qU zSPC{V*PECTcup`eJvnV=3M@5#r#eC}tgOn?;h`4H?Ddyfcv#)_0AB{Hdwg1IW*Ss5 zf(H)hSJe+6I8bCHrl(~lK@?!7CoUs46`n$*c4A~2p@y)z$D9hZ` zS44nWl>5)m>_2MI@ev%*axLVQYw>xXdywUA<6AHfc*|g$Sn7b*^1_XURIg?x7AS@; zxPhTptYpFA7Svn-FM}^87n~g%K~wvb;q1G?aDHHobpnC|PL{q33&X ze9ZUq$H)7pSZMH}tEWkZR>M;Ov`Pa*Q$Q+(uYi&@ksp{aWKTk(H!5*3H&_mJ^m4=D*Dg&DBinO`VMUpbEgRhB*eK{vo|f_pGj&!)#wGwr4OlN>^m28guy*77iKre*c)NTda~mMnNPjcJd4M0)Vn9yPxCCL^5Kh*X$s z1nP7fz|4!d*CSG{ z@TQa$M|A#K4WBh+Qarbo?xbvjMr^uA)jle{D@=N{9jb-`Fezk2d$? zrt*6xduV3)n-h@u%?VuM>_2Z~U1>n|a|$lUp|`xtAL`xtIRQICvjR z-NaW^1E|a3M#qh*HL0Q-=Ae-`%;6e2r*H&|+rn2=9dOGaHgjX#2+5+a-;U6)-_D0_ zp{d(-r?03QK=%~9;K6}EIP2Cc$#&~G$#(w1;M~hv_by-29ROMeK@F~T{ho=?rMTn* zTDIf@-?H_0vcNEUt43k;`hm4+nCpCqyUxeQ?d)K2+xv=c2i!6!Z*)WZM%;ZN^O`SJ z$!DMPG0P4!uL`h>o_UH>M;RV8hV;q+gnnfJ7drdW4=glfCR7IKGRREe8e9t6b3=qm$FsK zhn_!~HF-l{QAL36CwPHImtJsqyr2{qe&HuRYah*{Hjpn|0a(i*5rjLW758IENDz&? zV!A5%;Jq|=bzv@+2XN7IQ2`JAzC3>pnV&z$XP*5zJ1}50my5z^4*GhrSZHvBJU0)a zpPR>p&c3F}u!Y2IH$X=zF*{;}6S0@sRmsKAv1rymNLY0Nev}ecwQdpQedcaea=Ekr zJI0I^o2@>n9rG!1*L7`jb#oqZj&q!Gc&%HkT`h+!Q!NJb5_1#N+ot=B-xy~Y{($(u zMZZX2SGQ4jxBaU9VS8=c>$V>5$6`K>8BZ?$FTD()MptgluM&AN$c}~F6O39-j?GSj zPz;PsB5hRLg#QW>A=9R3wn%NBnGxSSHa$HjBgvac|4%|1M7@Hy5n48D*DSaB4cmhG zkdWl{#K&gfo2eTF_bo0XEeD_ieS2M?cV0Qthb*c@dQG5@Txk=>Ib9Wr^oocdQMqlR zHp=>LSBv-&we1DHx2pt(J5;|6Y@F0=l3;abBE2mBr}S^xwBe4G0;3L0cSHAyM0#nK z5&U>!GA-1GBl_=%^y00Bup_TQ+ToO6Fwnum%;Hy5oxKw zv8pu8IFg981cI=Rz%+$%bZgJYbEhR9`vbOpT;Qog@h*g&I{v3;cMIG`sSB!l&w)tm zG5#M%+`U~7I=^(*f%yL`wm)pWtcxvQTN;_uOz)Yj#s>^*_5bMm>6XPDkEuuEZYJ1I z|DF6Uz9Rp7nVEvzlnHRykBfzmgjy^B{vgqtl#=L)^?Eas;qc>?=q|d@o8}3UVGc;*go{_9NWkB?Rb|w%=mWlA!Wh;gr=yJg)s2A zG`Mman;OCJM@Jz4(Gh(9>>VtBBVUpKG0ie42NZchWBf!jJoL?=uawyTSBJQ;Id9Bo zVIfEG&r55~sv61tbo=h`5Jd zC~(u{Gbj}t+^ zPy!uaOy>i?qq)HiL4%e6EG$yW0Baqk2)*x5Rq~-rG?8?$a*HTgnR;6hbnhfp@`2ye z#G~O`(j0(AeM{83Im(wlWb=f;pTDb0KKQ~W?0AOMre**xI<+Zui-M@TmCLTXIhS4i zc_Ha%S!4*^c>q~-=uSmW%*rqx?*e9Fvry|QWX`$>yQ{M* z`OsBl*3j_jYYNc9K7Cqf^}vjzA1m1kAKxHb;l73;#7&||tem=$cxQ?#xi-$elFbrB zc(gGPiw=(}gE`{S9kF-(rb<5kc{_^_l}#D}ei>9YiTv>n86ttKf9g0w;tvZ|$tBM* zsSc>gbiexLK;w}0sy{VNL%-^B(1Eo}FpHMgeb_4Wk_ynO-R z%E_ZxU>M%@qc^-GI#v;T+uy3>;%A?Fl*NbPeP{HBw;!Jkr6KXVO6JqM14}2re!9cm zN5(MZHaMu)(zPS{Ir{RtSKLoP6@U+1y`2Y~BOTv4rrWRBXW8wxM{IXkpRv}qtg&=A z?=g=yoi*i}+{Wd`W`^yCVfu@@b}>6*hLSTRPd)X|Ho|fLh7kn;J}P=7^+!4aKB|KP z+>P31JV~huiMh&CDF*}urb3#7+7yw#5O4`6q(SPCz<|L18OHpHH~xM785K93 zNDnO_9GD%!x!f@DXW~h(HzF(ErJNltg2GA7MY68tU6Cz=Cve_`_m> z=@yvVdxXwye_QHY3pDq+(7Ekzj?T0|gS!QU5VW=o&a*&!p9z>|v^@-31RDBO=ntnx zNBqljpt)T_7c8YY%~1J7Kx8D;lA)vJW1(LHrI*?Pvs37RVIoZ*2?(`Qdn&P}tc+xh z@0v(E1Vl;0n$3hTMe3B0mOq?l%%3f6u~s^qk*Jg1ZJhzaw<^qqH5eO?fLCvo=z2kw|ae z+IyQ3M{_K*U&pv0k=_uIo5Qrjg!G8CMMMT0+n5rKBhuzz{r`Thh0eXsa*lEKWwukc z>elg=7tB}8olQRDZetZgl76%9UtRy0r^(M)|G$;5XfQZDCJGPg2Qn6eD|PT@-8$Pd z0j~$h(!Cx2Q2y9Q7;i^@17Fb~!0sa)8&5-sXvTW^>&*Om`QBvByCUGi8wjYPTzGWJ zW{*?|Y`}2KIs-r4;vM-1Yg-7n3;PeZVa0_Pdr@ zvuYwO!E*lV2)~@aH&64F0=T661GOlZw3a$J_uwQIfL{Awc~$aFy=pvbY6#!=187m< zdkP&qW+LTvrz-ihFKJRwU@-TM%3uyTt0L=F`C^?{y1E2{bcwX(9e z4Rr$G$oTnDRq`#}>1}p|Kve46m%4P%esNkHuLzp9dtKVT$_-`!W#1Mp`H-z_Po zFV!7^@ITH}CBGAWHn5#&=PT+CotP4>PK5Y05c#Z9*yJp~u!;AX3>F>oH@g9P)bckY zIYyBGhjyyun|_n#F&y}ab_IU%J3?jrsNNN1{q9Ls@|hpHleIb2vA7$UMb)tgo3i09 z8l*ncT$OzKp_=y;;Psm>Kwk!r6GS{2htY@mc@X-P@^sHB{?k3)^=Tod?;K6jhdYaq z{@d27T2$)?JDomIj=asa~^hn?0nPtit}k_v2(UF**V@h$l1-=!db^z!Krur=J?+6rQ;LF zTaGo3XB-P1dA4=7WwwWHb8Tt1Nwy)jdu*+3ciL{VnXG?W&smRJKeN7LEwMglU1XhS zO}EBchgy4D+gR&cD_hN$zbrpmj#+kF-nG1HdET1AnaX<(^hvB2vE z=gnW6KR0hPuQx9@KVr@|XPD#7!_D`a+nF1hZ#P>_S4|g8$4z_SmcwhN6{bf`K2xSC z!8F3u+tl9F$W+y2GyY@z$#}xJ*SOvIy72|$W5xob*O+J=Y3yU{U~Fu>!)P~LGh8%$ zW7ubS->|{(qTz9aWXLj1HjFa#HFPvIF;p`+^w;%2>rd+U>p#$Mbfh>YI0ieqJ6byG zIx0F0_TTM4*uS#xvcGL#Yk$`MkbRCl)jrXFzrBaOmA#(5lHCZmG0xhK*gmyw)xV@) zqL=mA`YHMc^!@am^iB2E^-l21T+)53`$G4jZj)}MZmF(Nm!q4i8?EcF>#Vy=S3~ED z`7h=dH8aDdH{&xAB^5^#Ii9NJhY~rCs_uhCj-{&WULsGTs^fVgPo%275|JlR)hZEr zJXOt0i9C*~raD9(OI1TUk;hO~cY?^HsTwnr$PWb7b^q-p@+hkQ+lt5|sd{ZEkw;MV zpYcQPk^58id~YK6qw2X&iQJc}XTh+2sQUdRBKM~11~6Sis=oF!ksDBT z{Wv1mr)tSbBHu~Xbty!yN7Xggh+LPduM`ux4pmpzAaZT0zWgeYYf*J&7b4fB>Wg6K z8dP0znaI_tx_ls!t5Nm2<3zrLs>{F{RjK+6*y?twK6RDIRjB&JA4IN9)g^O?d>d6C zdxglAsQSoqB3Gp9qMAgmK-J>+h+LkkMGc8uj;asBU~p4ahT-j^YQc6QJE@w#o5&8T z&V883cB3#?e!C zA`BHBRmUGDatu|+!4M@>9dnvU|50`HBqIGw)lrv-be*ar7ZT|jRfoSqq<^S7tUZyg zQgz4@BK=L(!M_mcFRBijOr$@lI$$f2{-A3Ai$waJs{IBM={KtO$tBVis`fS!=~t@u zDk9Qls`hjf=@+W@SVW{tRPAmi($7@w+M7rhsoLcjk$$3T=M*AcplZh-h;*K+9flL> zN2<2lMx=98ZQG4VXQ|ryRU-XB)t2uO>3gcSXhWp$sM>5Tkg}zG^d(g*_a)L{s#bcLNQbCe;U^*;q-y!5L^?oK_ZY~7qpIV3BJHQD z?HMBNqpEo|k@iy6FqlYtsH&Sqq|d2JRuXA}DdpPt_mV5otSB zzk8BM?@{$kb0Te{>M5A8?^5+!_)*@W>NgFDw3VvI*Fb=gs>k*b=`E@r9Rcw;s(y6{ z!e&(cawG({sCo$cyP2v7PC)J*Rlk@H<(jCv?@uCapz2;&kzNm~>&_e_^1W0&J%Gr) zsQT>zBKM@~N%*JtQ1wJAk$X_}>)(jnovO$3h}?~;M|DK*O4YC6yMH%T4<8|N7pflo zmB^i`dY~b{ml?m*Q&@K4)Qb@wGAx1;K3?TFl#s=HPaxeZl6F%Y>m zRd>!Jax1Ft_>#yisrumvBDbLG`;QR0IaRm8hrStA-K(p z*vK`Z>Sp)=HKyt&Gm#qw)wQ3$3)Q5kx*MkCda8c9oJg-ybysI1l~DELy-+!Usyksp zUQ5*-zd^wPs(x4q6{M*8{$E5|P1WrSh_s5T+x~{aNK}1yAdyy5b?Z_nBt+G>t3Yud zs=he^%I{Eh3(SQTRNWj86>O-w@ha4pq3VV?M0$>@uis9jWmH`cll@t$mRx{}CsbYM zgR&%4UGpW8o}%h21E87*Rab%Oo}lW>(7~lteJLAi3Q+Y0Sb-m>>I#^lk5TpcbMO!v zRiB#&@03w>nH?Svqv|tvLm_{vK6Mmc`k?BQ!{GT1sxF1)dLdPpG=t|VsQMVJ&qY*y z6qddPR9(Cc9`&N?qE_(A7F8dDrB9~n!piU@6;+F7!(&lYT~L8YKB^WjgV&a*D%T>? ze5w|}Kb=QaAN;p-sXE^aul-PU?kOVWQFRUs{@GNWy&WF1q3X<4@YW1fbM^2Z3{|s- z``>I)k9cdn-w-LAs+r^9DGI92I71|_KmLCk+2ODM|CsX|XDdgB{cYP{wjS03%g1nn z?rVD3xXWlY4Ad{zUC_0PnFasq|84)v2hU4_K+ntMtkl3|{9u8B?AVN?*tq0iS%Gye z+5|i=Ai18G?9Gi>cNc_@;sIM!_$Uk;t|-K3v2Td3Yql1-o2}(@KcY!YfOuUTaEpr9 zg>feYpVw9+N$c*qj^KA)=Y!AGyxa=z=vV+3<&F*mkIPC*_E&;L)}|Fz$!A{i5j#jA zRyPTl#mDOK;$M)q(I%vAw24dWUH3gp3$eP1Kr230r(9Ev7^_>?urabXY|Lj*x}Rl- zSlt9*7ayxr?+b@#{UUb#=T%uc{%>(_eLY1pP#{(}9`MD->J)r_tZv<%SVR|O>7DSW z0?b^<{ss`M8wZ^bAFES35h+%;u5LcszivJs{k^d)I>hS60=oEEor)eIi5a5Q zKK=t19!&p0G)-Sh+-qI6Vx+HD%%@+WNuh(?*C?PDANNvB9~$>sR~3_`K=QHQI>{Ox zs#1*vZ1Gj8RP0FU+Gy|FG2XcD_SXCkOwim*hi%vh=zyqg7!CC*9f**T~26bxqA#!yT|aU z?|GM{hSS{rKrQMt7h-8T87a5pd*pU}&*v_x!*JvM|MJAW*j?N8wyUf2Gv^@3aYwxU zf<43br!C(WV|~zC&a&Fl!TgbVi0Py$+oUrtHr6m~HgwW|svoU8uak7;W0uD>CvV#X zTs@(ODs>%IPJ;rjr_r_oBO^0CF+OQ>Qhcoc%#7F2e-&^aH>A~!tWA9 z6mT_N+dcZT1sc2{;AU)T4ZGeCU-|SZG)P(*aui0vOl<1ic4znDlfbc274Sd!A<9hLA@ZV2cWQ zgxH!cf0Vn&BINF|h|m3$<_!kecBBHgsBH)3W{UuIHzR6yGaq%yICf+}{4NDhMaAzl zsKMnUxO#N$jm%wp^O={u#xlbcOa^B0Q!vyEj<8*hsge)9LzDgj3-xq>7QayYq3KW# zn!0leQg=?_Q|}$dni{_3(|}t1mt0HD`r{G1;}5Fj<1b8M@nM^q1o)yh)pT?Ro%%@G zK}pl;z)#c3erFL&3#;^0pcTJLherkwyWKWb@{RoZK^7ZU=_!CMewB_8UO?Wq-Biiv z{^Avu8@AVzfm{6cI#P@Rfm^?-N;ALj7K z|7+`N$GB^`*0|a`_e0(P(~flOH`Xkx+w!8Nqxmy)yy-Vnk*TWjC1VSy_dh`YjXq6x zO}D^)&Hk{xnr)+dv8@mM1>0iAkY7lC&?lhABX9Jap@2X_a$0-x2*+uFPV101C*8MNl5}XOE8&3wh9QLcvq;ss88W;BvQs(H`DpY*OH9 zK)5`9qsiAiHa$HjayXCSe8uko+(*yQ2s;dlCtI2GhoHjkPMQZcRjCk6w zGUy*ws zUV2uXCo?N9U{E4<5>AHcmzdz0mKGQ2ne?B4NCnfg1W%w>(!XMR#S9R?5vA(_BJxbH z;$!2d2EGi^H35Z}nTBFvdyt)!k%hn2KLS$GRM);5g@A$>0&J(Y!UPbY)P{hDf(vl- zpzj}wc!-_7nclPvd_NWnu?XlBGadpvg}^f56c9cRZOD_87&kQyK3jnn9b%_2Zi2F4 zJA!*Ido=c3f#y63St;p(F4_bbHFQL>ek>>`BcPXIEovM(P_;%tIuEDKU{nPP6k9VptpkN(c$q1%1}=-GX5JHQw>`TG5Y?xWida*v?E2q zGk#hApZrF?;&R|N5%t(RV+Q5aiQbZ;hN|RxO|o={S?5$!U$GlthX^Vv%fQlaA96m} zU6p*^*6Uf`mcC*a@QQM8hw}!<7}Cm;D*4nMcCplreZ@|Jo-~G9{p=%U!FE-0X}v$4 zVQE|WiXA{J%0C=R%kCWzH-EP(x!76dI4Nb8U7~SS*j_wr2`G%}hlnankn(~<|WwEwy<|{S<^C-xcft0c-1{X>HaaiM*5kP$i$c$xfELov&C2+@kV|!WI$6Y2`mgAo9d?Rr1mA zE@shN_=;lyT~ty-7<$k(im>AktCA1hOmmYOcBurQqp(Y*{#E20H&&HgUhlbwSR+HW z%RJzX!d67#w3sglonPZgFG>^mnq z_GM;XaN>}0_c4YT&;J97`vKSMt{CS)#}jb=Z*0r5erPpWhMJ!=9Whlm zCK=Y~|I~NZ`C>kdi6H|^J@)6rZmWU70T$d8Hdk&4dehRA;)4V1HKp*;Yd>>;vfQN6 zi~;hy_=@WTv#3Ha;mnD-UU+{oDc+Nwk(Qm5keCtd!1{6cORgWs?Lf|NntbTazT!Kf z1ET7wMCd?rVrJ5m)NuZilgM9klFOgldM5h=z+tW)@QXUkh4DiiFf%?QDULDxIwkvV z9Y6anw~3~nV0&M2T>uwV?JgWV#hV^(^flMe=xeU=jo#-1YjlsVxDK$3TBsth(;e6= zN}Z`!_;sdot7;zRfni=dn!`LZF*RXIMp8n!#aGuri?6Q1xA>i3vKEI^T`k}jb*c-q zczRam)ZohUvXaU6@~fpI`)dj&t!9y7fY*%X08h!B(y?XOs<^TXntNrJ(%GSuV6HtR zHMY10u!~BK4Kug@;6EiR!lL-%$B6&p$6WlJtL$evAC5}Z0bkTnDGYydd`kF0UvU}H zS6t?z=XTT-go8~$H9!}&iw{E&-2DxX^yLGQdHFy-^Yq_CM*1Dm9O<#?shQ#Se(pH3 zKX;tZUTF`@4hu_FU>CKpu<4D-v8hwCAbw2O@@2{ufo1$F0^Spv;(IVeZWlO2SmgMu zjEuz8_#}q;nf++yXZCZ=>^-$S#LQKqWajuZC<2wiB0r^gx1PGnN8X*zBDeJwR|e!n zL8lRonN?&@`qZ>k#@J6No}wrI;FItCg(Zhr%56X{DwYzNJkgUCTt=46!7;LA4j=pQ zKo%Rub){&HYc{bNSszmlfRFJHfZn|t&wdkMaYbMr9F;+W+0lsm$Z}QkO?<2YYvOvo z;tGJs{TQpE}1lzH>~oU$M(}o9#JU1M5a>d&@hP0p^3|F{X1SugPd!W^4vG0tV^Y z#JnGKKlz$WL(f3utYZPG4Rk9I$n{ruj)9aBxsBHdE1$mkh%(F#E~P;Tc2B`ZTMI}S z3278nB~7=Lfb6Eo?a@BAoNmk?Cd{z@n`Ww82i~R;kT1qt{NV{X0ZDk;7XJrdND(^6 z{Ubx;yMecg1pHWZ`1>1F*A!S~;Vq=dE88tyH_$exOzuEy9s!xIv^9)G1{%6cs1=p# zb#zWQ6}o0A&4mn*FxO1x$jh{40G#n4&Kjp!jZi)=||l6xFqKuXC=oZ`$pS;w)?D0E#Fz1nzK#snoP$2hR5L6 ze?y%&=B*e5{L7L4=Z{!)0f&e9h=o!IGi1i0kLK_ZRdRhbIfvp|Uk$kJIs>}+h=qc# zPFrL>_^T?p%(nXi;lo9Dq=ww=YU%% zaPpuLi~XAsdH-fEa&G_USY&WWcK~Ej4(Uk9s>cO!_q9|dAG^jN78^!(`>2d;v~+9+ zoSCVq_b8^`a|2V~tBKq~c56Fe7L{rqVrsh8rQExfOtszoOtqZvG@fagk!^un{EQ6P znsRH$$!G0woP5@fJ5F+bKFy93$b)VJ?4t6ZLu{@(Rj9>xtwicwE4kFU6Z*2$5Z`JI z)S}{BrBG|_{fPm|KQZvhAJ7C{Af31skc&zu4k1UC3Ciu9h0r@^@u5dHWX%nUS}g%u ze4gA{ z4#484W0+4BY2SZDm3-=9ni_iWv1ta>;UMv3qAeqQ5hrZ)VRL78!0u-UY~_GNS2d4!Veu@-5{_;J5fs0_P44sbE>$ zG%AB4#LtY(Z}wLu-@;=bWi1Q~T@zpyztBZ;RwMA16RPBb=bZh51&3W~V*nSwOI5(t z4|#AzZ&ohXY)>f+q#9N;+Nm~NeJ`OP9*+~%d`nx@xHZH>E( zLkwRU#z2-phVF0OLR~HUb^D|C2DZ(%p6z^V}T<7TGds?Z}E=8YUG>n>oC2?AHKfuO)3g2pem1&v)A6r542j%9=(>U}1|uFsZZDuVa7YKK(;sJfJ2+gK zta_mfTA-h_VQSvC0w#V)e^vhi_V)jcjBbIGQeC(`!L@WS#{cgl?jA1LdB9l#;{Pjc z-`VO}(<~dzSIpf_i;c&PO%1d4AL(7Xu`#cbf5?5MobvOb+{jRHgor9PqAo3g0jVB{ z(e?4y7*%rJPFclwF|Ln%xC1=|ctzcT*6`9(HIn|ZSCxF?p_*%o;QGBEh()=6Rbq9V zz~>eze^-hQ{@$HWD-UMv3%>QiKr70(9!jf@YDB*BhAR2U@kuN)1YQOKvZ%mI7&6`0 zAnoNJRmrE$W8d(|2eiP2!NywWBLbgSt}>tJUuDjk7{>yGjr&Hy#-SceL_YVaD*3}=S}uzW;g&vt zEI!<#9QecCph$hTk}A3Mxv8r{=zB+#KHQgz)ZZ&5xW1pnr;pLt9%AJ80=@Vcxng_O zA&bmsj;WH*+*MPC7b+z60%q|Ql2qnMUR?w~JwTQG4wUQ24jCvN(-S%%zCu#41L3Y= z{!sriGM`jze{ukyebObC9X8oLfL+ukn;sa0?Eb?d z5}!y_C7;+-pCyLT(mk4^C6cEbxxfBRm3;m>MJzvjk-7oDsIPvQ#WjV7j^!cpvAoie z{e_06YqD@)fOn1N01x%KBlA(6DobaF45FMP$5?ZB@)h3=?BWXzDFZx$;~ufUQa0gV z4dvqJwqW-!c>do^+yh<9oM)YPI~Lf#vEOBzXFX!Q(~@U?-)uLHGnN?sH1yCvs{2M) zCnkw(F6I0mwLi{>>`DJioT9QPvjPJa$hcTcITt4z2Q`x z0LY?F#Tw*ko*a)qg9SM&;pLf%fu2oftNMV$>wf%as2W4(b#^N`t&NBI(aB|du} z%}y0+IgJN)QMH_q-5)Lp+Sn=~uT|o6j?H6j42Sk{z$xm`PB|e%Tpbp4?wOY&vw10> zdB9kfxvsBxEHHNy^w~ycaIFSSYpR2oraFAg2bQsz@aoeTz!dfBQxMaiLBOnM2F#T$ zG4OL`vnNs zm=`3UbkbIq6wEt9xOtT$Qv~x~+lkQEcJiTTXyRHBa2XEJq603+T=zL= zI<1bCj`r3Utlcd8Eh*+d%!TIarVXYZ#{I@b@B_> zeiQR$%(NIIdE{1|00N32;0eMX1&nySByv`Q5mv~utrUoj23JNRdj%wRv5k1Vfm9?| zCWxFVAcsWLRwlg8m6Vo>X*n4Ja*we!)dhpC1-dp}K+=)6G0hQ^$kPNQ<3?&QB`pCS zV26jp{r@n~)g%G6B(*KGt}P-@6_CHCX)n|(MdT?tMsO^Nn0e}_D3U{o$diRl5Vc+E z3nFr&fb>y~VO2K{krPBu53L7=$nl~Fsm6IiNQB}_gM2<}|g6pDe2dAbf z#brU{Ndk;kRat2k9$SJ2y)y%!*EC_fKKup*8c7wfTxphmZ`$<4)Id`y!Zw)7H;vg~CJWf| z;WP_u(}Pa1K*vT4_@S^dW_$jCuq9X>^4d;~64ohZ^o*X2XD&!&%I5K@&B#<{Qrf{qs~T-T>D;oHQPk%tCp*le&*$-?@b+y#fCG6 z7Wx9+K3%n#X=LlIp7G1(zxQ7^@V~q%Hc%S)?BmKuJ@Q@41w1Y#UCZ&EL%*|?7V^QH z<$rxsls5|}W`LJDo+D_NKC0vczj~c<4f$Vl^gq2RD(t}k`yDfrW8+~XK#kmKGctGL z7mv%1Vcl7NX8!}6(O?cPN0hn46=d#kg>UDV9%t^^Gp?%xk#zoHh`Ur~*p|D&)78MFZWZbYLUYiG1 z$;bRWk;R0|Jvo3W>T*vIlX?n~vei$j)MQD*pv@LOX#KlE^+1l0EtLRnOMU=1 z>-=oiv`{E83t&YR3Z$lu=wU|k7FATqH?!jtmK-8XULY40z(exjJ{Sp`WvY@-YWkcd zh0j|ikc$1hDVyowQ3OFfCRK8Qv$kGlfng=f0AR5znF1X4MQ-{sA~$`RkNie878wH2 zGXPms0Gb^Q9=f+j(k6GRl1rRjPqR!wdP+JFi%L(?5c?-zs8<1*8(~&*Nh3~HGGz8< zUDUkh1_LB5S_6b}O(1fEjjH6EyQQXZBrF%HfGl>o2%a#Jus+s+E~(#^OPY0M3_Fxz z_nrczVt4PV=R$FkAaA|Zs^s$?`IO~_4@?yAWWLni4oAdX5VDZBt4mPuN37}~k!Fut8DEnul3|33++ zMdknF3a8o`sY7Fhh+TcID!KSsf9+@RZG^-uGS(#SzumvOFSx&RpKyQa-sj%s{=mJ} zy~$nTe%bxJ`$_jB?jpC(J=^Vdr?@A(C%PYS4{`T*_jGr0w{tR=+Yo06DHO&?88s{3}8szHZ z>h9|3YUOI`y3wK(E}74nPnnOwn~k5FcbeZbziEEm zyvF>Z`C0Q4^TUwYG0&W9o?)J5jyI1pk1!81_c3=jcQm&$H#OgBu3@fhcAG8c7}HhL z71K}P3HrwLm1)1}Q`3j0cTAg2ubNhwmYbe3J!&d86`1l&S*BFe6w@TrXwy*BeWqTf zyG`v(%}tF=bxe1dDw-VdUgW>VKaIZ_e>9#per-Ht+++OMxZU`caf5NK@g;ama;b5V z@j>H!<4j|Qak??VINmtYIM~?N*u&V#*xGoPvA(gU{IQr_A&Nht{KKE#&Slh zQD^wa@SEYH;RnM>!x6(5hR+N;4DTAY7}gtB8&(*eHauonXpjtZ4B3V>!&F18VT@sz zVSwRYLsvt4LkmM=LtR5PLnVXLVAB7m|4V;ae_nq^e_Vf9zgPc>{(b%1`i=T^`jz_U z^iM!d7d_FF!Xgw4P&|mD5QU6FLQ#Oihaw-vd=&Fg%tbK=MIMUTC}yFUi6R$84vK6P zStz_HGEropn1Lc4MH-4!6e%c@QA|fM4Mh@)sVJtPn2aJ3MFNU=6mckGQA|QH5yb=) z<57%5F&4!b6r)i*fMOJiktjx>7>;5XilHbfqqq%4B@`7=R6tQ4ML8616fP7_6b=-2 z6gCuA6c!X_6ebi#6fj==gF%l%hav_A4ix#nfF}Qo;yQ|JDE>il6~*5u{zCC5ia${N zj^Z~IS5W+l;xdX~P+UUsGm48SenN2p#d#DzqBw`*EQ%jce2?Ng6lYMJMsW(owgu^+`g6njzZLGd|?-6%do@hOU3 zC_X{)F^ZiiK0>hr#fK<9K=D3`?I_+uu?@w$DBeM_6~)^q-a_#viZ@VfL9rRdCKMY{ zY(Vikiq}xANAW6(5)|uDtVOW~#VaUQqgaLFWfUt>yoBOK6fdAyfnqs|=TSU|Vi}5O zQ9Og}&nh(bmo zp(sG%Ly?bSK8krL=AxK`A`iuE6thswM3IXk2SqlDEEHZ8nJ6+)%s`QjA`L|i;IiqR+@Krsr%NE9Pb z3`a2x#ZVMOP~4AVFp5Da2BH{%;yx7pQS?L67eyZwy;0nYq8EyuDDFYg14VZf-B5Hz zaW{%CC_1C)grXyg4k+5AXosRLiZ%gJh+Qeft`uTd3b8AN*p));N+EWo5W7-{T`9z_ z6k=Bju`7kxl|t-FA$Fw@yHbcH! zg-TaiV~<*)Xo;c)ismSqq41!%3q?~DO;9vO(FjFD6b(?+M{y^LdMN6msDq+5idraY zqNstQI*Mv2?m$r$#qB7n1cZ!Tk+CZ>c16an$k-JbyCP#(WbBHJU6HXXGImAAuE^LG z8M`85S7hvpj9rnjD>8OP#;(ZN6&brCV^?JCii};6u`4omMaHhkN>?glk8VRz2}MN| z6;PB%Q4WP0g$sofg#(2hg$;!jg$0Efg$acbg#m>gg$_jw3K9^~e<=P%aUI3AfGEWI zF8zalcooIpDE>n6CyGB%{Ep%`6jxCEisCYgUr<~^@iU5xD1Jh50mXR~KcYB?;w*|E zP<)T#I}~S7oJMg9#kVLKmnaUSIE3OLiUTOVK(Qai zJ`{UV>_PE4irpwaL-8q!T_`?5@iB^>C_aMoKji;=h&Gxjd4xD5ATMk%~%>S7mHCHvQH}y1rWt?vK)!;S6=$GiL>0Z=%Vm8HeBcGF@ zgp^IbbYf~+^TgcPlys=1(mXak@Kj=R#S4-?H7zyK19!wBVH&c>AQ3%~fbvAymos?1^|u^9H8wdpF?9+)gAV)2tEPE=GezxHEpTykt&VlrMk@QI!W^s$6|(dNXZI&3pHU%*`v952DUBJ+eWGy z$=mIR9FZ{#ViHz!E}6uu=A7H<=^qa<*%0}idW=6Q^+>K1q#kxnm3;bVhO+c``4-xNUThX;s6PflhjvpX2N-gYzs(8(wnYm#=+r^b z`>~!-$^HC#LfKU{H6NS$7Fq#VY+kSG%h1$x8{7-I2lwI|_}_}Gfq~Z&HD1NNgq#Dv zRwbWz`wEt~gKwc3c*U0ERqY$eM}^P>rmK<@hvn0vZxxSc;rx!H8o88wLt8CEw~oWE@xvc+}O9!0Jvf=ktw+7azn~K z@2QeYoApmROACWpAFaX6*=+ajkMONL{(lteBQH~T{Vmj60Ok@(G7{vJyxlb4}bV)*4R+nb{@css%=Ys zR^atUzHYy&lF#|wqYNjW|ECjoUssXykh8X9iv1nPi|=b)VmWE4XZD(QnC^hOe{UFw zexUBzm>**rlj%1+|4058@?q=P1WY3Oj7L|eQf`Aut5s;pJ5rT=BgdU)joi|=us$G{;iaq6 zk^P@w8aqJRJbdx6B=1K)^_KftYS@+C3Djk{D=VE^Q#4_=7qMr1`M6(cJS;7I3+n-H z85TD#9aj@tK-if-tCA1BVl`{yJADi50(4Ko3m!%&5HNSDD*2%E-eEyuBUT4M%WxwW z(YpTlL+DbRjSs4oWFO-LKUtmyhS6I)3Zs_|n4n#~7gWi|UG*`G+upaZ7T}iQ9qv-? z%h{x7Rz>#As(kj3G~W=Ic{PDu^vo;mn*WSD5PHTPeCQ+#Yw+g2g*5=W42#%AG`JQz z__0n?T(W6T@|pMUW|?7gR~?u|Z|)Rk|2T>4z)w-0gGu2%2LqeCH7~LBFifgNZ zPJ+grx>c2YBbR6j=fhmQ9l%A;MfHMru+%lOPQI*4KJyoH$Y`z-h0&}qXDAPL1xHBY z1cXkUz=zIk#6m;pwK71L;XV3@iykkB9I@k-cX;BT=i}!cXYnBu@-NgL?3tK#hKIAF`RnXC_6Yg*P@+MD;7V@=mh51Z;4 zHyV2xzA{YHU(#pmV{{KXCfon8=iANh$K4HLR>yQ8pOKMdxc}%s#V9Z>UO8We%y1&V zQ8o!X5yy~{v-Z`f!6%Pl{#sN{Bqgkh?m}AFz0fmz*Q$w z*5ym_M(}QknGNXGAo7c4lldFbdRm7BkzWw_OR>HLBCjZ$0`aBx%0C7pEY`~f4iN2O z81w9(7xB0neav%onw6M30!B0oFX2&Yyt6A!l+0ee2<+(Me%Tr=YL zAEjJceO>(i16!t^OCrA}@b^}}#cI}B;D=Z*a1m763tlvORp8k}*}8_EJ)Rc0PAF}% zKi^Yu#wy2-Yk{LzX}*-v`~S+7Yw_DjwaPJ(H%6f`B@d0r8~peG59l`%_ht8K_d)kZ z?k(iNClTJ3tuRpgrGnhq8G2D-Ys zn!9Sd%DZ$>vF|(QVduxrH=VCIpN0y3vz^J#@y zjpG@|LPs7{+FJ%M2+p;o*(TYBKxMtwwmWUNf&bx8>p7^T_nGw_Yl-za>mutssGJvT z9ct}qZDXx(t!y=0{<8dNIcC{ydDrqPRK{CunQxh4iL(r|^nyxw4J=hG7W3cc^X9Li z^4&J`dh>GgBj$W_22{EmZob#t&fL&^yV(kr?Jk&(oA#LAGreY70hR20rc6_UX@se_ zsXbJ#t7@_t|1th#JYn1mmFiwMzF>UJSYY%T6QMF)A7ck&W8)o0yWtwtg!{&@&+xus zgW*NP<4^-G%P`q6%Fx%)(a;2HzB%;Q^*`%R>i6qE&~J34I3_@Cy6%paj=GMD4uk!7 zs73dceV6@h`&#?6_J^SMT&jJd{eF87dn&2WF;o7sC`-{0qtdpzQ0-g9#nLq*wWg|fDUn)Hbzx;9wWO*ifk-W=x&Z!vn^SfESRyr}>b!4=)Rd}ohY=~B zs*i3WQWL7qu0o_Zs?L0dNR6pF<31uaqH0baks4Ap>jse;P<8rXBGspA#=AtSN7eN1 zM5;^G)bEK@hpN+t5UDm*-Rp@|i>fJ&h*XoRQ@}VisG5{Pr0P^nxK5;MRCTr`(nD08 z^fr;IQgvc0B2}U4_!o&(nW|$C5a~gxj{bv44^Xw@yTp5&s^t@i_ZC&lE+XEWRCQb@ z-Wyc4XA|#rs#-4)?=`Agl8N^!RZSO(_b;j%EyR0;s(OidFH=?fFY#WYs%A9t{z+A` zj(9Hy)z|;6NxT=R`cD?|o~P>HUl8v(s^0ESynj&j=JUk+J5_HqCf>7Dz4jXM{zlcS z@TX^}dgW8%Jx$filZf|Ms{VPKcu!IF;tJyZg{l{-6Yoi?p35WNpQ-x$c;Y=l)!%*~ z-k+#?#zwq9QuWsj#Cx2ory3IPF{++~4j!fIiSxw!166-oLcB+)di*Bw9;WKCRmA%} zRgbnH-a}M9@*VLWr0QW9Ip0zB&@JNqmZ}Gb67K=3e!H7^zoF`ZcEr1%s{6MS?>?&T z>r1@c=k;?`Kr~=po|$l&T-BC*ECDeGf+6Csf_pgLprt>N|Uh_amzAI7GZ3QuVE7 z#QOnNw{Icd_o=!K{`5VnZkZHj(Fdt>g!dB_Z_NkgsJg1RbTx8T;5cD`6~FN zsk#Av-#4kcek8bbsk-z}*kw@liEgkDplac(#JiQM1$E)PK-K)M#JicQi{pv6n5sS) zb+1#^dl-D3R9y&za3fVcAAwhps(D?(Z%5Vn@Tad(^)cwe%T%5FJ2LeD7Z?fngeEko~qdo5brvwPJfVipQCEVN;sxdHEj$Wo~b(RXE@tZ zbt)`2LA*<;IvRTP1XV{hA>JaYj(`QKkgCJ(5N`ohhr%pdLe;@Aaq_7; z2)e(RssoM@?;@)9pGLess`foXyb@LWG$mdyReOC%ybGz?6IPYSgKF_e_)1oy>hNwv zsz}wL&lBl>st*2*NEN6$NJpgms5)Q_k;+rG-%cWxqiUa@iBy)Vz3UUH3{`thBa(xv z-B%FFPSrR2^?NkQpD^RsVFDQXP z)pl<}i2|y&`3p)2Q1#&@aMPcvtt-G)e5$te5$`OjHiz%;OsY0p2$#^Q+O#4(Bu>>P z*~FVe)i^!8%1zZq@IA_+YQx&ZJDsZa=MrxwRqJje-VCbNX+^y0RIT+2@upF=CVVwg zsahQ-`!uRPGz=cJrfQYPh}TWk%362?nyL@MSz zGvQ@Zs>c3Eykn>uGn;rv2h~mg?jzn&RK44rct=w8&gaBCf~tQ{Al~6ry#-6(Fsj}h zOT0s=dL91eAymEAg?I;3^{*YoJBX^6;nOyds+YiY1E_lOAo2F6>V&z?0;E_5bE|@GR*9nGxB7(v*^%InD$p_{Ws;fbcI|Iqo!9oHHjU z%bk#$|1MFkYly(_>{TQmymC1f z9Ih;M0&r1R7Q(<2GBQ$K&h!X|-*E`}cO2sKuekUc%U|EKq$BW`;=_3Ah|>%hI$7EA z{@B*^IR6{O2>DhsMRH+RUz^9m!u^U404wZ%1q16&cjvgBfnrcdx_yfx`NVf`vBZ#u z+#ZO9CDF6QY0f}BN5tGF8+cnYF7BEbHd84Nt~Ry<+)}*SSmJ1ylIlzj4u`Fik$UT7 zF74_os^@ngDZMSw3QJ07j620S!<`r?f{LKUa+Y`TIX>{s3+!ls6xcQZEG$!+0fwML zk~=3Z(V3MLwDRlnBS)`Smlog?-a>rJ~5YNhFRDGn1#(kxstNXtmIe(XW@GJ4%zyVd}!|>78*W% z%>i22r%w&7gv!voOaD|PpLpAv5aMQ0Bv#dZc%mB;Khcd(oT{or0O`?9fmn2Uv^+2( z#(NRF@Kr_f@m+7R28YU2@qjP7GL;IS#>|nppsphMjt>~#jiWcbBj%SOwr`ap`S_E5V)0>k zH;Ufy_T#e|#YpTutVllj2kgW&n|qOJv1Z~}=6J}y&Gwxw8D7j=ZaQkpGTtygZZsI4 zHdN7X&^OY(uj{JatL>*bpcxx`Irgzwv$dvWyQQ!BsM&4r7V{kB|9?S-P1oh6!|QEu z3!-$ByXZ+XkjF_6$e5>h7}}jAw#lF`0bBgurOWFjtVKAG!WS7Lb^`LIs44x&UUzzu zYgVAGg97rVXj^jnA^qV3ZT?5-P?6gV{&ImPzb>6RsH&4A?IvbR1sd8bAVoH`p}5?v zRF$&@;->;~!NQu&2EST*a!AX2=Iiq22%8de9$JX=eUwxSs@+%LO|AGgr=1R;&TDn$zjb+NzHKPg!J>X(kVgCow9MR^xU+N zc0Y|qhq3OEdX3s8^m8W9q@;|*+%#7@erP_KqXYlEsBgB?VkEyjm%@W^e4e0V;J z#;lFx4Tofr(y5QF8qH3|w}y^v$U+g3M#{9q_@E)j1%g2}?=gOKP-8~a2=i}cLVn_J z1?0HX<;vfndeR;cy0O5$OkiX2jnHLZ-ZasD;eMfuk=&eWG1@2M8WTHmU5Gr-|>O zkNQ1!jQ>AO9DVFdZ2N3wtm7?f%_q%OOcRXj4SyNh>pi-?x{6x2=1s^m?;Eq4TqF;} zVxQOCvt%SVJSGVb>IV+|!KK!J`bICuG1*UZY!%nrvEoaWr@F3Z$q2yiB^(>ZZ4mXS zTyO9wzuw@ApKq`(B?xT|2UJlmJoUFsS?|%dN954Ok?;7n-L;$rhH%R;02UQ)Q3Eq; z0x};?P$ZXmWrf)+GgQAD3e2La->I2ZI~1fnbW4$3>J>Lvvee*`9s<;&T+(Xl;M@z2 z=YvBL`ruG5^vY)0EHs4g2LrUI@I8eN?v;@8+ue%f(>A`$(!yXK6qUgovf)D31ML*a zWnOWoH_Hrb@<3n~zb1$8+7NgDc13crSGHEwa)glh0KgU%5)U01>VpCT?~@Ba@8cDK zp4D#U1TAZCDEZSLz(tk(2?GzGiC>>a{;yB-4L)ow%MCNJA8?DGiFo)9t{Z!Ek#=t` zpSISgEG<+Y>2yVDfO z$A9B57Qc&UNpHZPBYd|co4!QvF2a9tNs;_cyq>^zqP1s9FX%*av^o*uB1YuT2P=|` zzOuUNH7dy8>m%ioOTXGZQ%cPWz3->VgCdiaR;0Dkd1LV5hCcd@(V2Um7=<}*9; zS!SqX*&Ucg)v*klvf&DUwUS;=LbPdMKIS4d_epbr6-KF^oRUZH~|%J)}r3 z{K`(M!x@jl5F`qf^A7*;`lirhoS^QodGv|VP^=q#o?X}mqv@6@K zW@%xsJ_TsS@73izzsP&_tFoo9@-4mMm};{NdvzDEi{Gou>?Q8iuY8K8zw&9xroWo- z&an*D#}oGINq{eYuP)=?W3PUB5_aP9q>?*vW>&iuS5)t3z+OEOIw5|qE_Wj0Uj5J8 zi2mnoF8a#Rs@D==ubu$t;`izbdW4)1n=dEui{JOk{3Y#sFUU_t zU8v5dulh7g5BuK9KrepZE7O;-?>(1?raza*gIA?Re=AkNj+Fg^;Ad=#z-jmOBSyxt4T_=Jq?-*bewdGZ_Vm7gh#%NER zNBf>Q&t+b*L*<@^nA~V!79W!fgqD@%gi`;s1gU>o!l!;owRM5h+$f+Hb(#yYG@Xo; z`}j@dK7NzSz0%Cys`c0Zs|L?lY7S}=ppM*Qjwc-r?OW{aZ6DbNSPw!rz$r_L`HDHq zbkme)s$_i4*vhcWFj)T^)X5{dB3&KrCT%;YFt;wIE#&_Ps{c>X3CI|tXRE-E7Cg%O zdk=NZ1muy2v`7!3*yMEq7XWCJm^}a`*#zX)s9K3*d>K&kO+f09y1C#F7x>-&5>U%L zWTLRs8|tMA7$_kPs%IwDWD_tOLYfT51#xIb>28XE-%dSN=#&c#mMa2oHk8yLq@2x6 zhg5XG_l9^c3rG{BEeF#TplqUmu@c&lddB}LU_ykosGjr}1tislH5oE?E(rYv(IFog zD(8j%g0kmdwPv3a`U}b}s(-;hg#Lm`c!Tx&LZMHgUqZP}#bFDDLTJtg$QiPCBW zmmpNG6?%25mE-{aAkMv?qQ#CuG@nP zwCo88acie4l8-&60gDX|_<4XW$^jpStvb^naE(2R1WT@m)T3S=C$K5Qd)()S|-hA=KHKu0;0~cOn*c2(BgN@j_2=`2;@t09BbRxEeDH z&_!L12|>@wP4`!trS>kn2<=^V5g)qg`|K!z1#l)ni(df4o#%+_xUNV(w&fcZ8$up4 z09#bZBgEEp`J?8xXCt>go6lW;6w3{l0CRy`)V70iGnW91trrm0dV!BxN5i5*{4NJj zMaAz_sKMnUI0Y@q$ZSdGGdF67pX}(7hgGp<$uU0%-9I zwI7-e<)EpJ^3KV4kDb$?H(6@y3>limL;%Y`Kl8@cCCyNcMbUI**U!`U2@EJ+g zAvama=N_u6y9nFsG~gD$y_UJdCnda26#xgx2X9fp8XQJ-YE(uwdaacu^*Fgt$$h`me5U{6J><@_c#C0VQlb0;f=wr~&7wDr| zK%gVctck9y96Y-P4ngotk$@DEuvPI0dGk zD=BVjMgsOsFTml*Z=uAw(HCiK}{u$Gd6Au0}+*!H! zTg3{<22)(ZiuW3x;u2sxr4`2U43B&XXehV<#|M4J@O&7vJ;;tv&6t+mG(A2$D>2@g znK?7do#Uea0CBJEc-JgvT4pLd_0z0L>n5|};W-9);Q)?P=^6BoLK|X_weUijfT&ei zi>j?8JcDNYo(LZIfiF&Ag54*;q|CU-PuomaLP`ewT7eeJi(Nsm#oTOsKnC996YvX$ zbuiFeTvBdYW}u5@qtRxX8z!UwekPi=OfQ zXv@Lq>fZwPed=a{t4-iX^xhV*2@7d3%zX~8K*K34L+r*#KBEMN&HV!Qd?B4=9PRL` zwSXlqq`jaM1AoT8rtz+^r{O9634J|Xy7nz? zjHWNV|92*)HCe1Wj@A?gAA5cSF( z-C68-PeD1r78PO&!&Y{3$lPzIBKfAirV5z0^c0i@W>LQ3$jr)i5P|#rtVlli*K=88 z19+Kef~)qF2;95ABKhE3Rn;3?cnTZ;u3RU8h!ix%LH!gmpmvD7Dwv>h`Q$)~=gN?-tMo1C1+`Y8)Lz?*ssjDRjGsUZwK=;B7$HqR)M4}Itb z78-V`27r#jE|vPpk+bz$Me=zIRaHD-vDO1`6t*I2XFIaCIHgEF^Txicjq7;|bigbs z8<80p=&?t}<`|hSZqAQPul#KY%L?|@M#sL)%nMGurgM?Kr&mJL84apPYV$+z#h!wfN={|6Aq zX!}-s4BYu&0q6e)=3LV*lioPguu^|SUq$EEzNWdMX&>u}*%cE*29$W@&w~Nxe|A#T z1P*QrLGoRsiph|zX1MNKp{)$YQ<({eJyjh-bZ z(P!P@8-3~{?4W^#sy?ubda^kJJKcdz$70CE(+Bg3+p7xP!7#5E&0(JHN>578awmmb zJVQ>Z&)_H3ujz4wwK$yW>H@#0Q(c(FGjp?3f=gq1cU&6NIh8*BH3hR&nY=K->qK*a zr)4L%Z5FmFrhbp?so(R5OEZ;QtDUEyHn59IjSVxm|KOjT8(~qLHU#mf4dLV0ROQyg zQK=T-i#jTW;ZI3S3m@oiEQDO_Ue8A#?P3QyYyxTmdek-nfvdQ|k)F~B&7IPS&%9h! zy$MEojcAT^XJ&eKxV@)TM)oO{`Rr|$vi63Br8=;ST37;Eh_3j+)sa+ZdU7rV;^|tR zl!3@e8C>L*d8%*(43TOAhX{+Dn46X5N>6k%%n9;smxSwlX0OTv0A_wDN@h;XfO|z* zEV8pLn%UWwkDPIV9T}}W1yuprB`8XzGP8mlmzk20&KP^r+ekj?Z9ci{21^dHlqx_j zDwYzN+!dD_Tt+6gLhOmH_}H^dEH;em%F!Cv8IXaN4iC7}xj6nsWFG$_pE>7Imbsy) z;6Y#>6qP}e#Eguw2M~Ac0Y2{B^(<~JPr(C#+f^(sW|Sk}=sy(6=bWml2MnB*1aeYO zKyb*8lu3 z@qmCPRP!i`H%OwGoh9Hhhk6{KhH2L=1*8ts)-Ze)n7b{64sUFTnZC`1E>CiEAv3s{ zfIPQQTe61`A~h9II*GO@J8frVr2B6-saB8pXf&KN)1B(hP&eE}=r9U#QxhppK*6Rk z1Ls8YFcYb%2Bu6Nb>Iwa<$UmvkS!NDhMv-~dNk#J6ZPQtHaHV$vc2N-v`kf27eF8oh>Lp!?uh$o^wJ7wyB5QnZgxEe&R=A->fPs71xMN}yKTyRbi!7xw3q z&sRk;Af31^kc&zu4k1UC3B4?N6`_~B%7>oYoHaKjYPA7q@rhcIy!8m2Ur&*I@CvFI zyBd269tQAXf?`J0+N{eTK^Mu1(2LgcfpgiQOdd?f)&MMiI{Ja>N)ikuN!O5Gy2huT z^(#9*;A7JYsKsxi{M5=C5@hx+MP~0(K66nT%M4qQmcT52E8=IC=V1_ep`7or@E-Xd z11qw~kP+PikVR!g)6pFCwxeM^^4{8WkG*x)RF)P7Mf0c(iV&AQGB1z^@`8H|f5P4J@^Do|0pgdO~@;FL> zhb^?BxEXHO%s^`+1>_BcwU(LX3N|=GfOjpdLH2z$X}HkfpX|Sg6m=XJjfTUgE0G2W z@F&vmw%lWyd(vNM)KO_Ja@4V(&=6Iy?MP9_zCyzba?{}vz&-+2y|5oQJI#N1CQ|Qc zm^X3+u$O>!Fsz@!2w=}>{Fvbpz#c*)fbtlM7y;}qGy*8M9O6VLQnzTVOp5=TNRLG0 zR}FPt6RE4vp{w>f6RC@UFDjiVv^B*sMWoI`e?@FD=<6j?C)oFyFnS25Y_H3}gp2=-7JsTvTreVlTpx!L}Kz0(ocQL z4{H9Rcw@j3BC6bovS0>&CjSCP!$%){fi92_zTi4;R<&)*xIXgW4)kc?6?F$%#Y;UE zNc#RnMe>PbRReUCh`fhUcrgcjOWl@9;}ltcp`z<_EX$aG)0D_6?(Eyf=uwBS(>Z zV^=q_;{(=XW1BcjnTO~x^R*8??K=lq6*m!UhY^>e}Bk0yQ70Cy-*+XnRC<-CZRW<=O*}Z{X)Fzvr7K7~cSg=8^IJbdcac)iH&sl53Xz3Nr(GtnKj+TC5ry}_l ze`F!c4`2PBz%S~nA7*h?p`rCH5qW*fl9By|hH_LXEik})M00?L`uUN0-D*Xa%zkE8 zyESH2fkG%W)E(Hx7aEcWc!Xd9Vm~WC75^;%srWU6^O@0t=l?f}V}O0F?KfLT>mtif zmd57!rX!}>#<_-%4Ho@)-Rs&L+OC=>V}FXR5#uIr22cF|L;sKm*^~a4I7MYo<_0da z$UCm=xRf|&oc~{e*BK3c`z1wk$H}TKKQo5TgQC46-{Dk2X99GlGdo+&eRDo?-<;3q zo~$Y&)5cTae}{9LpyV7CciI$ZT$U>_173BS9haEFRtvc%XBJ)KXBMrR(v>wjtcCu! zI7O|6YWTRMR;qDwMXvmHgk=|T2 zG%je+-BBc;eb?_Sdo52v60nP^<%I11a6!<H|a<%A4zWmwR;cVa3spP0&L{(KY5T+>sK0L+~QeYTMqT&qFT9*;-N z7=KXv* zn)mbNeDj`EJp%^jogm!2cn}Gi_p?Sw`We5#>8c-0A?6(~+`RIUDS~--r6csNbiR2n zJ-|XkFkl=&iw?NR2WvSe20=f*sz^R??XOv2IBtvuU{S{nB|;&;T0DnH^|thQM?{ zRT>D9#t8WFl=&8Die_;9zkAmtNe5en(ycp!V>0*+BT}w_F~K$hMf;|?(gVXUM?fN_ zx~V`CY@n@d0pm~Amb_F28p{%pU8rtMnS{ z5y>T>iZM1Td%B2}B;fi7Z6d@;MWjTh4*X1|yMAGF=wBjILb48AM1oofx`v446z~xb z_Jpxp;3Ga+z-|j03p!+oG)dT`isVZn(nMjMVz!VIgmp^!a0T74fnRF8fPJKLwop4C zh%`>XM>(Xepx=NPj89}doaNM4eAtUA~-36VUNuZVmdBJ zKJ!ywhA{gd;EV=yaE+kMm5R~Mm5TYyy;M(y)b|v|0JEqV2xDjVrSHuZv6dD{KI}UN z*1%0Xg#=(lxi}eE*^|UPgS5E{F8D3Z^3^` z17t?D1_%>2K~(*7isU1|)rCcdL`*=>OI1eLM~elkc!>C%f~q- zB7mHl>5Am@X1vDo!t$04ykeI(g;xnHAZSdkBKg1{>}7#rt;hmkv1^449I{pv|LX}5 zgX9x$o68bICh2q_j!GseyZ|1SNqV;eQs1q>r{1uHrH1_fOrRE(|Box2VrQfdjglbt z9XU_z&OP$Pmb}5>`{V!LYPJ!_Wydd$?;M{w-g3O`Sm{{gnC+PA80YBk=;&zTsOBi+ zh_PR>pRymce-7CJuh>`F7uz4TPqUA=53qN#$J?vh%i3dYf7yPu9kP94d)xM^ZM7}m zHpiA~n_wGg>uhUkt6?i=(^#)sPg}pYerbKj`kHl(b%}MZd6RjqxzPNWIm0~JJjDEn zxrMp5xq?}5x?wtN`oZ*-={?iyre{q>run8!lhZWR)Xmh=RL69`$zZ%`{M~rexYzi; zvDo;W@d>C^INg|F9A@lpY-Ox#tY|bEZW;bC95Z}v_`tB)u+Fg5kY~s;BpQYrdKg+8 z>KQ5-O#0jUbNb`@|L8x|Z_z)me^T$!XX}&nBlJD>59{meAJCh1f9uZce$?&LeWcr} zTd!NDdt8^JbLmFvdgS+sYw7a#{>zxHG88`>ANPiYrwbG1{nqqM!XZM6-x zm9xVasmIyOxcXXDkJld6sm` zB+Fn+S4(qCEz5lto%y=?H}etm9`jDki<;#cuV#iOSuwrZ?B=HHl0ilfD@F<|QP7JGH#Gf~w#jrfdI zHJ>Iv16563iBC^e!^gy@qpH3&@oA~5Eh0V*Rbx&OUu;m_e0MPM#ZdLmaN;9Wy>*^Q z|5Ek(SR&n}>XmIo`iH8Q8x!dcRsVc}NPkoHLLrfEQ}x_#BHg0uAMJ>Ald5O866pq2 z&wzTJs;9L?x<=JggNSsMswZD1(qB|Paf?V-sQOa}B3-8H@wG&{MAc&t66sH>{*XbW zi&Q-ff7J!5es3Vsd8)p!mq`Di>iTL#`kJciRugG2Ri7(Qq_3#Db}o_jP<0LbRlBLW zx+{^sr0U8wMEZiND=HD`bE+<1Mx@WE`cwrXeM;3Q8xm<3RiAi~NS{!(u$V|6Q?reYKc7e+QgsoGjSr~mYf7Z|sp^Hl>OHD1gt4)cs-BHRdY7sTt`X@Ss?P67q_?R$ zFPlg^s5)mHk=~-}>^ekxld3bVMA}Z(u?dO{CYTI{XZgUZv`=-b8wZszWvq>1C=8 z+E1jHs5-C>kv34ZKm6&7RP75x^aZN+fdRaps=d||>3OR5gh9BDs@O+|NF*OstJNTqMAfRBh~%Ye6|mJpsy_H8kshaN zC74zos#dH=q&%utfS-E-Rm;P)noreobBOd9Rm;FonMYN}L?X?ls_h_==1|o-kVubG z)qI3Vv#DyzgbX^W8ZD67MpgZDM4CZW9Zc91{|Orh$jI}l~2>d6@p5vJ-1=t3e@kHaKJmji>6zS0T7X)sOl^^ogn;z_c1e)%Rg+jHc?&yF?mA z)prYsG%~1eKDdBL=cxMaZ6f_a)dM+1`kku#;ZM&}bszltzftvT7&&LCx)&zSX{zpd zo=Cq^^~-KVIz`pbClKius(!kaNGGZK$vz_eOx2HJ1wKL551~gtQT6>DMEa4cJNFXl zI91YK0&IzrX$Fmeu4^^JK%`kty=;4^WEs+-|^bdajA z!y@w?RX4&g`_&!Ab?ci%8cfwKgh+#^TAW6tfmGde6lyV3b>n0r^{48qXNlC0s;^`b zsV`Mux=ExyRNVk;U2m$su#-r=sJb40vYu4+@6CEp_1V)z>Q2?Q2~dZXs{Xy%BUD{= z66%*ybtUX5x={7$O;G)ls!x3l)j6rU4CZe~sxF1@cc5w!4AJ&fE$mOEc2r&RD%9Vj zYCe1j+E8`TT6p4|suFw%T2s}#6dnkt>cYxIYDrZO^tT07{d=?KRGmMTNX@7^4;Iy? zRGmAFNbyvC6uRGpsFVj*rCyz)CshV{I9&@GY^ua``Pt}Zf z;R#f#rgw)oN~xOqJ-i)C)oHNu*QTm_J-oC@)s#l?5++rrfN^S2H3`13)v1~QpNVQz zb+&~!7^yl5zA06yIkfRnt} zR@J)M+S&4*B?Zo)g^>Nf!_>)mNY4I$5YEfpbcc20wa2x|nwzn$W8RDDPIi-_gp^L% z;*6YhS5CZZmNPBW|0b_9G4SqWyzB?b2>5xMD}FuL7?w_jbAGE4gFCPbEuB2Fd$*mK z;!I6-r6=Pv1glG@^7p-)4Rxu*&N?bhJCogsak+6>aj8s7_eue&II18*Fth~QPXVbo zsDW^x0_{x!J0wpAt4pwh+%X?lb zys4CobX>`w5SIV1^vd5<928Z7yA^O13@*F{7J(vR>zmT9JS_sP6$(fsSN(RuMDhXw zF9E4qf{j3+OG`xma3$^HZo|^qM!3>5=vJRvE^u#&riFrAQgCysj81TS3b=K^^iEF3 z1b?cqbvW>gsq!enT`SdJWVRlU3HyQA#6xgem(KPz!Z7!@Q^F!Y zSHMjQ{GEd7e&BG&{QqvmG1~r&?VPQhb)IFvrMfxIwADn6gCYO_qP~gFt=*#eThl&v zPRvK-F6pMkl4Y6K+EZ8=G9Z#mugD00&mD65$K;sKpDB`)ys`MnLf?H%_CsC=PvL`r zo*gaph`%+0cf#^dn>+R6cfhQAs`Oz`;RDctQp~U8+uq*+)(?T~9abok&pwBJdNQxQ zr?3*RmttAod$Wf+GmyKzd_SUn6F&b!Rc<5jSBxru1dj;vw|!laeEv$A?BIv{9rpu& zDc+Uf+h6eqAZr_)BKge2=djGJJcSj2xfCZj;wiij$mc|B zsX_7xo(Y6+`Ku!No#?oO?F0<@^3fdfk=z@|-D0>R`TP}B#VX+rRyp7oo5dOGBSFw+ z_(sjrX@M`qTKh>rb$_ z4LpSwz!iImOvZ)1Ah?K-vMyHP-CXw`Rd|a=vb1eHh304tX3o~T&TQ;No!NX-_j9xG zur!+hJ}TdmphFHpYhw=Y=GyltA3U)<3k*xM5rCtzG%H>`HPoW;*Mb);Yex%?OtX2a#tJUCh&itO?#Pfe=;^+zQ|LwC? zvQDsUG2b+|F?k@f-ewrDe@%B+*Gs!X^OL4QY;Mda>H;CzeUPn)1Q{c}PzAIPwnKN9-t(ncvq1XfGP<{_=9oZhhDJ~v* zApR7m^dN3Z99{P(d69XNm&;smDkp@wNi><&tI@nUsi z*u8|04~z{U;z-$lGSbaOE%>)Liwb9l`hZ%BXNM9j?DxrsF3rQwAo}n#T;#&C53$HF zit9yX6tm$91Rd5}k$m9VhgsmZp2E5ST#7FPa%{}mkPq2_^g}lA=|`!q=)xSV1N7qO zU`dzy2kl4fLHoJb1;G@T?H?_Xo%j7^tM}(yy|BKI<%hviGn#`X?1Fz^xsplWTYR%;s7}mqzOMn;rFgzC zVX$DPZE%qEkt^@?$>7sAQF-ejGFTmGqZSzqN$tRK-D|xf`RI)b*zp0gvKpX^pOwnh zZmdKeGZoN zHnU{MW;c8~Xmd9!zXNwhu%iXSQdOV>Q43392bBDGG+OwfyKIB4hpb7KE0)<7n|YnNt?5hCIOAF4EThS=#!wY%|2NWY z(RGDe@1r%xWA!mBW9q=WfFoqjz;qpag#X*sIztzx8BR$3$c|5Tl}>fv(7#^3VIZG! z=>`yP6^rSQx{&y$ENDO{!(dM8HJHak;yL}R8ZA$9oXL0y2-$=xeqEXy4YW;VYWjh{5)xeRI? zMB^v*x6P&(K`jNLwFdO6OGvUVHvAM4g{ds-txBuz5`eGl(|{UH2ko5pQ(qz-uUK zZlJdiDwqgeUDb|0D3Bub7h`>NP<>^V4%}=4?N?G-@ykMoirU45H%ML*x?fkf82Bb{ z5cW;$Ti_0iZshd6Mcc#zP+BcB!6E#x|(zo6Wp z>ah2m&`q7(VhQ{7XEFZYnmD@KAGdvDdjR79Yt3iPElu-`UmD99M(H=`F6i26^EE$c z>cq~7d6V2CtqIBNB{*C>*Y-d^?QGbAna0CaIl z3t{L985yZAXL6EG&84vmm@24sN|QU)2mJW1}HxI|}GQqa-` zCd4l=@hx4T%3=XacZ!;&6S6X9X1nN$kv|`i^XK!CS50CE2Yg*R00_UUJ)XcsUu@^R0B;VM2)x|gX9JU2)fuBP)wi2m8 zR?kL7@|jzWGH~H1_Ces60imCO4M^xb!TO^{1n9OI(+1Dsstz)<}IQ*%>ABPWhIPD%t&(42fSv= z(f^tEi2m>Wfwegd^XAbU=Kc<_Q4$;{$;pZ=+4%qb(x&5&`xth!sRyYRlMrkAk7>MP zscpAyto5w*QK+k*Zur;mw4oA2`fEew`&Qcbv|Tj&HA7>M#*T_P7L#CgSk_o-o41-f zJL=fC+dGlVhA5Z#q_2BR z=Sli|{lKpD+_aFEzlu($@k$!&?t~{BvUPch;^&oW1=~GO2aev-4poKy#_%t~9lY=i zg^;jASnDd^EWCCRomm{otqN~zluo6*kdf_VTr=nqg=ag&ME#kT7-uFt3nC`K$~Gta zA>qxD(y6${F{123^uK4)iBt@qAajK*#vy(mde-?L$x{^4MLId*qCV(z?m4c<^9? zOE4}eWc-GiR{eSTPROL8jpF_xurK~r$hMzdJ^eMV6+FRN_nq_eE zuN^ZT{?q?;|I331)W?JWr4%1fFLBv~(E&dcI$Cz_Rb%(s8bI9&3;K{rmQ zgHAn^m2W4azS~lfT;#=n{=*_eaAhnYiwmx(k(sYA(!MQw{NLWlrOt1zO7MWY?_+>k z+}(FIwQ8Y4?j2PW$>*-#fVDO_o<{?>ILEV^n_cS=_sv2@^07ybX0aiBKMJtLh3_eL zaKS{*?XuH$JKt%WKV%Qf3xj%Olm@lD!&6ViH|8Pz8}s;9u635BZs{o;0n~|6NW7A% z!)D_a`7Znx{$2R|v8n(q1jL5}xVV6L=ysuGk?H*6quqZCUdmbe|1yAcuvK==(~6v-V#`Q3hJ ze*?(v902f9%P7FW+AZ1RQ&HIRSZYDIGS7yteUYxQ=X!oI*?iqFvBYtV;9MiBcsxp2XA z{K5tKNvh05Fn^!unm;_eg8XaeDw1pdeEnCf`C(ty8~CHKFOvs-*uHFyJX_b?W45}t zG2nRqU+q8t7upWls#&K){lBZ`W~N!jcMP`-ZS^yCJGFmln`?4nKZBR#hmqA$I{xRu zu4_72RNSs>N^W`}89#W%z%|R2n5#<9|EU9xg`YZb$3lUp5@S;T&4NrI7q`_7BTsT= zre@5Ra}E&s_*zBs(I?zw(P8b*0CaI{cNls?t~-_H2OoP7sgFI#r(SiHrG{;8I#5Sr zn~N^ApbO{+xh&2P{IWRtlgqNau+2>a-e_!dWtU&%ZSG-tdv%zd;9{O*RuSuVN3@8Xlxi|{t`Bf`*P9z`*Qi_kNJbe z2lG#fuK7#aFn;|U@_+ptpMQX=QWtC(UBDlW4Wn%Sunps0xnT5OUcqQsc5)wJ4G&j8 zlK?y#S3ec-NSQ%s^F7Zil56|LcT^AGzy>W5x*%?YM$dY37a{})zU+qRUv}f7=Qpg& zS|8TU1VE4Cx)~`)3CTa7ph$iX%BkMLfeMCB=z+KjhSd1}!WF@-+NWEQ_S3C=+SaQ2 z;IJW{47B1l#A;g1RAv&=KiP-WpX}pOFaG5qJ4zt*H3_Jr5&8-g2T_(5nn?e#Tz~fC z-hA!@Y%x0jnQtO+i#zj$Ses5uO8#L1TKvNTE_r^OhP5~>=M#WD8q0aW;=u?31%H1B zg1^6m3%>a38w|J^j`P)G4iU{VP3_qC9R-ex_6_zHwy$ghtcR^*ET=6~&6mu%rkkb( z#(#`?Mx)_bLu368eOKLobP3w?+L>BS?2wp4F$v@nng3t%4EWQsX%d%^{4sjQ^yhNS zaAvuk390zh^4~&|N7N0nZUiFT7E*ag-Jqir1PS0smZ-A(fdcF zbAoTF$pj&eJ0krd_W0tIi?%}0}IM&!I#ElLjy#lOJlzZ`9OsAm>wSkeLfYPNfpT}o=qq@xEL{YmgN4fh)m=|_M3|9;ZlAOBxz zJ8r9Kbz9zr_y4+>78}1a)-|N+x9jfcI%|DU|F2T)gqRKFD*VSG|I2ISDe^zmC@%h* zoaM|+nVuS-mJ3%G+_VhV7W3(V&jTda=dmQQ2jlbb^Xi52(nA5RQ?NWBrwL0HZZUP` z@)o?kn&oZjDbfjbE`{>4r!@pOe5^=5_~#xLytSuD3*h1$?P1`m(-$J^TPu=}zUvT+ z-oaC(0d#RuZVq~!at1(fZIL4R9oW{5?LY%hQ7m*ooS&U`K>ju$Wy~o>@@ZdGC7!hK z6vY6oIFGfOHaNhk`}FSM0Qcs*gZbQURq2;Do+1L=;)3uY+}W9~ME4YTB9^^S)|Jh7 zh9mr);e7a=gV`YhH%;aPyttbtA@Etb>HZR~)aJL&BlfNHeC)NVR88=;KL*(1eC;9F zLFWSnzdjbhuaD(}Cv9Nu4dIP>04^@P5duyZLrQ*S8)?R$Ri6Rgp%RjE@3!G$y0p z;~X5+LF^0iwXX|>eC)SkSz|+}aW-H_W8wB=(;*$?KDQgqeQr0O`-60r8!l_i0`6#h z-__h~yad7jXs1Yi2QoipI{-)wQ~VH8mqPp9zHiuYq1BXwfrISu_{>v@?3I&JQ~|? znLNVuJT(Z>PYvRuKOdUXn;oUmjehswa&q!j>z>BofW0gEyoGMM)wIh zoA(4io44S##~E;l|Hl;R9wLrgjw_CHj$a)=I=*-8ckFh2;@Iif?s(ntlH)nYO2<;i zVu!~u$C2Ymb4+nea*TEiarAX`b98XDax`(&b5wUc;3(&?IJEYE?APso+Rxfg+K<}5 zvwv;>-2S2cZTnXHYxWoH&)ApS3+@r~YsnvZRKrNo6dUIdc%6j`n#pSrH7@H@rU@ zk1`K7_c1?WZf|aBjx*OaS2I^Kmo=Ns8q*!qHPc1YZ>FD3KbXEX?KOR7`oOfqw8iwQ zX}xKU=_ylz$!mJdG}Dx6a+?xN<4nU%157`F=`F}7_J-sG@Lb@G#oX2XZYIix#2^@+lH-%*9FPv2eNQQul0udlDKp?^?c zUT@Xwba!<(beD9$>weK4(;b8ik}q^0>E6-3q1&i?QMXq2w5~|!(=E`=)@A9Y>5_C4 zbR%_xbiH+5b?tO5bd7a&bPrj7u^zJ?wEoBXh4mxrJJvU>8?7%|*IJ*p7Fm7P1=iWt zEbBCDl68W0q;-(Bx3#OaowbFvv9*r%A!|iz8LP<}Yx&!9)pEgd#&W`P#B#v$mE}{* z`EQ&HH94PE4Y$&WKEGWzwiVY}UMDYTO^(dZ4u@1#^D4s>J7R56t)}UC8Vik&& zC|00&8pU!HPoY?b;z<-sQ9Oa72t^@^0u)P7e<~3dKkiBTx)SF$~2}6hlx9 zMllG*KokQ|^hePTMPC$sQ1nL83q?;9Jy3K<(GA5TD7vEPf}%5uPAEE}=zyX?mv~tSBrf z%qUDKj3^8!^eA*Fv?w$vVo}7PAORu$i{dVde^A^(@i&UwC~l#+iQ)!|>nN_FxQgO0 z6jxAOMsW$npC~S(xPan3igPIbK=C_@vnYN;aR$X{6u+W4h2j?!CsF*2;slDHQ2dDE zIErH^j-vPh#Ss*TQGAc$5Q>8+zC-aXiUTOVL9rjjJ{12!@imIQD853m2gPm_U!wQ| z#pftKL-A=q_^>NJ?1~S&;=``^uq!_7iVwTu!>;(SD?aRs54+;SuK2JkKJ1DQyW+#H z_^>NJ?1~S&;=``^uq!_7iVwTu!>;(SD?aRs54+;SuK47x?7|*>g5qNoAEEdV#Rn+f zNAVttohaT#@eYc&QS3nR7K%4fY)7#T#TzKLqS%6BGm2squcO$6Vk3&zP`rxb6%;QA zgoIs@uqzUFMZ&H~*cA!8B4Jk~?23e4k+3Tgc16OjNZ1t#yCPv%B&u>!@@D3+sm3dJ%MPoh|g;t3Q*C<;*&pjZ+RK6$?9e<~3dKki zBTx)SG0bfH0`mWV&^RjDUoq{n4YB@coo4E5JPh^!uNdYUjQVHw&2?Yt#%V8U=WFlR zyrgLp`$g=)m>(=REstBun_n=;Ir8nzVp7Oe_>1yF5(EA#s*vQ46qhqKCnetRc+Jkq z$bz@Y;!-mbovGmDA-*a?@+_Dpr{}tIU2!vA2`L#+wl&b^gF=#K!rIKu#%I`w?*Snh zEMW}>Q(6MOEGs0NF|5%>uJILgqbf7xqy8c`w}|zRJ7K5?+ zKrf}cLVnGVUeYBU8~q0kTGK@CMgv1OFmNgh`Dld=oWMaQE-5!HGtg=!A&UUDs{f$K z#M6oNKX6YxI)+Vi!&b|mLXVTOBIf^3B93A9b+$ikZLLczhb**fC@FV0g`74jlR2rDVe3?2EX4%{)a90JymH(lBtvt%I~3hbfXvz2tsX zxi7eiQ37lq*|sq-}M-BKgz@Rn$#AMfU-@Dx( z5w-=E{NB=H3?F*Cku^08lJe0VB*C3e@LSpJ4eUX)H~8eg3}ngSTUidsqw=l9V-r15 zAa6WAtiC0l|FHU!atm2*uz1<%TAX#1BYBfXisW1TVhffW?i-Z>a&h;K!Uj0wLiO(% z5xQ}LBDwHOG^*=>%{@g9fERbgAq+m~vPay8lN8Ct&i|`3YjfDc+5tN%dsyoCN78y& zTyjgjdlZ*^Ih!Sh#oGqNQQ4xXg9k`m8=tPzt{+6d%YB(jBfm+;Io4jv@9}Z2#E$TUS_qwA6s}{|-}(v74a~^1U6pA=-_oF12%l`+Ge$C|RA`(qVp zRoh!Q2{nTrh&#lE^#Eef*@;>11O`3nI-)0C=b{(hDbG%dww|JkrPG-2_ z6BCg>F_BAOR9SVU6qccQpcl6cMWCmKg0 zpr>Ugw`~@-!c1s@^b;DCOb?F=6rO0u(nHycMnEs_T5Oof{m1^~+z3nLIJ}R%WgP!L za^bgx?EoB*8bSxe9gxC0FeNc9e87+S3#~uqFRt~A%qkx)?AsdvytsXP7<`~!Sa8IT z#!~!SM)OPY7xh++85r^PqdVfAnd#Z#HXnHoZ9eiG*XD(%Rj)h3B2y3O#Vs;{%tIH( zCsUp2$+?iDN7wcdCWIbg;zH-IKF^MF7$|jx4ipwTF*hsAm7eHksE5r*>S6Qw)X%-b zQiG}MM9tKR8BlE`i-jI?389Bv;zK_%j)i{MQ&bzE-NH^FDpM=aahWL@>5Rb#cR}{S zUHI&aRWIE@jHMQ^i@S3lncWqa8(dNb%HRX<0lqx+a9uNc<2wT~>C#>4IdoR`e-_Q% z|5?7dmucCd(%4f}1E_~ZX{aPI6k1nzs754`db7PyY5s5$`m5Dkn;L`c|YfFk*% z1!F=;s|h8gev9DH?IrL3dU5uD{%4tXsJ1eud;HEf z><6r21NHx7^#tx9kB|L5cCKTEqZ!=VpA5MGb8K4ca%(Nic1t_+9`g{>A=7x{d1Ho= z7<`7Z`sMojbuZ}}YPV?H$LeFAj%i4Cl89LvrCdEdm?j}4O^fc2{3#)*VLESnA<3w; zJq&EXk4b#(BHA%4G2WS(IWxdsI% z-AeF!pg1do>p@E)#hb&-oa366lLnc-iR$jQ5K=}tLhIqaS>kIhcqx=^9kLWQ6HXO; zM~&dPBfdsLu0e#g9pZB%zJ}3RBNcZU@imCfuN&&=BEI@UhB14PXPs2US5Js#+4fZa zCE}|qyo0Q3i1_Nv(1CYH6F&kr&e`#)aAmh?dVKbOce}0XV7OO@_-YH;KSgd99WumM zOZ;!i`cjCm<}@9+L&Vw^-5|tQBS{CI3_)$l*PwjWg)~BU+JVnxHMb7@2c_K;+KA#e zAijq%{(p!#I@*1)ZZY}f(EqNW zengr)a5VP}zT=2s4D_C#{M)UyiXhf~h+RiMPj?~=CWpgjThq)`*S!&1u?GDu9QnN$M zO}G4%e3_g|vFskH6x&rV=t8`$8<0mMl_FqoO0FI)OCP||vh)G|X!*1)Yj?;Qegx>n z5t1oGR+)G+;xr-i#Ct&?~yUQmm&ux+iaiFfiEiMjJ0=L@ci=D{6*vV&) z`+;SL#M>^wE-vvlgdJ5TJmLEev3=k1vDJ@VL%LIEz>Y?`Q(&OW*lLSQ@@SFxqowde z_F3J$CZ3{BfIdoC6o6XX@2OUNxoG8uixkPXcJ1oyAc2Y55s;%XG5yGNRe?PZ@_OW` zn};8DE2^hqx#9EE0l1^_`SEir>q(G$!P`i`;BCIOyY6MFVT;lpsH3q(@l(q~I|%*Q z&j|h4&s^xjyMM9JkUiWEpv7em(@`Cahal(Nxr*fS7S%{)d0}X@jndFS-jInn>tCdv z^)H{g#YC1Gmc2GW9gSsArj9Tdr}szn>HWFrh40R0(P0n!FrY_c4=baGO~;I<5Io~4 zKKP-LEO>iQQELF79)`tmmzdnp#5D`QA`9K0$v`{}@zmU#_bHHO}j4-qy5>-5WbJ=8)wM zR7x*ne%f5e{zi<;-i_QO3nQMz>Ax%~fHqZ#BTSCR25JCKf%0bTvn#|mPDt#TZ8IS^ zaT=D+@r@PY&{P_e*FmPe(SoBa^4qJCE;kV05W#+Nx$*E&)?mS*tYE|bgCy|{ijI*Z zhq49=8BuieCHFNL${G-zA2mFb)n9NZOYUgIP*y*|p)9%WuuxWCAx`?RAD4!*`b6i~ z4G(4Y7CemAzFFeyCFDy(Elb-|TnNP1Q}C~eZ3aD}#MeVe1*(uv(gOpohTR1Zp+GNb zqtv|JgyeOF^j0}zU|$~*5-%*FN!rt{u*q^LK_N)06p~#=DR5g6_|&x%GEJ5Ji@Y6Y z_Aet#+9{S&{-eC`&WMoZH6l7qho7B@Z@A!vLhiNVDI~sOg0sAo1|w&A4HZ%jkdEKL zih*jt4^4bs1gCbfEz)V*xs>ytG1Hg!llA@*UnjxKVVL8V_&UM~FI`!eN-cdtSsmol zjsFA}Sc}F8F{jd+ycPvp8zp#7hWL|-uY-`KRy|teNf9t-dw>4_x0-FlaoO>U<2%P^ zj<*~y!+U>=9J3u$9pfDR9Ub9)ziN&$ju`tD`ziZDc+YQ#{T2Hv`(pc}_G$2f-vE0j zd%V56y{tVJUhMnTcF6XH?QPquw$<=L-yB=2ZGvr}t+TBuyvSG1rmX}HlHOOQ_e`&wo;4Mj=EKW* zPSa3RH&aVf9n<|LgYl;EcjHmxUgP`5Vt5(v3F89ebYp^Xn6W#&gjd&C(P%W>GW=mU z1~1=zVAyO}XIN^;Gi1R_cf$=m46P0I43!Kfc-iip{`VaM6^v}afb{>7UK1n}9 z-&6lEyj=Hy-mLpucV73SZXdiI9pS1h6 zA8X&xzMy>y-hj*1PSK9i_SUx5HiS3dteSr`7d0m|-)KJ3Y_q0WC&JrwU98QlHLc~X zTFW(fi|(*xx8+^SM$0pn0(g5a-7?8C*wWR~+)@i(Db$&-n}7R1+`R{wRK?Qx-IMbS zpdgA!4g$lHa})u|hy=-Of?e3e29g1HM9x{#?!p3sii!vb2+OJ<7(v7wzzl+l0wM-P z5e(>8Gj+~%pPAX_hSPJu|LgO-Z{1R~e_d1Er@N}U+xaP+z}Rbg%v5H&&os+4&2+nI zfT@eAx#@b7$N0DLC*zmKL&p8ar;HnnD~$_{vyExSvBrVMuErL|+D5P8AHz8{4C6J~ zOrda5`GEkDKBwybUx{>-s{4i$=?GO{T1=$RsQSVyMEaDf&vzrzCsf`01d%?b>Yi(e z^bu8e&mq!>RNZAH(g#$1I)g}usao+Jkq%LHXEKrAr|OPVM0$^^+f#}3E>*W3C(=7q z-P)5#Z&US&dx`WGRW}nNy-C%L6N&T&RX2Q1q}QqX*jOUHM%7105$PaRAAXNWuTpiL zfk+3a`XF@S6{@bSAku!SuJIFTA5~X_HD0Fb$}}RqMAci8i1Y|m`%Na&!&JTb6(X&p zYM-V=dWfpMONsO#ReSzHqz9IJF*Rh?^zR7h3(M?|`Zsy6VA`Bb$4)!kGzK}_l{su~s&>CUjaQ1zwzA*M~$7hqV8qw4chi8Pj~ zd*SE4ovM3!6KM=pcdsMTXsSN*I*~?E_30L{Q=w`_4(ubSx&u6R1XZ7G2Jv93ZtX#& z;Z)sx1fr-^-3YVjP^xZthDbxG`dBq04W{a&lZZ5kst=bDX&_Y}8bPE1R9y?B>=vrt z53^Z+s;+`T*N>`Y@K5_vb@^{Zx|yma*Al4@RTsA<(oIw?N+eQms!CwzUQ}HOf4C=A z7s#+&r)uCKSV~j%p53q*r0U&Y5~(Xy@4ORE2~u^=KSb(G)tQ6ga2-{%SHQt3s%9P} zQU|Ke_?AfRsXEa2nJOr zy#yyDs5}s*Z&2Z=&i5=^jSF9K-EzWICenQ+n}MwRK4{a)a+ArcrU1>r|M8p8&GvH46FK79ry{b=_P>V{$w1Y=M#2LrRQ>&Xcoc%Fzl|dc z|EB8s3bODrRex>)kDgHVr}gkE09AijN*4Y>)w8dYg}+nvyDntmC8~Z~P8MFI>M2lv zqv}aBS$Kh}Uk@V-f2HbIo5{josQSh4WZ`+L9`8mL{!G=+A0!LUQT6C`WZ_R#{Vba- z{E@1kz<=rotpDFbd^dTQc;54P-NRiEI6reXa!j*7ZaZOXVa>2?GhZ~{Y$`T>Zfs_l zN%p8a$^Wq|gmT3RPw*#`cvd{?R2s`gp>a_Rr>$Dg5 zna)CkoyWw*&f54a+ILTHRr2lJ;u4Dtb{-uUJ4dFs5O%k6t@CdFwa$w>YfcD3k>4nQ zjz^JVr8zR>f97>na*e)hP!el&;2#-Z{^&#-azEWdm0bR%pB`fQp-AyI;EzX;&L&TI{b9>n9!mePaB3OS_S+C!Cm`mO_67lP|=hXH*&uD=b_ z)AL%Jm8VxWAK@}D{k$H_3_de7zCIJHRu8Scag-|gJ@{!a+XMJU4S^nrTMN*@;=}>?P>46 z$Mue@hI6{(Daf$jX4_!>)7sbafccoYv8llLiqUNt34b`Qe+8cq%mw?3+jka(F8)v! z>eKzR{lOP+(U#wzQYF`>i~p{{dIW?fW&*Le(1eCKDLHp;PQE|*_rly~havabVSMhV z2D997OgIO)#T^sYa6`>%c2*k=_L+wf`^>|9>|>fYLcl??g*r%nYGP(yg8GfjO`S^D zCZ{hV@#%|P;wAm>VGRuz#byDqxQk*n#94{VEup76An>UUeBfKRvB2ONnL<571Du(f z2@g)>rKJa7e?{DHmaCGF-RW@_8>Z$Az!taat_0hkm!FtlK)vL|ail+SoKN5UI7<(= z^UeTzakuj#eXwpZZ0E0fBI#E>`J_D}uWOzTq~bo@loU=ftIk2~`$aKQe^Jb*ZZ(^= zZ^OW{bfE4d?DQT|L;N^w-eYef=&?8Xpj|cQg)4>A094$S!eLN2-OkQ#M-L9rh27#bz!kS!q`1@>!Y2MK3zQQvx2m0aY-y_T?+h9E~G zAd3rfs0j}RIU?cl#tDRe;{+eNshfp{73UOy7Plo)p+jd1g2_kvt$Td}62CryPdug} zOAK@JWFQtdCu@k&$dvh@@*O$I|BfuKzn^7>+eRh??T9vhwIkog zBbus$oUz3jB|20DI|C$foY6=7GbS03whW5l)+gtAKX4veRilpU2A=djjN5d;6HHC^DY_d zY8yVkAmo6(X8)Leln{`j(^y_=US4`OHaAzuAscOTnms*~;|ggq(*J|2 zKgFe>x>U%~>sYDx{?-Y>;fw4 zh1_sM8m6$c{D=5ix+10Ld2E^y_`SE;fjpeK=kqM zZ&O!SDv_HwI8P(wGo!Yr*?+-l9a!Yf5aK87$2+v9y>qUmFkAO=#x~>6oSNv*O-;^* z*P`b7le5)()boY>g4&k-DeZ%QBh=G8ArqM97o_`9IASH_;taJpb!!&t*(4#BjBHBX z1;Y6-NX+Vg6kqep<%e#X3H5HCklS>kddE~R$NSzkp%bU_6$;-qFjmODJ(?dc2lhNU ziFtW++f!f!m$|_>2>!q8P2W;qP47eA`ko!0PVRl~!H!}_E&FDBQ`;`vP1bjTWTuMp?Na4_<`}_O+-XwEB!L&KuR&NGpfhGedhj#k3c^;65o4!duF( z8f;Jg2HM-9%LRu~{Yy*^y}lE!rU*WB?1vQyM1Yb*E*t_l007%``Fd6gpe&ZdQ5ksy zwE0AurEti9z3Q5lO?_800f$4DasV3JsLLLaZ7gE?Q@<_p6liUOE(>M0wW!H2e7BU` z3mSYxpJB<^GWLk{rxauc3q^=r2U=aHkJm7*Mvh4Tti;^(#3bcHqRY_c1G={vIV$1y z+T?;vc%nMkPw8`LbB!*G6ZYqf9GS3Cn4O&)JT(RfsG-GGx&(w{wWtimP%&m`ff8)j z&xYI|fc94i*(YemC)?y)XtG$BA2#wO-iT337b(*1(B@KIKHQOQRz6mx&d}&HT4+=fl1`!1 zesE8plA4o|Jy)H97yb^-E)dcz9XG*dwS#8iXV7dw$TS!+aMUs|vTzSHIbWBN6ZxyE zO{!5#h(;x+CBh_;g{$m^YoO^n^=Udai}|4Auu(QK!5~;-L4F#1TZ0SG>`+W<;cRGn zu0Fo3X<8jUYM6-4xGo$8jn3BR*VQyi=l)=`>SeaU;j^$k*8k57*8eZ@9QM?5k8`be z{^;!LD6$`eo&R*}E~~*Z)V$tw3U>UG;ke<(e{GL{8@Ki|qJ42)nTtPg9k92Xa{#|Ji`GbIU-n0a(QqV6v={p6tZeJIkGG`N(BYu*fj4 z5kMAKfT=-Nc39!kz;Zht2nWfBUY5#2LpkGofEHKI7z;Y=8#X`svCYqAUQ+cbmKhGC z+zrg)4x?z8W36kD+M;~^Ed0;k;?MfB^ibS*SNz;W`2fxho7|*)T}&x_lh@Lm@PLx@ zI{{ks)PXD5Fsor98rras%ewf)X4b$^Q+x-oimNF`_fS^bY9um53fF_Gl28163QG*t z=JSA9^kkec{VQFST;wH<+OxKO4Bkou$_}w89-(ON!tZ9#Bpcu(bv|GN+8h=Nqb$OTKu+b1Zq6 zz_NTG&lYwFOG94yLUqTvQp7)3%Ey0lA&U>6$UMLoy^>NUmrPnigRnpDP$d_7NxklvOUraY6?_^>g-CqWIsW^WhI2c8M;^KQxA!1a`C0Ng)6&GEZqiK7YJwcpEj z*mk@12Wz3Vs%5pMnfV3tFw<9tXARxRTLcnKp})dW8(oTRI5~rG`c8UCmv9ZIDNIkO zA5OSF{ePJc2^;vosj}mAHfAhaTB}POJ2DW6qf&{-F)Kf~&^%7HcDkfSV|Pnkz0kud zx+L!Sjj2l|xaD17Yf3R@IG#czeUg%~`=+!OK3NZM5D5I)l-9y=aA|cM8VlA!z%Byb zPY_uAsrD>p;f1tP;0RY+W)sV0x>U7rJw{CeN-K2v7;)QzHAUzLTrU0xjJbS)_cFu} z_>9D))QnK2nN%WvRH#=p!DAodjf&s+$Z{lUnUHfZ_}vSigIOxjmZ2mFPSp6rEfMG@ zp~jd%A3U|9%i1jV$P2X=91K$vlOcVF-4m0CraxHJnW7?HN*OpkR5Dob5{t z@(G^05pr4zO^JCUct1zr%p6RiFiVvC1pZKLwg#U4(PfPu+a-c6Rq_G2SKyjCoFjo} ziv&&}%2t5+)d~eVz0#Uy!n#MFG<U-~5UyIq{J>eO7gu$HYepAu(MW*!4?H zbJ*2j26Faks!BfZ_){!z>p=1Kz^mU?TpV6)L%|5a&Yj$w)>*D3&v0^jG+@qf=`RpA}u5>rw^q^dZ~S~DW|R!Eo32zPAAk2ZEPkUvu?O(Q-E>PMH{rq9_&ky}KF=q8Q?pirZ=yR6 zt`QNhL()b{Nn)cblq8m1@!=dxw(xc@IAzMDhu|J8ISxgK|(clLt% z|1az!I9$uzo+tQpD*GlRFn1m;^cB`Qq=#chCjkZu(= zl`?BiTufCKYEyX&HGs|1+>#G7S8IUPZ|15LRul3@`zHUUO1@8YAHe!V{XlUmK<+8j zz8Ez}yrjOWPAQ&jE~A zmSf|2%Q2WD+?x3emSfEUS-+KfEMset!wbl9gV4z12JwwN^&{3jAW+y0h{eXj72=?W zM8^D)`Sw>;$!G6Zz_Npb+!!whVd}sTbqu~-S3af(A34LsBE!z2DIn{&vxwy&SmPCT zj8RV`@u;Wyq=Pl@)wKx}Hvv-ps*Nirjl6FKaYtUONuds}(U!V05*v&Nnc>Q*BSA^H*{f2ZxFB#H_Z}M6iFM;7$AE@Ip9J52SbQ>-9 zAbdivd{7x5`|cvv*x)Jk;^irv1;~I4X!8LV`0xo^SopSq;<^B@-$@sarv%~I>jseb zmLyg3x%1v&x#62$2e`$4)0G*e@^5;-$;jSsGN1j9zZmvl{eNAfgP2Aczcc3fihMP^ z>%1*I&w2W|KXRwJesh(&8aTH(dpZs|CfI+qFM>M(_S!~RzqZb{x-E}dnwoc-dzcOy z9fk)CO-VT!L5MC@Y_Wd0P(XdQ1!lqj_V(dQ|Ldv#n6n>|Uex8Tk1MuIw@XBNL6-s> zUXwKc0~b8$QWnK&EnJ2BoGxWiv073`NQ?>)BCXS<#EjFdTD(F22PaWPkBXQxJ(2c` z9u<+3G?DfQ^B$V7i`p|0=~-P0v|@RW+AQO=>@2WbnA@ri`=|P`W__3Frqo0ik#xE{ zleyDJy-X-Fz)Pg3bt&bG_0z@39}wxOX%+~tiugi>nhTc!R|xw&gxb+WM2WOB(E>qD z5xv4-CXvd8eSoxaNFwbJ_6xBgL?Uh1&k*yP4E8JP{^}(8*?^ zN`44s#Ze}NQV8kE0l+ILsm}7k;fCM=VT9Z`QI&ky)seTU-2$-sU5Qkgai?Y^P7AYc zz_%&OH}Kx3gzTQAxyc05)ct`~P@0-C?9{|r>B*sY4A7*Hja4Pzv`aPNOGqsA16)D* zQwA4?bV@p04x1Rdof}af9i>V>@`BG<*98mrjf;hoamwK9}8^#N?LrA-QU#94(0lM(pAWIk|8M-~{8dN%>E z*rc8c9DZ39N!M1Wl21G<%SGzC*T&F;Z=rXkUMgxhRm~+3Y}Tk^4aIk zVA(qdiaP?ke)rC5R{UE3W=~&7PAK`xES`UbS-edtOAlYk4nQB5uVki@3qfn=D%C}~ zSEw$k=8WKNA1_`tp@O_QZB@zlj$V@(-eCT}j&TAp^)$X_oZwsOYvSGO9qReqlj||N z*Sg!f-f~TG{^2Zi`W!1AjqKa)ooxGTBdtfR(=2B!GtGaQSDG7|Dh%Hn<{N5~Eo3zA z_jS24gmp7`6+`!+p7y1U#Qgl+^rV7(ynyQqT`tjx=t0ywYtnJu!=kiPN>DpJDLd_B>VoUhHDGSj(3LE7z+DB)kqq+y0qgvDs zz9Rw$A4Wq%PV<@W`8nDzCFoj^o8i~??Ni-7HLB4(n8>oGMYQ|LU6#Vxx+ZX=+RaVP zz&A+K(sLqO|5%r&f@4oTim9X8{7Cnbji?@{XXU3(OU;ew?1us;b+xnMN&N%e^9E79 zoSKoHm>J{dM(Vcz-&aS(@p`x9#83e+|U6 z!sM@r^rrr0Eo@Ut>WN5i=>BzP4X0#{i1fPt^*~H_Xu^j`uj#(CU^@hE&*W-|bWmu& zXqtscuj)RS)gn7(Q5>}#KA_8GzU;&m(PB8cL8Mo7|H?+T70yc#X}|t1qK%s{DFq_! z(|^*?wx(tSi1ae%|N9W%DDP^|m!5j=3|G1Hg0r(jvcF-kVjE&Dv3v}7{O6lqFxicx z4O_@X(kCLPUkC@`r$ER<%t3g%90_LZHD3=5cf9$hD!E~g6}M~dYlArTWMCE(r`9sF z8vsOoW1cGc$SXB5NO%Wr5+IAo+*4$X8-!!(udPPb*H-gcOR|}$QXwP|CjzUO1Y#sB z)Nx>p14$1mw|5+L^NA;F90Km%ngGQ5-Mz(5V^PG+dJmxw1XRg~UZc5g0P^AE0a{Ex zJPJC-;M@NzV(8;;cbhV!ZSYH}Aa{>B2e=<$c^ z>UEdw*vdL z_&9k~Bn#0izEdR^eZ~5-EIOEdc>K&B9S%e0ol05RPJUV0@(Y@m3}KBm4A@1lu@ond zT4U`vh44F0@eRId9cys7T5%{q>vyMY?1iBU9V;-0*xQvCz_;^W0H4!mMPd~eAC`zi z0AKVHQNfR~MBJtnsgW_wu-#xJ!z1?p8a24{3qG1D=0i5MAS*dPJv%EeLGibwg7l1(@LKuD z8EAnYXK*dB@_i#?fkIf<2j9ySy{^ZgS(x?vuaNcouehu$9{P=Cg>`-Kg-p@wdL_UY zdtHBaJd&Rs&m~{}r{<`~E3E6k9ftP*c39>!-Bl?NzT=eBX-OQqc*)!v3_R3btUv@?IFS~NtS1h@UWrtOA z2C$1>B`ao+S|uNU2BD8X!-w9L#6rU=c?Lj>UL~v0m9LVIH9`DiO}O~WPik&ugjMo% zz!$wrR`6r2l8-)#*hin_Vy{T~jI}zGDrQluCBV|=^5{Nu;D#LHjX z&k{pUZYmIq&dG)D3Q?yJ%KTA7wDLy{`OMF1!UK>NNCjrmX@L+k9fFkl10|^O0Y9j* zBI8-s(lA}80JZ4pIz$~#Wl-ot$I#S=j`2T z@AL0(U14Car!R!VIY|I2=5US%G$M=m?(=BZcc16m^@!&96HF9|fGc{U2&Tf-Q5QDw z+m9jf+mCUHR}`?PL!8!5q^{vxVykZ5ZtZ0pYkA9(XufP->MQou^*#kB0Y361yU)1i zx{aYUW%f?#kaWXHdBzjaGHSn2#7YVJ$jYn`I{mlF1vP>X*G`~{WZmgX1yUEnXM zw5RNC-wPa=II;+T?h$OpfCMEY9yazEOq;5?>g@`!Xo_kuWW zOU(C%NMFI^ZinjGWZetnw2g)rJfSi7fAUn8zz+@%vykcj(A_)e1gVT>H5N~#-*oR2 z^$OfVhx&9u-~k?GrydyrC(^IFFH9o)=8qA)Cekkg5AZ0Rtu*dTr1P4!Sw{AZyjEEW zdAZ36i8(p5bJO!v>HmOvB9A_K-MVFmmU9x|<`*ay_Q%eADy>I^jEVHKz@q_bn=zuj zL^>z%n2FMGbfA_AZ2XEh(J?**QzQQM0ZlqAww z-Pci36Gp^h_&f0fCsrtsNN04vypnb`xPS}I`rqpQCDS&-1mK8tTHrP&v?NuXG#Jn! z(ka~+`4N4io`MaY#QeWRd;`2IJjXq4+;_NMbyabuI5ydTvG=kqv!1jjSmv2uGkZG)5PJO9{0aQ%>Km!_{GQtDT zpqSQh1=GHBA4?1a&j7@t2VOAN6?Wn?=eMOag z)-SrStl-Uat zb#;#j#%|1?QjnPw>Rui3EoP=q%MI`3h#HMFPNE_9(pT+ z$k*$B(MeSA)Q7(0TH-AkUP6T|d7bVtDfCmDy{wc`614uXdIS5x;~R#g9zQ*-k% zv=NFD5cwM2^W;%&hJtHo(i&-&!Xf|p+#4fX$F!DHkmS!RND7&VBUP(@Y}7!e*uC7T|AG zMfZ{#_^RZj&CE!Ek9O|dkkx#;TTN{vvmih82@5sj)xDYUG@F2Fh)^>g-B&u1&9IRk zBD-~83PiQ1S(_5srF+E$r^RrNfyhqX=L_1dnvIklx_>OSjf8(Z9A9?bzg-c{MFr)F zY}5VQ711UWPbacf;CP4*g%jDL`|=~AcXTx1PiWSCilhx<0Gh}q-M?a*Ho{IBn!$_$ z{Ub8$OJsw<0jG_AhB`+CPF~vP*kEh?>d-O&zmNDvdN+Ii@eFf6=K9&y-?`Fp+R@H_ zhwW9^?~k`^F<&y@WLj+e&{*G)N%pBb{QqA_IKE#}UsyPfS?GkK2H+E+*wD_-KdF)% zBUfta7L)EF2ff%0@U4w$m(Ca-qu_{=q^+PO2_Ii^)kvL91aBB<-M>xx-I< z;*1F_G1O($5f+MzO{~UR5W9W4D*4!bGzWhH`-b>oYXUZi+g7o5+bdYR&fToFAthWJ zu*D=FqO8qEeUQ2hzJs~5%|yPjJKw-kgI8Z4Kd)9pM@ZZXAAZ`|ivRFanO~CvY!N7_ z1;k=r5sb345`RMAggUC^o7nj$YhrMW>*D7a;T1}Fj`pudYX5pZbq@zi4cXyqfm%#< zILgd45{9hJ@qF^m=KS-?WoeyQX0UY4_*t3_ry=!?AF7gX>Hg2N)KF}64N!|IHj1(| z6MP9S#1Xh@Z&mWa$9>C!L(M}C02fp95Ct9%>>+C7-Kyjx4}Ob9zA;cz9gv3zIq=IM z)94^lHaw$BF71j-pRlwrIbRL5!j~M{5F?T{n5;@JaoKfNmKe$suL5E*Wr>V^F;0nu z_0Fr3Pdb@R_`wBTCDr0#TV}k4hg;n#NL+UcpV+FoOd3}BRe@Mc`3PfMHDZd4H$1FL zK5N?_SU+eUD5(OhVxFsGSlO^Ea@NMj0e9BsKMq)ye3Ipb$~YhJim8lK)Q<@SUtj6!|NOxMMlQzc!kW)>ijEY zR({umVGZX051T58?`Pi$-v_<}zGr+JeXD)4Z?12;Z@h1?ue-0Mua2*Z&)_}p{o4DX z_f_vM?(+Q_oY)V{-rMKI#70{hIq(_Y?5C;9~ck&aH5#z*6Vk&TQut=dI40oNb*AozAJoY;SLGY`?~CxBYJW&UV!Hw(SMmcH6_Y5?i4y*OqJ>Y3pn2U~6KlX>(Zr zu%5MkZhgo4qIHM$5o@V6V9m3pSVvj=Svy*rTCcS_Eq_|Rw;Z#)YkA31Zh6$Q+;Xoa z-;!z>ZRv06WVz9Doy7%jApT%JZhp`FvU#U@y?KRsfw{mu)jY<0i@CG8nYotPZMtmw z(e#DsebYWug*($d$vw>7%iY>t-+h(a?7HAO1vf6f?%Lzp;(7q?Sh&lT<(ljo?&|Go z<7(i#+GTP6<~;5E)cJ;UFVtF;neH>qGEFnxZW>_fVrp)>-sCa>nsKagps}m5g|W8LYxu`-PL0)gO*T`=T`I=!Ao32Xj=P@7+o^hc7a~7N z)zJ?Vc^g$n{zc@iRK2Yak+)Fw)?P$@f~rH$5qUFJ2RA43CaMmsMdXcCy`_xEk5je3 zm&hBa+V>tJKStF)6+~W7)tg*Iew3=c(un*BReKyG^21c^ejAb3QMKy^B0ogc&Q*x~ zAXPimC-MVSZF7{!YpL408gnS| z&ZO$ecZr-q)o(mRohZ6MoKDrFLx`M4)%~{;c^Xw;eul_Xsrur#L{6pZ z^OuR7Le=NsKb1_?Jz%ROs_uH9$ca>a`Z*#`p=!l$B2T7j`JY6dMAaSO?GvfG4cvPI zRkySx@_4Fl8cXDHRNZhlk;hVXJ^b9aQ*|Bq#u%!u9Z2NSRK0&Akw;N=)m$Qvq-q)b z+_zD6MNJ})plazNBHv2Y;cg-PkU#i~m9g%OQ>bwa=?nBi%ZxHz= zs?P2}9vUE|I%XHT_;9 zcc$vJPl()!s#C2*?nu>?-bC&|)uhfuZco+84T;>2s-xf+Y)jRVgvf2EIs!&YYpM=^ zlgO>8I;7CKLH;s@6MC&()xUN^&Woyl_JTW-sQUXZB3-8HB?FQE z3ab?j+Yq^ws`a-LxrD0q;L}!2)jED6FQaPh6+~W2)ml#zc?ngogL!f>RcnHaE~07; z@VX+ZUOj-wGF7YXBC48XA6-RP}L1n{k>FmE+uk+s&-fv6jIfC zk;wN@)lxv@`BXK*N91m*8pja%E~*mvF5DSbcm881@*PyY3{E(Ys()T4@?5I^F`dYB zsCwxWBG0DkMOXyRqUr_sb{A0fm%T*J53A+Bl@RGqs{Z;4k^Z3SFP(|>J5_()L8MDm zJ!d4+MXLTd1MVN8>i1s}=>k>Hj)xmOsCwoAT&zLWZ->E67gRm<23$fx)sr3IY6z-+ zy$!Bxpz4Y0aF+sAzw8Qk98mT6Ger8Hs>hnZy#Q1_`XrIQqv{d(r)Q}8=|e>NmZ~2= z4#(1|`cXqTHcr(Kl8JPZs)vrjHAhr^zX#k%MAdhnhiikV`u1aRu@6<>{F6vuQuU2_ zMEZiNudOE1ajG746X_UL4+MzxIaT-nN~EJy-8Y;_N2vPJVj_J;)feE`|CFlF!-?}x zsJizFB7IENJ=YNFBdYG6L!=L>x(j^c1FAlqL8QY}t@w^ehp4&}O!q!jcbp>9dsN+? zN~CwGy6rfT-l6K&oZ7CJ z%}A;~{2n~)NY!;P6CR-IgV2RnsJgZSo-U;78b7=(NY&L~4dwm62Z(R5cOC5ChqyPn z{&3ymT;VwCXl9>dd(Gy7{Qr9MNpo}4Jmd35w_yZK8S(k65b~j&AdDjBd{8)#s6HhC zHLZEcx#>x%!IxVxqB89hRdS<0tIi*1A}WRL10@{+Tg)B((b$>!IsTm7>{;n44EazRyl7~s@&E;M7jpo=}=Riq&;1zTIaWrpgR?4*8 z^pt38C*d)tok{#-POE;H%32%px$S^nOg=Y?KBpirE$rBn8=`wm=G@O4d<9{#<^f7@ z?6&c9?99Arom)pa_NYZjK57x)QI2RH9E2M$+5owj)3Z^g4kr7j6=X&G$w-3mBMBe= zEzOHhkS1*n@M6-WQSeifGo!&r+=}2MZsmfnHk7aq4wW z;cxPZ+jnG%!NU{c=i!MtS$Wa69@Y`bhjrwVuli~bOAeDsOCT3BnPg-qCuXE3gvw_# z60@ciz)3bbcMnlY7KZRk7FK-!DGLnF;TPr{EO2r`Zf9Lzr{x#Fka zSz<78i@2CLIU6n*$z_2DPC}m;IEm{MD~>(E0=Es6GzZ{BAvu4IiB({KPFi*rW9VBd zko%SjKKBPrS#GG3YzEw7j^M}UPW2arr;dJaBXqyF`Ov4DvC!bpH^#@Gv*E-|7F=9S zM_}K+NZhwCpZJ8P7`17jq$v;&ii3NkFh0?z6k+?6@?pQd#G1EWpri@Fb{7eY)$>Sq zlTDR;%Fi^}bf9c3jFM*m!>-y(xp=4-|Kg!CpT?Gr10{`sQq1dgl+qu(Bq@yA1D^rh z*@OQKVA<6j*q+huYt zbJlY_>1c0%**+37>N(awtwq){IXnF%7mr=1zAjGSiTHa09YUx}PnJY=%8^5${_ibnjf$ucjGgJ#@b~n6{_h zCzG88ld^VjcNgDm{_OOO^lWXj-2@ImrMGkdcGdl|;waPRr_RaGgxfQcwcYHZ`_;iQ zTFyw#OP{6*k3fc9;GCn_H)77|r2FmhQC-c8h|NN&fbK`}V>BAv7(f|<_@6Q_Mnn_} z9t3`Vm7h`xW&?M6iZpaMnwyr%~4puR=? zuNfJ0gDM)`-IWb7u;DT&(b3(SY+IU07Zd;q?HC)Rg6g91dOtNcFF}v@Av7I}jxRw4 zlkV%C*iB++2uh^H{&s9s2MVyJSs*YI+&_u2CkAAovg^OQr7gxyL5dMEmIAe6x;H?V z+@a50<5UYoGW4_*Z9t7+KvA2>88=Y4Qn;aWb-D|FQ(4Mdku#S*OM9Q9{=Bzg%Cg=3gHnkISTqI z3#BPSi)k7mUGf0NMwUFljg73XsyXKef#@LsEG7^g3m76g(Bxi4 zg8^D})(x$kmwY{w^mL6dreFy#Os7Zaw8u(ujApw?cXFfZUUuWqEt z%t9{f7GM^W%c_J~YwLiL<_z%DoU7|x#e`Q2;ixd2VG(pxID#8hCe>2tME59ka@}L~ z^-Eb~D7)$h$fC=xLXNEc zD!I6;uNlGO!XUgEa77QoATFIfV8w*2cYLQxKJ#@>mKk!KeSlf?rzOa&&KqIkc@vO$ z-UL2z%N&*%mK-+$vFIg7kXUi$Fz}o=5O~fTT;Np~N?Bky=Gq&8#hi7fUK~y>Ami)~ zs^qe+zWN}`3hvM=4((Cy6EqWcQU`GwT+?fcSJChIn-T)T5W1yrvK&K1I*i%ogG*y7iIrCJ>XFsQz z=zzUj{Me)O4al5zM3r3j)ecRqBaF(fz%F`{j!0S{X=Za(@`+n-WId%zpri{BXUE4= zVrD)Ndq%D*x%jINq_Ox=h1?nN<5Y#5pBkM$LF)8-RmrFSb0tIXbZjAY4C_pA|G(e+ zviDZcJdfSI*3r@ay8SlW30r~9VqIfxXxVM)V}8p#+Vq`irpan7HP$q&bNgMpTs@s1 zIMW@MJ>MAGlUK=TG6rJ;x(6|o$VKS-{;6;+G^`I&XQijk4uyb{b&mu_HJ6e-J1ZkQ zF(uSqlJ3DEw!Nf+j&@`?IxR2-pfntvl^Y{4 zD;I7wxC4g6-{K7$J1aLz_iOW0$|)U;nUxzMFe|6D8K>{n$cOgVFKM%8z6>@5p@54P;1h*)EEccyddz`!}h{qS-96h_xr6Q zI!AXoIKvGR=q{n&(FUnW2kO4!i0GxdDZ)Mu&^_H*NprM^w|KrGx9OVa%1_mOjH&Aw zWhcojWhSRvAT+0Enoey?*@y&Jg`qF(Bw@W$T4H)NQD8BeGWXAlQ3E$Ye6!JeQn&+0 z;Jl^uR*kH}4LiEuDjzY#Pz^=P;mR6;MB_<(U7UKz#kYWuBv+8{8?br<@m@eI1MK@7TSz z3D!p}-&oq37nnXUH8jpL>@#@Cgnu>fA58eCKx9Nr^j)3*gFjO!B%s6tFbMMeWmR&6 zA!YZEVuB%skd#RVU@=LVC}0}HK-TAmsFKfIp~)CPa5xE=#RP|=n3+Hb!tPn1N&)vgl}xBO34@^Q;FPeg-#CknT3BW=iC8-$>87!&)F`+plezj^w)SGm4+ zb#=;)FCDGy_u0O*wY17``+Y5Qmg!}$bFl;5#09VXbLQN1UxDgqxqsr3eD1T{Fwp4QkAgmgv z0kD{@gbExgdXais#Um_uADubTG`kF*!RMb;O;<+DC_k#Sw8cQC1E*h`!)Ux}}t_ZiPgH~~=A z{kY>%M_c>*_9WXswlatTylYLg63b#sZSync!KUM;Y&Zq5*4WV9&UMf=)cJ)o->}y^ z*f55iC9~AfKu}gz45E99AnvWy2_7N^i3Ry-a7Su-aw6R92quEpR&=im(=-a#??ZF> zb3<({NV32eSI=rUcJml&;$GeBhu9|k`JochP)mgc7KrbN>Wn{TTnC<^5%hDZUn&}s zfj4e+KhUAEr5a6v*K;Zx5Q#ZCvvbq)Qxn4fBPBaIFCleKVrCA^p9!s7c4#>#A;xtp znufH25O|$O_Zm7)bD9_iJpQA*6>-_7eD~Dw13W9F`{g*AhLp$wyjP^V`84fl)}inm zlJ1jYC9To@Iy@h#`}I87sIt|D2Pt(g(4!4R?2_TR%gGkl=;}FBVPm+#h4(XcziTM` z-w*Fi;aN`IPb1M*B781O_wN)o72XlTGope9k@~G?cO39ash|#p_hInzsh|$2A0};w zrtAKhSJ#i)-4DFks{8b_$F87H2-oh2eOyU8a z-P8RDnzm=yTxNDk`qcE)6gA-i@B8WQlG=9tY5qjo+FiPzDAKf+1FhvG=H<}_@6>%M zsCs7PmKvTa7B&hryJ2_)S@%((b}G~m-N?cN%evpLtv1E%LE+(M*zl$6`t{ZLMSk{- zR2|s~}fB652zY6_<(y9=J5tFMy*9;A{;0AVTVlu=T!f_*b zk~S2J0m+TUtQeLyTGal_b{y%({f z9wtISa#2@ima(WU0;OI+6%(UnP?bOs^L$f99Y5N(j-L-)o3Oxj1En4S7L&O{VBFXs zT_c-diGHjftw{ za}Il*A6=AK-{YbaB<6i+r;9+++_n?k#m=_pH_BH^t(`P7Xnw? z#RvZ7Ll(GspwtS$Vlp-w`_k?KuRF!<%YoB6iVL~$it;h*YrByRSh-v>rm3-X%&skiU z9|+)zoF5e2$oau~5qYf_`Mhb@vAj^sIv;rBP|T{0DIu$+K$U#vaYI>VIJ1QDOR#58wNJ79Prh?gDr*BYU zUf)x`ZNA5S>wK%BHlWBC@ZI6d_htH~`X>8s_uc9n=1*Pv>$}!h&FAu& zy_dbed4KYL>;1}m#QTBwZSSkz7rnc^<=!W}>%9+n%e+gy3%&EbbG*~N$=(UxQQo26 z{@z~R&fYfO=H7eJG;`tt`5srI4@x1SO!?WM>oabrJlb(&9hv99) zQqLmKy`DQg1)eO=G|v>zSkDO0AkWR7?w$^w1W!{>JU26yj=vli96vfv!?}si z9ETlmISx2paO`sIaBPN3inWdvjwO!!9CtfrJ8~T9jwHu;$4JKzM?XhTM<+*XM>9tQ z$Muft4zI)JAokzw=j~_h-`J1YKeoRI_b~3W@3lW=-)4W@zRtedUScn@2kdv)^X-}T zsrJeC+wHg72ip7CyV={@TiTo0>)NliSF^k9X4_@kZ?>Oo-`c*i9kG32d)xM^?M2&e zTet*X~Yh!C}YiO%&t6}rm>^6h- z59=@1@2w}T$E}}O--j0=_FJE`K5c!{y3zWu^?qxqb&>U6>z&pDYnFAIb&7SYb%b@0 z^=4~#YX@tBwW+n9^*ZZSR=3q+`P*{Qa?Wzba>8=d@}cD&%R$RamS-(HEn6&)Sst{k zv@EkomU}F7ExDE%mK4iG%V^6m%Pp4PmM)gImKK&qmK)qB+(+FXy5Dghbid?&*1glc z#r>H3LHA1cGPmTu$354b>z?6GaZhxQb`Nvk;_mJ4;%@71;cn!iWTT%JqfoQ`aHao32+}&%2&+ZFg;QJ>pv9TJBoxTHw0NH49$7Omii=#<_0u&a_-( zsbXYNC>}$x9>t?59zpRiighR+Lh&Gq2T-gU&G88LNEJsm_q69@Tie)I4qF91rF^WYficrWXBoqr#+=pTTihEH6P!yuL2gQ68 zccZuq#hobbKrs)+ToiLq%tkQ_MFEO@6nQ9eQOrbY=EMq7I51P}D|oJ&IZ=u0wGxikc{{K~V!m zbre^lxC%uz6jf1FLE%H;Md3l=M&Ux?MBzYTM`1%@MPWe!BOvJBCKN^#1{CP}@;@O> z{u{+*6n~-k6U84Wen)W$#YGgqp}2tJR}{aXIFI6I6z5R0Ti#G*pFf#ikDHmgyKaMFQ9lH z#d9e3qS%AtSrofb>_YJjile~M9!2p8iic6GL-7!b2T?qLVl9d_DDFqG8pSFUD^Zl8Sb<_Wic%CMD2h=m zL$MUa5)_M3EJ9I)LPjB>Scu|26bn$?iz0xc5XC(x=A*b9#a$@wL~#d-c_`+hn1f`D=Kr3kxHgk34Zt`uQcim)q1*p(veN)dLY2)j~*T`9t@6k%72uq#E_l_Km)5q6~r zyHbQ*DZ;K4DP6f0do&!yFcd>k3_&p%#UK;|Q4BzF3yS_I`l0BH;${?mP~3!~H;P^; zdZOroqC1LiD7vEPf}%5uPAEE}=zyYqNXXa~8M`85S7hvpj9rnjD>8OP#;(ZN6&brC zV^?JCii};6u`4omMaHhk*cBPOB4bx%?23$Ck+CZ>c16an$k-JbyCP#(WbBHpbfq2k zs4a>%C|aXvg(3k(OB8+-El@N^(G10nD4L>Zf}$~sMkpGhXn>+Vih3yOqNs!71{AeX zT#up_it9q6NEz?f;@_-^;u;h+P*g{8HHxcHR6|h}MHLi26kZe_6mAqQ6iyTl6m}Fg z6jl@#6lN4A6h;&V6eJ|1e^C65;xdZAQ2dGF4-~(nxP;;&ir-LNK=CVzUr?M!@iU5Z zD1JimBZ?nTe2?NRitkXILGdk$(kReDM)=QFUa@wkrLf>XDiFEDQkeH2{fnBi>D(7AKrPM-~$Mw0G`U?G~<>?#rsr0`>d!hR_m|i}ndnFVG%d{D-P(9#6 z-D|8hO~v-0|7!R%m+^Y{(B6 z(Lfz8957R>jUUv#E>YX6G8RHJ*#o+tfzh-TJ_EB>_u5fSJ1}F0y0b>?4;Gx5b0hB# zBJ%xWhge2pQffx9l7h&q#d^Mag%y!ki8Un7%2A%bQukv-=q2G}L}h~P7b@VyNf&>p z6@pwM)DTl#L*(VUpNyh53mvMYHK{}{7224loRr8Vx*wBbdZtu@61iB=Y#aKeG)0_5 zUZ(rOGVBr7UlMt#pjkFpj>s%2mI(S`*s4b&FV_8Wl(4ZXJ1o3N_hVn!WVqIl$VGxC z24$DR{7SMQ$JXwLaJrMQ{=b0uZuLIqx$L>gUFJIJYUaEf_WE`0sgN&rSjSnmn!htQ zG^HD#HvD2}Lkj-u^8dn4fzl@WmZn@`&ly|*B&Q{2WTa+I3oa3{Vq!2pS6MN*Ij=Nj z@WrP!?>%-4lr{$VJpFFe`4`}0mkbW9g&i4Ki{F9g15C+BA#|Wod^->$x`E)gl&O;6 zfw_Cw4zvoCHiQo7_~gMAegQQ^g0TI)s^mkj>CQrT2$VJeXdQ3LyaKc~&VtB&?@=Wm zecH<`dhbAKeL%k}ZXRFh<{#<%RH%~Qi_+n2FTm~V#ntU&MGz4DCYLJt9hmhN+X1NY ztP33wS>qWQhCs|-X{zMm_E}l4JOZ~)d~n0D48-hlOqG1xiBnlzsQ0}Aa7EVpMg&BV zviohS;|Rr1k)+Rmaw zeSIxJ7kTtTbqgBbLC_BMRmlZjIixcS+%!;n9RQ2DVilLg3NU-cYDJr)2;1f;A9l>+ zEG!%!yB1(Y9v@R+G17#Lt?`kAiq_rutT$_xP2j{eyt%xGnJ^jEa^G__&u_u(&W4*8to&OvP&83~5_Ds!A^H%I1w&TJVeN z@$rk8(KkeHUQLyJ^s63Z(dz|DuLg86m+sa%6ZzE;K;J?hP(fIS(jOkSX!EAnGTp-#!-ex;E(>l`d1-r8@s_T6Nhc1`pxlA z^#}7C`1=&Rqsq$NDfo8EszTQJ0lI5kp|w+DzH-(+pL5ne2wnCf3*9JPK3U zUN`no$i-(zDsmT9Zt7EW24C#go~3RVDD4c?I=+{}r4D}OX^b9yBL^RbsL0_y3^DlP zGR+0QaBoB>0N3%R3of|kGKT5+4nW29UVKw;*Q~1He0xVA*71Bhmsk_dM@y$E-}okihD`yQ3!sU4^YeJy3J+SI{W|70n6iFa!YL+T1 zXATa*{AMgOcyhb=cru%_K+@!IRLLhUOk|0>1WMZiaklu_Sdf^rGe{bT_(|jV_z(J6 zd>Dvr06z``F*^N#yi?v*C7*l9NtU}!ptLn`PZn=>EqC~9KDh^CPwv6T-l)0P9Ac2I z06Px30|h(iFtKw76L(+-Chp*OV8KAv?%*#8arKv|TL;D~+~cpny^THQS_rH1mcXs! zs=Ttv5UWYUelqTQH1oLYD>rj+?k?%Xnz>`3)DO7n;@w**evK&UK<3-KsIqeQ;2bWo zFNzhy&};$haTuBkJFN{w+|duKl8^mFK5KID?B?{jP;P`C=olU5k4-=JK&`Vz?5$T= z$4<~hs=)Y7<7#})0$}Jl?8(q`eB);&GsX|r|JN}bC8oWm9>#;ddwm{niMO_AtEZj& zP4^hrQCGV2H|L#BpW_inXZu0>SldZkzRhecv(~VzwbVC1Zth^b&2ZE(iTp_J{xfFdaMZLmL9Iip$7nflab7m#-%VK>? zjTA=t)=Of2i)lAFDdM&zgGS|DsD%q=Soml63XvHqfs7-6Ap#Y_wAh=p}l z+a&BLiM&(n2ZR$}B64|L49tXvh`d9e`s~UEB(4ENhTT5P0)ZJ}Kc%wTj0ngO`AM-J zq%_OU2HV8`ib{)27=*}M#V+-fCSyi0h`dFgvr~K*iU>Xs`H8r6xsuiGX3YP8L44i4 zcY0oOUv>|0l{!CkR&z|WZ?>JYb++DXdChW_dAwIrso(-z4~n0ylXA0X z!^4hY=4DFN@3Q)Q=C@9>wuXe!KwyqT!bsV@N32iK&P$XxB$lk;v+vAh*`Zo!0Iya)Ym=2S3)Tmx_3h8Lggm^!liup$(mzRFhFkt`1lP_^^TqJ7ihjx_dK6d z_Z;-~m%n0-4qwgQz%6oxqBXka_{rU!(dKt|uH4o^=9g|}nZeb2#nshgZo`oL&SX_q z-h-g4_nyJ_09?IiTwOib12zkW(DRfcu6b`)4uAPXr|w^}Z_fu0BKH9JI8;L^Gffaa zGTnh4n0uotEAK$if1Vq`TE9o2v^#WQw)ol$wF5D8CWt;;*?7)Qsk{q82b$TI=>q2e z-zBE|O-+r@_?G!Y*JS5ckR=QfAP4-jn<1F9Kh)?6F~6dE9c1*nmB_EfB}b?(IsXThDq>>VQJxbq9>3yD53_UA^HUQNbChfK zzytE=b!@G<1u{|1YKP>PqK71gnM1z%g_tB4?V%FVF38RBYkPTIOk6ptzho0<{2fG;mCJtu3#W>5k|p4O0^NbkPA#GN0G-EmD~3r`}Tc& z_TF}u9S)RD0d|20%A(k#2j-JX&BT)v_~>1}WYJ+@P6qV23`|__LYM+=y!97V@`10> zoM?vg?~?#n;Q4oIYh{5R8S6moEyb#=96vaL|FD9!H)Mb&0=~dxXB2*nfC-X6(O8xI z9-RG&?LnVF=>#u_32WH06@uQ+y$o+_NANC`h`>=yk=poH*%Wud89KgL3Htx~PMmQ$@AWPkHA%MP>t2w;!rtRE{( zh-SZEG5`Hv@y-7_TUd#1ozxuBi!bT2Kf?~R0!hnjRqDaOBlH@9WYo^Yb?lUvn-1pw} zyx;HnPu&u({pp(SKHXK-)idFjh|5k`=||L^@F$-j{U@LB>B+AwJ*4bA^eXceZe08xSV|(0KIskA1wh;bC& z?7%>|yot3k#LO}PJ1#M^Ahx=|Q1CYvA^01M$_58}Uw(QW3l84-`vE*I-uWOnotqSW z-$_K@cd~5sfX)AKvgoj^PXqM0EbBq^P*{PIzdjeqU!PkxdBEuJYXVVFLq8qJWB8;( z*?}mCu!hF=Ysy<$uetcNXL_-AhPxzFfmYyM61su};=x)!U)G7?}`r(?*}dz4e_o?Dz+En67uK>q({`W?i5(S5@Gx%(aWF88zU6>h(KwtJd; zynB$lySt^kj=P*Y!F9>?lk14&$RYbl&6a>1^e!=PVD|1(zMC9A7&A<#@&MykoUvsbijPi|t9< zBewarY};hpFk2s6TU!HLC7a25&3e}Qwe@}LYt|R7Ypsu37g%$wN!H=kJFM-j4Xu@} zX3KTUImVy{sbaC1|1_UBA2WYw-e=xwUT1#H zTxiZUr3`u2);Bh+6!V>@a)WP4Trw7x|DpnirvO+QB8U*ARF zTwhb~)ZNtmru#wnsqQV^PTeNma@|9^nYyXEvAO}euDTYwS~^$4KMB99ZWou{tPidq zJKvj4Bp+4Z$s$rARSzT)X(3hL*iWPdRNdd4Nb{-s`eQ_TfU2*)O{95L-P?{xbE&## zE0N|e!U6DgCb8=!+3R9&}#NcU59?M)(0qw15h zh?Gv%)u)Iwm8z@28fjErkxHZ~R9#*~BrjD{%MLmEN@1W|$ z?}*fgsuRW#sW(-}fpL0Kb*zO*J*hf6lSn^{Lv-Mx@)R+GISD>QS}PHX_xf zY6IwC9jex^N2J1*%%13*|%Vj_Y3$={Blfn@FT`RK0SMNN%cL zhOyzI>ZPZMienW|@C(wV4w z>Kh^%sd{n(kqlHl0kcd`)gR$cbyPhL{Y{|i_oIkJsQT@C;{S)L$665oO{#vqpZNc# z>e0%?{})xi+(`WYrs@~1i2nvvKYxSx|D@_?cM<<}s($hb@n56rVffRlRQ>2v;=e-G z4<`}-Wvae^f%yNR>Y>@he~GFG9mIc;s_(5K{@rEidf*x2|Ane= zEF%7&sk-kZ@n4|o>vM_!JXK$F5&t==?(IzcXQ{deY;}gJySo$rX{weUA^uZT-I)d# z_Ne;uKg9nNRkx2J{u5N)dVu(Ur0Po(i2nzwZux`wk5l!9WyJqIRiAG}{NGV^^LFC@ zma5P8BmQGl-E^GzzoF{WdBp!URX1EA{-ab~-<z9iCQsy;(e zQZ=t3k%mxpx`jyhP&Ioxkp@#W^BE!yqH0EMA`PVKH29Pcpemd;rT$b+>r145RQ19p z@a~Yhqv%V>ny2dHFuXsa>arIh$Bs^<8h*eX@0^&hRg=d-rA(?$hA!-&>ZBe}Vv?#8w?WlMs*VSB8&${EB>t^b9n%HM z8B+D$b;SQ7RY(2>bpWY4;tr_HN7Z4_!RM)Z&+o+l990LwinN)k18P8_Y^wGvA^vBm z3UzS&o2c4%A@M&=)jM_&|3<3zfhA}IReMb({`FMt@g4E6qiXjN#QzjkyKW->wN&j~ zj`*LXY6lq4YpB`=hUjXlw(ds!tEid?R4b|4vOe*zplS>Fxu2kF^YX;MoT^P16MqR+ z8^ZuD#{2)T5WS?Yqnd3kaM)-7e}`Jx_!3YVDsCY*2k?CEUPV*&8y6H zOgl}zjqe*r8jc(C^nd9*39lp!B8SO%JYxoKqXh3Uh`HZCr64PKpC9k{r+RZTvS+I| z!zGiLJFjK62|k#aS#T*aP;dYkNx;I=xL%Pl(Eyq|BvWtqBN?RCjOhEe@&%T?XT(oTg>dFgGgyMxgb3wxXk+h5;K12 z?8Jy}a8~|XboB-$dK{j|1!rtAU$XFCdZJuLfD^s&>J3W2%S@jFH-hNu4GKb7<`Xz9 zMBn#T8;+8+1pX1xMFo`BBlC^G86&!ug3@+Gst`DS;?(WPEFbVPiTOxGOf}6ORZ~;#>LheM&-+Z85#heLnE{mzGplK+S z?f}kf%>O?c$p3%D`I)n-Bh9|W_Pecv^+C(q7MppvX^rt0V;jRP{hNB7u7AR6a#W2Z z|9@K+cJ~#PgLDjm>Fjims;;#mXM{)Hu41arwTY_aCc#`Q_Y{+v0Z-NzxuFLF)97dq zl$8rHuUu3m7x(I4npZsA`HEbCD=;5TiyQJy(A22Q3laSCLO%GB`mCKh`-+?ZE->9b z3_LH#o02{yJtZmNq)iZJ@zf~-JsCdz%W3UXhp z!sWht@m`j@y|2g)+yYbS!ni}nWlH{A29p1l!6!d_m?iJvE3yH(!2HE9a(d*Z=)e4e z=)e5JM?blWMQ`dWvI4rmEI^9RW&!>@0%?C9!KeK(kELznE3yEsz>GQ#ZD>J(Z3g0= zS1w2Izsn zyN-0EhoT4wdQvGx*?Hn8?7@kj_@@3xQ%DF_Zyk`w zW%X9bBPZyOiqU_(h0#5lQPR;@lmO@gueF4a5)b|Kgy!h+uh8trzv7$y+MuuzPU1Df z(PbP0{(ck!e?N)~e9d%;1%_1r1@Ri;ijSL#A|Ua%>s84o*B7$naKB=HyhgY}9y!8~ zwLtV^Ex71czqhjJaB=H_c#UucJ<16GT6s3*YtFMNfzSS-jVwFl|IY*Vxa?LGcI_$i zXk|3{(aL<2Ul_(<+nleFItd#R+>6|9*OSivjvpM;tX(YsvfN|-#++mN!!*xiHm)%? zH@smOtp7$!G6`g(C)UawKcYGb2UszB(IWtNV1sF%v5huM*dWMV6VVi zfWhcSV%$LCZFy#Tlc#1wB_&u+ApKU1UoWE3f;@cU4l;bj_}C&^3^|B`{j4b__!7}- ziZ?eOPr~TNlxm2nWg5|NaOU7|T0PTPI6C&OJ*LT=f@Du#L2}Tt)r60rDM{%W-c--D z>}2d;RWV*~rhlm(>{}J#ePhN;(3+KnFE}YlDN}L5sU)U6GGoUiaIDNo&n>{;t)iH| z(JdZ&ErWKfAZ9TQZ;Rc-L%P107*s@~nlC(D3lI}o=QJDg2E!!;F_V!tu7;o_x0ryC zwx!SyibK{V=CcvjW`z3`u4{<-Y=kw;cs}7ui0CO33`2!B)@We6m?^`oLDK^pEKg>7 zT5iZY4Ht>>;!#;T^F&}tj}5iJmaod)|> z;lE{Gew|lM-i+Z^894_aHF{bucq+>ML&Hvq;^+5c;GU-O#ce-Tf z*UkoxJp1c*r|n+r)0PVsk2%-0*Lc&|&+xeZOMP|SeF>Y%FYuR@f1pHPQ6q492y|PA zFDYQLpp#=~D}4MIB-hz-<$+y{v!f8))(rtzpxZhenDrkZdCSjL$tU0V6-y4Wum)ni zOA+L%69REPy;aG_{zPMNa9P&}Y=JK8=-BEig3Qe~sFKgVyAo@1V81=i?3#TSGB>lS zlF$B>fn|p%M?GK{80CntJG*y7Ij3={VW34%Ty&F{3Fd$4mPhDXPdL$T|}<)v?}@Ndo}g1AXTacpbJcuim*B3 z@(XO~k-FAqRr2ZI`HP*RkeE>&=mjQbM9_!)%*b0~kSh7yul>$)xAYZN1Mbn{s(drt z)LD(FRd=b9k34Gyiwui+RX`RP3}cYB9&g00QeBmN>{TaNY)HAR0@wmmE*WfentfsdfK{h&%d@RnCt z;8wn(iU2%5E)$TA0w8QTlPdYp?;mHO!O9iHS~>J3PYi_;5Y#zKm0aL!wKPSG;c!+S zfCV1T!hu+VPdO3f8Ye=K9cmt_lF#1u6vK}B|L2JN zZdVCZ@9XS%)c&o#q3wR_R;aJn+q~5Dp{bH_v|%}%|Lf`|COk*Zsi*({pUJ{5zM`)1 zBMB_eA36agD)||CnfW=MoZRdg>8ak_(4sjUvwC(8U(fxWu6MbE`JD=34eA2;0@t7@ z_;klLO!=M;tImhEf5Sre@D+6iXo1CyBcZ)nscE_CsgZUcg4Ka{4&he^zFt}LKp33s zIzbl%p6epIkW-L1H8fi8DUU1DJ>|0nsjery!{S3mZwJ5^n9&c8ry7TTMeC$b&v)C}| z+s1j+C*@@2MOyu?1~_K!YQV?0EM)Ovsc8fF0+*VM?3APoFNVr8lCshYAkB=f@pt0& zshxK&zfq%BQ~fMV7jguP70y?-zFx(HL8$_T)^>&SFg76EDW>?8(0vbLAew!ovo? zCBO^Z;75n|dI~}dOLt|1-<`j~zcT4gmK?^oCyrx08xp~?yjl5lYIf^^W4v1r{%9G$ zh{g8!idq2nsCbQ*RAz{D@gi{-FQ0g-nP@9QG zrM{xj@a@ws&#^H=9Qr`fU0QQQ8ay{qkjZHVsZTiOP2X}^Fp)9w9IrH z)WWZ8*kot|SpjDf3KFbjCC4KW%Bu+dk6XM@EG7|)?m7dxAE;q=?_FZDZE1rTJAxkz zinNQ#6$)?5lb@ZFo)T>FPB9rg5iLTNdtORzdUDX)0rlp^Yr+NNkb+(S%-rYOzBluJ+3_*>u^3DN76>X_B8Q{BXr`HSduxIY+P#t?I_x#YmqPJoY1IqZ++kbVtFHLUH&#Sx*wYT9jb~XOLj?q7w+-MDiNJk0Yuv z_1;BuF|E*@ckr{>Y?=|gCo%5}ZAJB(!0S-LuOm~32RuH7@&A_t`TvE^eNL03uYIxY zeVfZV+VU)%^*fsu8b36aGmO!%(VfuMPnb$x=A825@kj7nYtc~fw8SMg6}(fFpOg!u zjrwBqx1*mWe|y<}mOw<-Ig|0T1Tt-h0Jgx4Z2EZ)V$-uYMbB%9=y?tK=yr|!5W;Hr z0D4?9C&JLd#TC3MhuG6Csw^8Hg2~s;YwG)fYi_Vu*Ibz8Rd)ond-ik$&z{Z&zdpPh zJ7gf(GYG&127Af?*IGRjpC{g#`3xU^KtC29l5Gb9yuf7JFnCm%2t-D0Gmf>#NGL2TEW;xAkGc;X4Em2*u|+6fm~Bs)Vq; zTM^s4wQTG_YR$OWEH=cw?*eRrNd{Vbqede_sY*UmDkq;QKwa-SmKu^-`vSGVlwnF8 z^3REa}>X(==H{a_Gf@qvm10FE~{p=2nMo`Y^KVx%^%ptSl(yY1M&abx^~1};;!#{ z8D9ST7+(H6>BxYW|K{5*wkK@$tlO;}Ebmwbnm;y=H2q}q8m}1V8vZuShj;BC(^u3z zt!tO?cEU(9+a~GLe9+G^n7n(QjYRJ{wvX0#itRh5jX|vpRt8` z;R$syJ{7jnqI#P&}a;GzB{i|wD% z9Miuf(eY;Gxrk`7?#Xd#JM!xZ?;eZsN7Jo`(r@+D2u~}Ej&-XoMvrw*6deo=H6Qu8 zftRC2N3N9CBZJQ4MF*WjEo0DmT%7D2J?K1E%=!^AtV2QPF>(4~BZJPPMF*XgA2w>x z`CidMXQlCop!29Wty?tcJTgwdaAeSVgy_MH5syIPAkN+4V)kov_Rt1Z4=B7>FZvh7 zMniEOA`KN&oi41K)YXB;9U^)hl@U!L(mi65B*Xfvx-7A`gT(~*%V?91ra@xr$c43w zYB2mjq=BOI*n&T-(j@Ka05Lmr+Edo)Po(~$2T`CoI%k5XoqnR1hA>w13yRTG>9IR!237Kz zf7G}=!O}_bv2?hH18J8{RVAPL=Vh#=!O=e%sN)i;Q1<(gZW084F5u9;=AD1FHA^gDU1z{I=QY9Dq+D%QR0T?!8<2-DldBPCg zw^5bcE?loLkX>}(V>Jf4AaGki&lrl`HAQd=@rl`;g`6j51EDQ-&(*7vi+w$DDm!do)Q^bss1Ns3BKGV; zRdVsKeXIG%!csFF@Z+-7P~Rh6<7eJL>X|pV)YrRd3Wq}O(J-KnOYRY+Ry{vRJfn{) z`Q&bPLmW8&S0)bz&i{`%zj8KmOtJyi@2%-J|4x?&0TuUfuZ+iwrekW&^UonlKvVtR$uy$nFMc z6@K&Xe z)K-2WsjC})W(^Dlgz|t?U;&{JY1kt7;$F1ui+lN&eZD%&3+KdK;1zgIq`Y)Igp9nU z5khZi#D`v^se07JS2P`<2Z|mJ=q(PxKCdLqKEH+!`|1_e!mudk0Ia|-Hd%*qA2|(&A@f~g8lT~; z0()kpduN6gyw#_Wdi5zT^_5ea>ql@IFb${$UIq*|b6~rn0biw@QC9KKC|7PIvF3*J z{}cchc>a$7PtBg0m64s48Z!9`<+QRQm2dLjN*HpRbtkEtke}dw9PWIDU4_ zv-Y(dv3Sjw%(A(PX`891@rW@Sa{gBsYUy9lch?=(O-MNFaM{<|Z@0Z@>uh~JA>Vl@ z!AMs8PaOkujD^#KWfsIF>}#9=`Puh-v%q*ndPq##jJCC4vRSaX2gRh#Xqtm6e6w@% zJ&KEiNQ>goW^!1Y^Tgy`Y5J-0I$?-3M@%^tO>2t(gh;c+SX0xO zW&=p1Sz^)?%V?5%Er>KzOjQ?bS#dZJX@;0wGTKU*uYgDesYW>N$GnaVwur}kBIS!I zRugI@bV4Umo|u~iw5hNWnVV*W^RXcNh0eu9nl5s(MLW_GDMw`2LZ?w8WsB@uw1Xs( zvc!B})g6)c3`nF*F$tSt&4rF{M9L8J)lnPNoVX7=UV<{sc23!y==T>>~2`1|6Jclm!7aU z!9wo)&rkUf;wlcjj3_X~g(DRAzUXrL-l)p5{UCu*{_QU@evrZzzT$E~D$v6hBK2TJ zL0Bjd^jpP``Yp$g8UU_)fCX;uD|Q30z?d8bR?oc1drT?ebc|oZ>FS`0EN>@Yu?u(w zR;PDS z;TIM*d^CTdBv5_9PoTP5_XU=@wXfI?%mTwN8fN8FM#BO}7Nez)EaqFf)-Nn|D_^k< zs0GF{qEUwyj?c~^^k?Vz&giiVh z`EgZMmJJ*DwA7lz!nX7kn*df|R1rsr;x14<@re52I#rg999W>cH)4@t%`*bB@HJ0G zR^9o?`awlimdzY6bB!-pW>`H8z$|?AP?+iV9bpd@tFmn9fT0(kWue>oiuC|3Fhr*r z8`?ky0v}W^P93aPHh93=)ioEVy8DWC04^|{J{owq=LCE3-fUI!dr@ zfjKwY9sj=!zM=(yK3!Z+ zmIj@(Z+&Aw^1rdaZ2rJ(ZL7J%0BHd8fnWHxN?BqusW%B}_ba>Y{msj!4ouYw-?3JQ ztd<9WI$qx&)g^_gwD?KT>yEH{ZR?UCH%~tDW;*=S0UT#~g_9KX313`^Yxldd@n>>aaX(X>Q(UzQ^=A z)CIUDg!o$jeQk)e--bGKrkFld`h2 zW@ly>T`heN0xjh*v8$Gf!P7jtv?dOdL%oqoq}6e-D}I6_ zCdVo<=|DJqLg_#&MVd1h#HTL_5ov|Uu@Y>J@o^IA2{E}&)P$bEoS2f70uDYLoy*0y zsJV$nq!KZSPfQ<`*NBKzEONOH{(6evF+M~@q@xA7^$z_t4cm~>-j9T$5&h%s0G$H!SA?2t*LKvWgHS;8OJA1e4izT%(GfR zEIji}A%>kt$i#n)Mc_Zi@_{{?1QHn7HRCw216!qt-8FJwY@y1s`2%Z7MNQ@$EZH@H zKVF}ikjDmDe^o9Z|H`?59GHyFPqBjpmh9@l9Iqu?b^9Rl1*IzQ1x{7o0CLlRSY#L` z)#5lzqWX@I|J*;SEPI#)_?y&X`5XC)s{+5k0ywymC=Mt@Jo}(3`KXOrv8XUQs>EY- zgn6+L^^B5^apo537!9Vg$S?^j1G4Z*814!~=2J>V?^8u(n>ny>RMA|jZ{sVj1k3{K z4ABu0=1)WHlS*NkleZ`=lX@F#YQU}-KWvRt4zW+{QzhTpx0PqHA;GxmHw>O1_nQxfv_t`QJy}LtQ1#qt3dJ z|No-xD%|OR2r2;7GUu7zG#QM;4eRu$^qq84!ij`L;-iQBSp2U-NR13U02#Z~$Y>|l zh#$GM)t^Cgf#jKM!1DH<|!0i)F8M@)~OkGVp#D{JN}?gE%YL}NzyS(+b3+~!C5xLe*~tqP;Iv+z;N z`mqtRSshjKVc*mwZMOFncLLbhl_x1<2t@aUBXJWf?N{1_TiS2H`E$crGsArA2;^et zo7M*$x)e~_@M}bG_%+|yzQrsuoIpDOa_ml^(TuG{Ru6Qg4eBCsgSvd;D@#~n@ENuT zVzE9$g*cky8=33j+u5b{xNm0(o*u-`xKm%p$|3xVC^C zyGwD=1_)+kh6YB>wn$pDEuZwm87wL69NPeC>^8h*lZL0nAa3=Zs^nuI)a=t?2DS!l zu`@7wR()w@te6LqPkgDWILah2yLSv)SG&FLhX?$dP6^jh_`4Ry+cK7)> zV<_M5Jz{YMFABeNZ^RhHVh z*D42GxUE?jd(*hFC#9vQcnUnZo{UiLH?mu>gkh0ruE=EjZ&v zb8(^6ti)W+w}`o(x{KkpxmrX0Kgr;Bx}LOccE0Mo!|{nN(Ynt%2+sdg%zv7fm~S_g znz|c5F(w;+F+6Cfq2H??sQXEm??|=(X@AsS$t~#;5+qmagc{^I+fG7al2;nm>1oE8 zl$#0ruVxoy<%de^2fr|E3jV>EqyzGrqyaA?{VOIpN}SfBE{sHaSF~Zn*EAx%6O(kM zXk86Dc>)cxd5HUCl7&@fbD@;LeZs~|q{EL$uO}J7qw_zlgchw==*c0{Yw1RC#t3SG zal#PkRbjsn>pvmV-k6k+DZ^&bT^~exMcA;=x&Scgc8`eFH@Hq}TZ7FBk#-Baq{Q(R z5NVfai!#T2B9+D@@iy9^37yc1v@<5T(q%Uiez+#m4q*c&;#^FmmxcXekw;o0Z5Q?_ zRa%RB8YR-Um?Upm?VpHOsnpsiS!(i-kW8F zH|s=v`P38~=FGuvIo}f2O|@aq6c65#Iv~0!HG_mmZ^qab9qCbv$4{V7J-^S=U<5TiTclOz)a1!O4HS{vUlm-KvDs2_4DOSVaA! z{5J|4`-%fESN0bZ0iKZrcUbZg14n`>8A)j&_nKF63wrr(!3#AHGH#PXh*k%lsT35g zW?7SFq^AUnZlYHz1=9yhQ#k2^a4XQp;G*rIx@YqIK#WJyexk6QBQtO=2qq-T`srWv_;mj@pO3qxSK6AH0XPFGR%p z1FzWFscPS{W2Ykt!jB|;_}MpDc!-Gg19-6!F%3LDBO&i_%ycXrK7-HwSok;aZs3l~ zJXA0Bg?1T3e@677Kl71~?PN_2-@v;7S|e&*g&r`9Ru9qM^R)R z&|j5Y_6x3Tmc6sDxDT*rirMjN$9E=ko(*46`VB++e#5x*=QnHWcfwbvH_*rBE19Wy zZjiGt)>tm>%dN3I;QSIz9tQCCiWjfy{z2XjyHv@y@9S@}qXYJ)J%Ly3-Zb2YgrM!7 zR3#s{K$EuscUpP?aP021MB7Y9334K9n}=1&XFkFvvt5mZyJx$nxyQQ)xx2ety6d>hxf5KMTtB&vxZZW`c5Qa8bV;r`uKQgRT!URbT#2r_ zuG?HX=O50K&M%zrIrli9bFOmA&biJE=S1f{&YsRz&U()BPQBwYR2BTv@h`_Kj^`b# z9ZMbaY+Gzk+8(jZw`JQV+lJZt*xK3}*ecmf)@#2Z_KlxIpcjWXS3 z>S$_Ws%Eko|84x)_?_`%;~U29#tp_I<050e(QCZdc(<{Wv8l1T(Qfz)@*=)B95%dZ zc-gSgP;6LiC@@Shj5hQ$bT%|I)G#>of9rqMAJ>1PKcL^?$aLK27~<&VXzjS&QNdxb zU$LLIe`P;t-)n!tzQ+Er{Q-NHeUg2sy|=xMy}rGo-3Yfa&e)FH4%uGSKdmp(Kd7If zPt%Xl_t$sPH`mwHJ9Rg8zv+I^eX4s)w^O%Cw_Nv-Zl-RkZme#AuB)zvu9nV~@K3_; zs=vjhH|vALWLLM-L>@)et_C8Hq-y60L>@uaj>m~SoT?qXL>@-fc7G9hC{^1g5qStz zTVE#fJydPwC-PvbwmeDXK~(jm5P2X~oBu%M0aR_)hsgb@+GGcj`%$&gO(Ne-)rR>* zzKg2$>k_#yRqGxi@|{$z(}u`*P_*eNJR6RbL%WWD8YaIYMMJRrjwY@q56_{(~#Zr?^^9aXnAC2|5)Uz$#2Le(wjiS!RuUl>EAn^b*n z1(E)y>gMW1`irX1EG5#vsk+HVq#IP-xP(Z5QgwrgNY|;lZV{2LQFZM_B3-5GlgUK7 zLelOHIXh+^@#yQx=7WMNksacszsZL^cz(lJ4B>ksk*EOk$$1- zBb$iyGgX&Y|fGI!#sIeMCA%)rEVA zbdsv`FA?b{sy>iMq!Uz~`zw)tr0N_7b1O2 z)!ZkDbd0Lgp}*fyH9Lz)UsE;nIFXK0HDf4|zM|^1-9-A5s_Bi1^aWMZ1{3KBRlPfi z^f^^iZW8G;swU?U=~Jps_7Le4s@_*bq{CF5@FtNyrt0{rMEZ!TV_~#^NY&B6`~g)* z?IY6rR2@l(bcm|MXAtQiRfqlzS#VSxG7$o?R2_U6a@D9hs2AjsQFTCn2xU;U-!LM* zMb*AHh;)Fe9dA`b!tH-3RP>ig`5$pR__T39aOFSH>6xp zwbC@miJ)qQdm&YUs<)kkL;|Xo>kCnSs=8nxy+~DOcOq?}s(mq$UZASw6p@~%s<|RW z)2V8l1Q9l>>bFCcW2)-lFF!+70^@2^NQE*tP9a2kgzDwj*RQ;dbSIZZ>Q?%14OPz)l+v6xh_?I+D_y;R6Ws>$hE2Z19ZO@Rlon4$Tg|@ zT~{L4pz5)9M6MoEci#AkNE@j7XD1@9r|LBrvFoUMWgL;7qUs-GiL{og7h6CbR;vCA zOWzu*UXY-WDOJz?L!?zyJ^LV$R#Np$H7L_b)l;xAK0(!!jfk|IswehA0ZOX=SP6U6h6-?0{kSTW%BJdv>)>g0s(t`7^g*f~DkjomsvZPeEu!jsvx(%R z>O1hIE2QdyBqA-O>Kprsw1BGnp}+H~`ubx;dVs30zD=ZgRNdPSUj3%(o~`gKH&u5x zfQPfGT3QH?T2pn$r|{A=RbPhnc?MOt!I!;&s#|-&%gR)JaWA}nOw}zg7;>rl{2F*e zn5xggV925Bv#{&Srs^hGuCu7RaW_0+OVtg~!3?UdgQ0RiRoBAso<`LtXAvo#s;gl^ zo=VkKV2w1Yu1JN)4Q;j@Qb*Uq22QzI`fK_^y-l~)VX>FkE8CuOFLgK2wMck1VF3A#%ur96DaOJ(cu68tj1c9I zWr9^I1oxAZz^#{vsiVRC)N?VTr(v`6Xv~vVBgSuXc6Nq0DJ!h2U&W+2J8NWkn0wtaVT8gj>P;c$Qn+`aRWa(@Kk>R4j1r#QZB8);k((1=kVm5L^D| zJHMD;H;7o%@?gV}l@_+7op``lIP*WJO!Ur5%FM}t&1dVD9a_#xgk(baMLq127SV35 zHzWA?OWxGp zO=bf(sPLwgJT!2z#(bKD&EPUFJRJi6ys-NgWh8)s%UJY?VRE;?BMnzzWB#2EUk!o> zx|1=#of_VZryw^YZ2J9#`Tv87dxYz0=XGZn$0GYXcDHSWb*1H7OEYtZX{YgbV_U;) z{YUyLy2%M!$e(1eddiQGfeik1NPrNN!B4vrI^$!)gMWc4xrq;F`|8;25=bPT3anxh ziNje#jshfoNGTHZ5Wh&!+45|uhC+BRI1Pwn_g--HZ-jFBmN`iw^n-I%$v5+$cC48p zFMbL@i^+?RFtg@Rgt&`Ns*;bL{w|9R1%kYQEv7(F1UCCkL|UIx>e0t9^>{XQ7fTKE zFBPao&p$kY!m5R=3-_p!Z{hA8Syre?m;$U~Y7$ZlE2rh~r4NbcUs5HP{7mVeEIFjP zCIh*c?Cl8hC_7YyejrbkeE0*KSoj{k;v|5dDJ11G0=~>`E~3x|4!tp`EXI zGISw!Z|z232bGZ%wpT{rIm*zVlgb4@+eLG&0@7V40l1iS*9hB3+i)ZOtRGd$ryqZw zH9LGT?*n?#A57Kkif0{3XO34TpSYpS5<_bAL?9NE8XaNpNcS!>7rdiNF8i57W|kcu zO`iblv3oR~JIEt^#E6{VMU`Civm=hP=wSBo@iTj*qZyfVpHL;2{mkhnSa#TBjRSVk zdn{#;N9?ht--giBZ{tFr9mD4E7IyI!j|J%L_^jzL@FQK`h@G9KNV>+R=c?e|!YDu$bkBluF*9KRGZvMFy*p=s2aP5Cq z*PZPG?B?e|7ew#ol`cfx&2O%b;G3)S!P9!M;IRJB1#r>pzX~43eU8-6ELA0+ev;-M zJ#5nE0KMqFu|i+g-guJ@**Dqv>>a*lEf0I+*}yJ(Z>+GFu{Ykh1kpDx;i8}UaVU!p zW}g*5vzN6u-e5xZ4JI!8*&O>y*FNa5%Jev+CMsvFt_QnN(FM4mR;78dTKbef!PbPD*&(^5GS{>HLe87&= z+F179c=dNkzxq2a{h7-Tvh?skLmtqJd7y#%4FWegLr&CHqmgvgXfEm57Mf>K!6%ao zq@sN?!8@nHT)E(L^hmlwc^zd1|8x!c7VgMS2VyaIWVN>Ss7nZa(d7x{5t=6k zaIJi1?-7<6f&n?eEIJqvv@)H7l)7XRTD)Wum-=iS&2?{BuCsw!^l}}f4h1kMbkSyn zF51k6KJ&%vtf?FLin9Rv4#BPrEOLy1j~!AaAN04*EGU%b$OKR^r8($04wNfXlT;CN zSr1k6aX($g;=)3a0l1q1N0Bb$);kxg9UvrRSU0$3>S2V&6+MSz&jxe)Wx z&yacPXMAS!cdV76)YCLz7E@wIJ19akE`%&AzC-yIzQca(TRDOI|8)~C68$sqzTc<1 z6!+uq2Ci3K_c~8I3!Em$Dn~o}Yxe%O!?sCqA3xXfZ;Q|3f}8YJO;4M;84nvL8h$p+ zGgL~rn6NOR90?SM{Ez>+MH)wVR$9!HFs2k_1#{ckD+97M<{8T2&3I-c<)$YkX9ROV zWlPL+>Lc3o&hn-ds7d^?Ip(>H5e=q#b274Ls}~hy(=C2zZ(>qT&dl8Od~YJG9C`nx zWV*oQWhVk$Cyx0zq0=sub^_Ow!-r>HtE|Ml+!WfE|9+>G{0nu}ha{_*56bX9v1>Nm zvW~e8=@>yLJgix89Y5yX3U5X`*9-#Zni5;k&NaQjxu!H2HrI49AC?g&O)f~!2$c4O zk_a&$CUjWhc{JDz5ttXJ9DBpv$xzTC<|&ooee*=g>wwA;0yB@5&X(!Kg+dhqGmn+l z!~CyM4MSk&vD#)7*D2K95O@blX*kmB3H3b$Uiea)jc`~(84>ZFjr27_xssSK@e$LA zIc-2a6oD7M6ypLwWb_+Kuf%+O%<^S;!|G)be3p@ErDuEwGOiZ3`Y1Jh?bYS(U zyIXYr9L`WB*9mlfh2WBzp0%6Q~Io_1?Dd{PAQxBFMH1hjOp2Pe6JcsiW zG?n&S`busCa528YFz{S>*%B_LQ(GTY#>c@m{PEEzfwgrjUr9MY785}TLk=CCDfGW; zqrLxCn-AS+91GprSKUV4LsXMJ;sT=r8TtF=*?m?;H6A&84 zZ?8wtx7YJQ+pT3mJ-!krfQktuXh1_tMu_+=7ZSha;uCj0!xF>9a{#gEi5K{~h6Zs6 z`ORgB{N^$~^5_99GAzt?Ko%4G&>EQz;SlrwW5~S!7@v8Pm1Tx+whfp?f3t%-Ci=ln z&7PSBWmV{7GyBFN{JwE~c+YDrd}CjU72w5OoT3H~d61Fuwa-<_XC2;}WrbDQ0<5A} zWyKB6gewsC)#0k-Ll2n4Lc^+T258Z%vH~4B4_`Tg)UO=jQzvattM36?_qi0GTwaEJm2gvJ!xtWHSnhy{xPgHG}phU zAFKOa=X2Dyzhv)W`^a6QtCX-Qp$&PHj3D=tn7d1+dXqBprv_i{n_l28@OldJlp0EM z^O(C`qc`SBEy&CPOGA}b@hxVir{#u@oKOfh=I+9XKEhEEObUf?f?aGP{uj(lO2=wj za^sk%2SoHPIHdyzG$?L6)mS(n|)^ZAxJ$VJm!G`LJwBZ!6o;TGqEjt-|RVU^i zd8SvX9_&$Vkv&TB=H{cP1@mHR#XPpm^e81MWhypPGv-Blm}Zi|2Qwo*w*Y^m8Zq~Y z!y=J0b$Ui3tckg^gM+Sm%&n%jky(%*T#oYJM`r^z=yvrYz5XX3=a>UCt2ypGLp=yC zgbiap#3LF+hX&fGf%yJ~4i~}x)sOj{is&En;m1zi9`o;H=r;?TAcFmJ#e6HHX(O~U z1sih;TqMGM&hVI0%!j15Yjn;AJ7Y{Wf7O4e3R<1GSj+q6kZe?S2vbtWtFCY!^QG;hrowWI5CW za4}g95#S-0Dk7ggph`aSdz!jmO?@SG0eP^HyS@xE^~)mVsXJ83r!6|f8WPh(hFhc|M5 z*Hx8#-Xogw8;}cE9eBm$!l@o@)oYG`$J(iq3wo}HW=ViSP)*n%P(c~jJ2D>qN|k)p z-u>7?0IXGov4-|Ji6Q?zG9KBWN-pd9u^+IkkP}h`SVd{iXY``=I-P z`&IW&_lxdl+)uezxF2&%Zl8OuJKvq@p5mV59^)S79^k&i-Ob(J-O}CIUDsXBUEXbX z8(e?8uDX76opt@_`o{IS>qFPOuKlh(uI;YpT^n6%TqUkYTo1VxxMsPgxl&vcT%%m~ zxbAlKa&>mKaW!`}aMf~EcDY>^SAz3~^AG3G&Qs3sonJXWaUOEM<$TRq>U_!htaF`n zrSoy8>|ErW2Q><^oN3O<&auwn&VkN5o!y-soQcjR&U()3&I(S4)9ASAxaRoXan3%- z-q+s4-qGI5-qe1(y@tJ_-Dx-3{;^%RU9_FI{bc*r_J!?Z+rMmY+Vg zur0IsZH2Zuwme&g&1<{QHrh7S*5B60*45U|=CL)h)v;Bz-Db1Fi-~_(uULPzp0WO5 z{o4AO^#kiW)_vC9)@|13tQ)MWt;N=dtq)q~TW4Bxtm)Qd>v-!(>tO3$)}Gc**4EZ$ z*80|()=E~F)odk}KP{Im7c3_&-&wx29JU;^9I(7<*=c#v@{Hvv%L>b5771!F%(diO zGA&aqlPqH_!z=?VcUZbv+FM#$8e8gGs#(fg>=uLhZ^+&F&3xAUqxl>2=jIR1@0$0U z_n5bvpEqwbuQ8XHA2B~^57> z38ovSKTJQHPMN+peP#N@bjb9U=`~ZS=_S*%rgf&3rpHaPX_0B3slb$FN;6G1jWrE7 z4K&?p>Tc>_N;EYw)iYH$RWLbBM&nK6HF!t{NC60xT*^XSt{f<<}M9003A&!2I-i|JgwvHB#hK|~fDvojvt3zl1 zxBasH7yD`Zar;sGr}p>lZ`)tD@3L>TZ?>+lJQ-y9`?mn+@v?s|-bkrG~|Z2MjX|*@mfx zB*Qqv2*V&lUqcT=M?)(^Q^W0s8itAnr@^HE2dZga)SuV?r2kg`h5lpxzw~eF_v&}( zx9B(N*Xo}j#H1&Bva|z=_9)t+Xp5o^iq_@Q= z#p@_uL-8t#y(nHmu?NL&6uVHAqS%RI2a14#iU_)}nY4#Tpc=QLI9-62%G>PoP+iq69@TiXs$`qj(I( zG8B)Zcm&16D3+p-QAjBKD3+jj2*raa7Nb~%!iS;|#X=MdP|Qd10E&4i=AxK`Vm69d zC}yIVfuaCKK8idPxhSTi$U%{fA`3+(iVPI@qnL&w9mP}>X(*vw#Q+rj zQS?J`H;TJZ^hI$eiaSvBLD3sUFBCmd^gz)aMK=^(QFKAk8AT@)9Z_^Z(H=!R6m3zo zLD3pTD-?++TB7ivXn~?Rie@O9qG*DmF^Wbg8lq@`qCSe-QPe|G7eyTuwNcbUQ4>WC z6xC5wLs1n)6%>_GR68OP#;(ZN6&brCV^?JCii};6u`4omMaHhk*cBPOB4bx%?23$Ck+CZ>c16an$Vyj! zz#bh(@jZ&~P<)Hx7>aLDe2wBLimy<7iQ)?sM^Jo@;xiPVqWA>GVH6*u_z1;^C_X^( zK8iyq4x;!MiuX{wi{hQ2kgzKfc16OjNZ1t#yCPv%Br+;6zfntg<>s=CsC|Hu^PoH6f04zK=A~MadP%K07D2hi=Jd9!~3K@lj!jEDJiic1i$<6c3=7 zhhi>@IVfhMn1x~{iWw*hP~@Y?Ly?POI>!IE5cfdWI=KJe-BD!!*?yO86`W+-Smu}y znX8zl7+*BpF!a_h*1fN*mN1@diCrB3zw}=!1V3hP@UV#SV}@e5iONNgyv#s~M9`(O ztHw{N8YNa-0T_Ysouc5*+^Y|tSb5R`I=XJ zAhg>P=*5I~Bj|Gq@}`D>tGw(gT3SJV6lwoSB!_xpjo8 zt0W?MmBg~iPtO`~Ve(a$9InoG2XZl2XCuks_CQ)eR^<^f1C#dYBJCO7l<^L`=H@ zyqJh-1pJhg%t-JGR}j3y6+ZaVt*q4{=+qU!#RT*sz=P$nLL z?-IWeo|Kc77isHq`;oldem?mWO<`PEOgaO(n8hR`J0&T@n;6Vt&Pd8iD}dW!bnSLm zKwx(TF7VmK3s_Ub;OHc5aInBB1-ZH2tdw+y*x3Y$olW?}OB%AoVB(H(F>y*ZR2Ru* zf$fVC*uIz#JiCAeZtE-Q0KiE?!v7i*tH7S%L)LU?Sn>JKUDiu{?mSJf8lqF}fm=*; zDmph@c?>NbmOf}~OCLV;{BKxe!+35NpYfax*PgPxS^3n=CahS#%hZEUJg+%R+{9PX z7KjJNVR)o6lh1&aa&{T`m2%D&e#yet^Odv#*zO`>F?$_Plgz_;%cnl~2U!_Wd)#e5i;fs0p>W_pvSW@q0YT4qbH^+M=tz4*}E zGngT4Gj4$T|1Tw&W|*wHTE;Gh4-Cof)$Y!&qplp6-dXId>nL^HZ9it8V*Atfpv`Gr zX>9?~=zb7UPBNXWMzr2p@KR;;1}t%x^Q$t##mX2x@qp zcW}(__0YDIn;QAqIq4}dPKZ1(=GR3d8iUK^c`3Q+$-%Qckq5;5B1%My%z>83{bSx9 zZx9o?Ma+v7)BY(=of+9#u#U2)8Y1@--)#QO^o;auZL@a^9IQ%j>0rGp=7o_XOq=hW zl@ITcrl)AT*;i!61^Qhia$?MHzA>XU{F6rHmNCD4#x$pXjfm`l1vTw|awj%-hBw#4 zzRgR2IOdMqAaBe^V|aJ|cdNFu=4$af0-N~n%%?N{QCn7@}0 z(bc@n{2c8p?-TPv8c`YzY;}m-Tl`O%7sZuMc)^L>Q~Zw@?!YE;kC@-% zjrb7*ch16m&qVGX^K0f2?S{FHiQFyb>s>^fs>heeUB&;J;m%qjcZvCMWqnhupOwg+ zV{T2hEscwm$eo0CjP-63xg$NtkcGxyEG$s^n&L?A@)R19+BHlHi9!wKs)G!BXXOVH$eAG!OvW4uMu2evFrhDKy`f) zxfRC$ClmKwu4PdDue@WjeUt61t*vz)RR61O&V)>FvvG`JgZ@{22c0kBU_yB^Sv}+b zCo*tTe>6BnL`T_z!Jqu3T=;!L9+6!=KMZaJR*f~arIsx7ISx;ekFp$ z^n_2Td*ExYyL#|nd%e(8b0H04gQI|2bo4un8hm`gN)l-2Zg>M_SGUuAd-prX+8f-G zBY|9uTQbbvs(*u8yQ=}&yBhe+uV}83L+ok|7l-FX6^dxz!;ceo`y z9Js~Y5)R`=l?knMJdVg6kMohY?qG)p+^ZS}$YSnQMMu_Jx`P+7J9zoncWK_%Xyz*! z3fN-a2d3Bo7pUsyLCki4sgjTToaV|MOu`|6D|!+JaOs+-`rCK4O+x0jNqpulnx{bE z({c|mi~h6(nALS7MBMr^61Tq0Cq8hU9m^1-9}L7|(jc^hLYaLb;8uPFZsq3#KQNaC zhVaWE02UK|p}-+e6f(9vsY*WUGn!Bl42OYn7!F~903`Kby_a1ce!Z6qyEVloU}+lw z#G;org*eK*YyJb`H~)ce=sWhXg974Q{Q+A{oGW}#L{7bCN&-YPegedWF}qplj=qw9 z0G%!*LQkO;M^0p%0S(<`hbs97pZQc6``z(lj|^5IbEBK8(uVn}O8NqEc6>%k)UXL+*RQKeKK?y+79X;X?*#lfWgX{7@p>b5 z-9xJ6(=XCw{lJoV2hfXN5~I1!5w}hoRr0attYnQ2r>{PME&BAOVu$(Pk+@c-D*5E= z+1C|p)}y3O!cpQbcDHc7=^Ek8by^%xSf^R8S^Sm?a8ta!>0PJ*c+xo2sE7N_mGv*^ zTkGD_4NExcsA=D3?_@h*8)d!VJd==>VEnJW3|Lmw6(R{S_kbzkyWkT7Q=oP_ymuaY zHi*cXF%MC)?Ijna+^^If&4~G%m1;xECqB@(p!ev0fk6_b0!6f$PvjJVu5P8_$mmnD z!01z`QH(w%i8pNY=+oqwd%fwVMd@QG`ZP)Wj~E$!x=&#AN$FtJ=+i`j(I=(di0IRV znETu#eoPvD8ZZ9WjEp{w6F6Ma*BjXB;hY>B^X~<dj$@cGQ7t`9u@QCov>c24jk;`$e4%q%4m)bnh`NC10L2SszG-vk%v2f zBo)GK%EOCvuwj zW+RW`M4lpW^8@;x!{nD%#521@WuH8|!OpR_GBW3ZV)0_~^# zT6B&N#Q6XC!2SQ#&L5mD9R>DRY&UI#t;;OOEe*|Srss@T;a0$W{YU!Ry3B$5q_jcKS+||Yfak0^@p5mn$CK1;7U&hK#RH3!$OCq z4AM^asFF*2_Ui2{Ekqgb2U;;vMwM3UTtLkGo>nCn_guT9EH1>qrU9;)_*WQin0+T! zMc|25`M`<2SYWVkx^Vky_fLp9ezq#PxM$B^WO2d1Q-#|%d=rMCWAXifU1P8Ef&bCG zWeri8GyoPIl__&4hwNjp!2PZ<1G(%MKIq6A8`!7Bk3Dibi0t>`1M|D?syw|22+q(D?A6^KPgWmMv58&kv{@uVvG_^A%o;1HEb z0esO>nGk;DT?C{ae!D99^h-4K5Z*`zdePwxg+AQDi^N0m{^+iu{QIL9Ue{D7fto={ zKrXswP>4L>UqId=ilv9#&bRb^UBbr6kH8q0!x-nZDrW-Mi_960}1A$Jk?AlDk_Z_b{M$L&AZ zTifPazqHne_y0aH*EP*G9x~Q9r0aL?>kH_}Sosu^uY8J2 ze(t)a>>d<%dH~496n8@Mz?vSi?-Q>eA z73bRWTR7ML(qt;u^_9#8;;upxEs+?!!y&U47ob^-3;1R=YRn4NsOA8qm}*oZ$gmac zais{^bp00^0O*_UYAWnXeld+z2LmbbpIWESxD7Wn&z z;ws4Zh^$I3=lRN+EGI0sGl5ggrx)$2xY(nZR&I>Qa$`Png+?qgn0AI>)8c+CGz1>% zh@1~~P$L_Ki_YyJ#^YFXET2JYQ2&W*9;O`G71omqH!tjoKwg<=M zjmd@$#5EEGrD%Y~e#!W%bNR_s$Ff=S@c7yvbbPvln);z;KB&3xLI( zE5nT&*fMCCQp=#{!4wP?r+_r?h?1h^_FX_^A~tuuaaYj z<4*gJ@ETe<+jiR>))UrD%Rlf2T}$(u=3%C@@aCHdUTte^*k1`Jh4_d?-hoKO25nA}>oe!e%3uB^B6nbFhg=V}6x@Z31rk-tWx{ zHuOl$6PC0M1v5~CEj=9br_s#q3&@8mpWL69UFhMaShAUP`_47ciR6#D74h_|93NCKE|KzMUM5P@km7(P(%msPpQatnnUhG1V}7%uoYtt@ zlSp^PyigT3s(37kv?%8Js! zOGR4=8*}qxzURfJLXI^e%@Z_cGktIBVw4Og4bAk6bw_k96Bdz= zwI}@lG%df8zwk!z!ib63;KnvM1~sMc-rbK5qj&dn9Y$wQ9%h^``7Qi~HH3M%7*xd# z!oJz`mJ+gg>pCHu2WGOsb^V3a0a#4P4uSDgjMhB(qbm7Uoj00=Z0s+*0U*WrI75&g ztTqW#78&1AYM8yjuVHrfZHPa#OFO!!18wR7ghjXF$pso-oTXe=H|={_{tN#@YYm_d`||F@5$hkudTB+_{z5A-i@CKB zjXB(xkI>tdyE)tWcXQ4@*@1tpvNUmGIFQrm_ZyPoELc zMed4}MI?>JHxP77ZB_Dt&$4yn1M&Zl_0JRcPwtcMBknicyWCsc#qRsv^WC%DliWky zJ=`tbb=(!)39d`7Q?5^32VJ{ePrBB)9&jyi&2~+84RiH$wQ|*URdnf`KRZu5k2>FU zmN>UM*E%KVLT9RTigUQLm$S9Ap0kou@A$=0>iE?0mSd0ODaSg8?6}jm&9>gQ%yyS8 z!#2$}%GTG`&ep(I)n>9@v3_SgZhhDKqV*Z;2J3R`Vr!<=YaMOvXKin7Xsu>7TYj^g zwR~=Q&$8dL-SUWKh2?I`9Lsde7)yUk2TLQ%4Hk>}ck}n=FU*I`FPV3kA2mN{&NpY7 z6U}4I1I!)Gjm_1~R?}6}In$S>_f0RGo;7VWtu*;f*`_4ZIMXerPNpWN8YY|Zn(@5x zE8_>o1IC@kO~zHmdyF|opK-i#ps};Dsqsdm-SCIug5hh!hlW=S&lw&wJY=}nkZYJ> zm|z%W=wfJQsA+KM|Af~QzR@4nzp8)Uk>D?Zmw>o?l#>JT{m3|-Ay`I!ruu$s$LqG-mDJ}liero zA#xL{e!Z2*jj8(OTp~B3>St?-+>olr+(d3b)uS0izL}~=&JwvkRX?6UMXIixNaPAsUGX!K z-BexfC$fvG1%D9PNmY3kksVZhpf{22R2|)oNav|Kd^?fOQFT~vB7INQTaOXxELDdj z6X`pu4*H8oXQ(>xej=4o^%gUcN~zla5h9(YYQF|VIz`n!+lX|Ms=b>M>07Gyg#Y#g zReRJR(l=D?Rz#$)soLddB7H^G&U1+LB~?2@f4`t=`(8x)oT_c66X`frJ+Bk#GpaU! zj7Z0*+RQ|xPpR7EJ|Z2ZYNH>B^a)iP<`d}%RU3eDKBj8@RYdxTs`Z)?=`dC6>><*J zRIS~WNFPwO)~7^zpQ<(65$OuN!1D`h;)#u?%70ogR0KoiS#;E9oa;BjjDD#kzS>$bsdpjp{k`8kq%JR^emBH zrmFE)BE3Xa{ZS(Ar>brukzS-Kfx)mZr0)8=C6V@0_0L^I+C$ZAe-NpJs#gn$w418G zJBhT5s#n$%>0ea6e4a=zQ1utEaNKRS&;SqzzR4upyDw zQ}umVHy)Gpz69dkhVb8HL!Z$Mb#o$%@$F$usQ_jsrpbZ#M7y|@?i*kQ*{OW zzVoTN3_3WEs#0T!^ip*RSR;?B_uNaQ+>p9^>1HC^sJf&*k*!p{cOQ{0RP|pbvYD#+ zf%p`Y^3U4eTZzJ>YcC+&{K7RnaDb-&YMr<1ghqh5t&dmcLb6CrfT-9MEZ-W zS+JV@N!83oMEZlO>3$+zqiX63B3-5GtOtqoJ5^_XMx@`UnrtJ|6{`A16X{o~CaxsX zWvY626X_SKPAwtQ&s3cOx4} zl|KNY(^S3dF9;x0brH<6EUGRjg-|S2=hY%oCRMYiK~$5fi7K%_0X*N}-Ko@3Fb<%tyrBL;@Ux_r6suST`mQ2<0@Egsb>bR;InE#FI9)ZpH8Fd&{jm6O4T7R66p@A4(?8*DO4Q@yP(Nby`?6RCQ-Hj z-9);bs(t?^(rr}j109@5)n2erOrUDdsYDu2)$V0b)0L{-3`81B)h?5XG={33zJY?J zRPE>^(kQC7{{xC9Qnekd{3EE^<`*aeNY&P`aUDk0mZym{l&YRYc($FY&0*U!gsRQ@ z!jtDzZ307O5LFw&m>fvehB-vKg{n8#CDH(@)_n(F{-tW2wnXYj)tl0Y)R(F?Pr;+M zRK4*wcxsla)!&5IV5xco{MNdIy-A!EwT$7z=A^*RYW4~jh{d+i*RV9YmPAe+p)-)KQ~qxcf2M8Dams)vXVU1I}W?$ zn5Rsl`%ld+ixT*P{a(xya5RlFF{}S$cT&X9L2r6S`uwzv+-%J#c_!v5bohfQ33Q=E z4>+HRZ7Ec)0FHh!PoUHENlgfWL#5z`W@e=0nYeUO4WyEQ zmqYBxSF3k{|3s`I@sk}f@;Amj^B+e^DD(eOLG}w~SJJnf!KEZVvWvi570cb+ zEN`B-6}6csFyLo+6Cu9_$KQIPjfJwzv9X6^ezSq;nUV?%4m?4tZSa@UWU+#GFy?nb zut%7H3hqWht85@2li5-f3;JQ$v`_Gk#`5IA4D3KFb z!2C)N2^!c+OPWP!Rm`t6u!hs@oL6H0|0Bdb+_fI={P%LKwSR4IZOga5X}!^sX5Md3 zFpV)jVffWBQ2zkD`{zoSOdcu!Y#-}C$?xJXYz^rYF)y1O{U93cgpWBDKaEl)H@Bkn zEzM(=9)DpgppSV;uITitn*d2K9#$ov__w2M`U>QDw*=yt=Xgga*7_Qd_lM!CCm_ zJcwtkc)IgO#DF-~`Erje%BVvY~3*XdVhg zKY5ob`G!vXfHgEE8#V%Tk;#TCI(2g(=!vDOR3N$x(ncHCDfV z4Pn22jSqX^5DN>}$Ql5w$ZKQ@ENq}dH!i-iBI{RHKI_vXSXLOsH^*lXN8Rir@)uK7 z$w$AV9g7ZMj{1Nehc8FS^@Etlm0McJ=kjsqe9Gd&Qd|#k0m+J`jN z|6p9yjnBA<>V!h%qsl{EN3Zh`SN`3sq3ihz>j1i#s=K&WD4r~&{6wcpzJVXq)O?5G zP+RbD2y=%a<;TgYXt)}$F~T~3S0xv^^pNJQ#RmSuz5v}% zu#W-V&j{$qRwW;F%Rbh+a4hHppfNudgjqM>`lY!V2x_;hk`Mfn=DskD-rjK-y{tzZ zF|F%V$;UnVA#2}G{=!~>8}mmCqu96n-S%z^*3<>bXTPQ?-~ltQC$Nj2d68~yG_(mF z3cF2wheGL6jdu@jy7mC*nBQ~_Gq@I7J(2A;;=4K^xrQz?Y-I-txbwOLvuMw?!WyL8jOF!4VdkVv(Tl|IzlM#imx{0dfLYGYYPZ#bUs;dfSJrdE%W6Hwg2Q-e7r*gR{>Eh2 z<@1Pt`8*fD^j~vXe5iKQ7Vu+U?I!wy7{E`Q=}k@br6&in6Os6rajN8!msR|hC5JD4 z8z2|`rB^0uxnKHSmkuEPr2~BW8ZeQQygA<0Q4CMdUO*lmK>-6<>Tivp|qHBYz znRBPJx8ozn6#K9CC3dIn5nD@ZiFKIeTgxJg)BL!(t?3QZ1mpL{49E+}H<)$Z6AmRz zAYYNp>w5-bner6&)2g8gB_;&daOWFg`HWGqSWaW%pI5l?8_TqHUd#0S1^0?$Sn^#Ltwd9}KwPE`Fwjuk~PLwXShGPtk5z?eTr?25$ZFtMw{JK|T~G|vnVW{$rtzA-gA26YW$S*|&39SZj> zL)nB_KF$!WwZL$t!3ZeK5X&6LXbpyvci#~B0SOvXgR6S6)W%0f7TV>wLqU^_TzYT~S}Fq>RMuR=#=Ov`l!@ ztyP9;6_bpFRCX9%IC!L0zuR< z89<*-;K8zmg&FLH`e7Pyq!>kBwzoOAMrQxAu(byI7woj%At;=JaA}aWw#1^ zCR5T=a#Fm(JAOfj$nMT_RLOUYbehUIM)DyjISGh`h16MM*tCbdP`f)~b!(7(+-^U! zxR8i+JK)AVFD;6JXQX`-^$(ods<4N>pC55c)c^#oWuk)enpJbuI$`j&b<>^@& zbMdh?1a1D9D*3=|6IftyzK;iB(av|}j2^amK;UL3Rr0}I->~42=rj(%MJGBb;MzL{ zyPMpH$W89!BPT3iks**b7LY{;@>Jx|GoQ%X=m%BunX70byf6#L0JE@Js1$rrn33(84}_T4=Sf1Cll{tCCNAMiYwx;!$xVW-oE#yPy z%NiR)@M|Oxiw>4510(7d8L{g%Qzaii|0{NgK=5k>;EN7^Y4GVW28rwJQ6-=Jkt-}Y z%*f$D9;X?pUbzc>7i;5ns@=7_@}Ylzl7)uv;xK>~w)@b|NcJkq?ppZl5=cJqUxWpQ z;XO2d!#nB$1qVmXcBZAb+(lxcsGi$FltJ9U27u zar$zq;R__Kin##0tB&InFaIHocwqd9)ffm8SH@dzyDRf=xs@JfZ+r*h|8;crh(1kE zbPu^7bk}pe;OgZ(;!Jd0aV&Q5>4)oVG!4PEJii5eWE=LE#xXx|iX zZEjYoN87*e1vsZ8n$3n~Ej>A`<+F>8`3r?D14@Upe5t{@ec3ZpGQ-;cE|wM4B9>RB z{fJi22uRn6uy;y&jxQO)l-i%VOz1MNb~v=mmkJ1dM)Y(>YKAu_te>an8sRmt*haD= z8uq2W`3dNk@5h4L65w=q>37BvZymBPCZ#2>aPbdkP-fGo##j6k& zq=9#u1g85bZHD42@C=lI?{HWTsjmc{nG!KrwC+eIssZm<1>*lz$@|1T#`Tc%b7u|5 zbo*v_Z?35|*Rsoe)!f09XWVCW7{=-!)}7Y1PVmED{m=a;AH30X!2Kf18%;MBfjk5D zyN({1NlR48^%-Xj)CNn2 zPQ<+M;Xib*Ao`%cRLMm@)#3(r_&{K52B3=yY()&8Xg(U`9(cbh`TWB)RXE@y>H~i9 zA5mresQ!Fpy+uh1xy8(9t~iRdIfO!!fLT;1G{WYQ-Xf&$|A;EN^e3O}$kM~Z^NBzo z^M~il8|)D-Cxq^YHM(~98V)t&!#XdDelONaJUpNi0v*WeK!vu)*pdolqWytq@gx`S#Gi!I)K2C)W zh~GXcc8{`s>`?k3c6bp3drIA+~a?MEWeY#$OOh0zbjUJMbUS~`AYUkK0kZp+Fi}!iu@O@9I;2C!lW4 z$zSYjCp!9z^w0_MyJDpiVL?Z<`<+u&$wfbP+n+3YH-C{1(8aHtDteU2C2}uNc9;vU zv%?(OnC0){FG>J@@jFa~zq}phy!qIRdGqsLI|Au*M{wy+b^L^-haKi!KreoWshB=uhnf8y`Ld?+5$rJUgbs+`VJaPnvct@5gqF{2#05WP z8pm25c9;tRJZ>vx`8&*XKk}#hx%?+f*-cxZ(%}N&7ggzyp2Y)Y8$xc%)D_5@x`NAk zs+NVtYf|Gq(2D z7p=W5?^=eK51Vf@{b8Zh6 z4YFH64tGS0@V!pVRWEMHE&&NQ+VzQ}&Yt1SWs44v+H zObregv(OtN%6T~4_e^AyfUjV9|2$EWDTr(odP79%aJe2|A{&I>5K-C>bJh}BFErO& zZ8eIYmB>1wHyD(rBVD9KP7r!!Luoj|yGdjcj}AvVCW-X7fW<#zQfYQ2e+j*^p_mvD zA_LAu`cuGHAfmTno1#DBF^!@*;fQoiKrKYtUB!P!q^knHbJ}JwQ#R=OBGT_dx3xh( ziaKBeZWJQ@CSbb~);~ICu*oYzr)8wCh)BQsjNtAOby*GFJVd%I-~tCVCF`Lf(l3Gd ze>IXq+@oEOK>Xk1$g{s~ciSddH(D-P+L;%b-ZoV+rWl^nU)2xLNeQ1MG=abT@BEVw z!R^3fj-rCwbknCUZz2DHN8SISf8^jZs^t1fN=FP~{3PIVFABWuD9Ytd@s%Y58J|${ zub<%OUzhe?%(Axe7u_h(6QyMhc?_sO_3UNyOIcgD^A}YEY*A5;Fl>5UrQGXwAosc*eD1b` zSnfvtqN>0xDqKLh@jHTuYdxyuqqcgKMQ!CTssgB@yzd&+(DD(Qg2hVmOYu}bbB6{j zGfctCz$|_W20oyn!5o4vyo!b{yvm0jt-1OI3w0%c78Nqk8k!E}5cTS1NWFR)pL+7s ztf}EkUJMyDQ_@Zw4P@{)j_ei-?xdgV7e+jJg z)-$ZJVU>0Rt@u?MX(OlO3MH*{1wXB{v|mjY8&+u-V2fX+73|0vxm?MtSkBL^DD`e; zx!e1ToWLzAr6qiDFvB}EDGTtqz}*Gcc`mTWb1XQFYDZi~HTqOTwDK$*-SRB{931p6 zOADjg9+y$Acz_w#I^sT{Tw8mfHy`_!@KJ4x%cxecBS-bp&B(uWGoQP~Z>+gtR9oXR zsuga!XotqhlJ*F`q&*+J_CgjMb|Mx47rzrxz_lmEd-oypz5Dpgoiup>FcZzdEb9A0 zkMelX4O!TK8EO5OxwNPHuV*YAjQ>N{uzQKSs_O|?N9SSZ6vsKoLWj}5+U~Kv051W& zZ%wjXvlLpIm=Bmon$DUQnB2xkjZF=^4FmKa>yvbsb$*>IVO>IVvX_h$5MP<;^QPv^ z3>NvDlk3aH$aH%F&Y$pxJac{1XJ%x~4($Ai+)jW8FQUcVYW zuoSgUZu*vgxkIX5dM$4CDkaL50%2e2Yq4Sw^`uuWze^GC(l!OgUnnLFK+ojW~f z(8gjX;S895z9i4AjOp03Mgqb-OwW=$*sF$Od&LZppb;C0{oE#c6KCS*_GSSE#~AZ@ z!J(O#l9h|UReb?r7Wn35&YY9l3U&}#^MkglC%|@UD`~ko!B1SUp}GPZ3N65`LYqJ$ z*AcKM3U7$@4-mPwfDJ=Li<-j(k#7=^;=*Y&6g(nwEdgr?ZCMQ!%QXdjPPNU1engya zHwyT+g*6xvZ6R_E0pGT;R+&Hvk*f=x9l>yM=(vt{y+Ob>C9H>ZZeWwu1T3AjNsKHI zxvGG#oTin~01YmnRfLX|aDP6LD+`@~TBmlfga3oM>lpu+h)D zTp7)@%(?4SklCdf z-7Wn^9$*&rs$GPw6(Xc5oh5&CSwLXN!O-Kt7H_v@PXB_R^r z9JobAf+I{#-6=?0wnvqG>T{p7gBq;eES}b8eKN><`kE^F-0xpyxgpi4DR7HQHHxq{ zb8Zjp(-8UO8CCMpzd697L!LtuKo^zg5P=@@4k7G`dsNAXKB6hA(%fIv7@$W9x+=>+ zQx_9*e!W$dd|r7qYh+lg8v(DVuoJ_p^;041mvdFgXWk;Q%#fhi5ST?JC^F3G>_W!R z)~b@vdP)i~@qQZKNeO0#`QXb7vC7*WR zB9_+UFRBl;qMlA;Xj$JKk{&s$N*s^p@cZlJmO z4@04@z@ea`GG0WaJp7_6`Ls=@vxWuQIs$1!J0R+cM9L42tCCAwI$pChKxRm7pcS9* zq@;;QWQH8-huDYu@v&!VN)W+8@Fu_(pEned-5y%j-l>Y52SpP5(vy<2Qj$EGSs8gL zNxr}fFvwlAqAL0Pg;^{=9O`ZXeo=?I2>#66?3p3t8hMCZBd>hqKw-gw%UEQn={Nw8 zMb&hSKu*g}?$Rd0+&5sU@RA#jmCp|K1k3U@g@++owm-0oN|udehrnlYZhGWssn#4# zU#&SGKUcGlfRj=`z!!B=iolnG-YMrcoA)>_FdViK7D_IrB{xxr4u`2Ox`j-d$vbZ<eQJZ@@UIokHhYE|-WykZke3!jR1Kr8A~!3#^tYdM~Dbg{o{pKL3&<=KdJiPde{ zWNBpHYwm0Mz%<5q%sA6<(U4~_BpgkcLH;Bwc;|jKsX~?6K5a^CFqKR|sx;lF2Qn{E z!=%Qs0uu9RYZzgJDL~{g0`g_T8}j62WTqqrn;R`4D=(rs$m7jU%u1Oa^hXeRRCzyZ zY%-O@mlYy+5b)!L&#|C2|L@;45s(-cF}p)b`(E1kp~Lh5hy>Y;-V(< zE%EptgS+*^Q6+151vOCt9Y+&R|uNaUV5M(`fSw(y#!bCF&{BKHumFN)qMI{b*- zUG#6r`s#?>EyW1#Hj!3EHye?=PB((5Oh`-UAtQ1Z0Zq{JK=3ozIoSyQso3^{Hlg~Z zh}=o+EllcCB63HJ|F_9a?McPMA4W(utorRhHO^ z1#jUmngHOU9@U}X0l%eswnqzhSffh5rN4ZK1%~N39)QJ9#{e*00pZ(;wCxjA$)`S{ zsmKK%n{hxb{$mrMR@aaab6dsIZP)Ob|Jco18e;Tgfmu{4gm!2s^DuDou zi(lvz<|s3;MQa3a(V7oFwFwIjk*$#cE-JDWJ~SdHVbfB?Zd%I6p66q+;W^n6fSo2N zLQk>FbvPq+6TK?=^lLTq5$K1yhQb%BY1s$#J8kA{}JD^v|VfmAT#+^=s?^ulXHBLPI%<6 zr+o42CGmfNr!*CkVSyY1{NfkLXr6oouY-3MO6nZvgKtP-4G(9u!2mA)jHZHzg#(bi zc0E<{+23KeDuMWa9bH|bpRM~-x7@wLeY5LXS1;$g&f6R(9T^T{Uv95!d&<_;`i6Cg zfLc%R z)$rw|_~r&ZHMs&@cM%P09s$e|;Im;{oSvIFJNOJJk+TK751}@tY#jmy4H_~_fSWh0 zEv9F41o%JcvKzL)C-OJ}ozpglTD-GO1db170Sb+eOaUfT$A{7uGd?nehVRu2VNvo1 z(&N!^`*5(enmo3k@=d+K$|^5P6o+0HM-!WDGw=XbeBp zY``B%Z}b>`vVcW`uCq!%Loxgr@%S+#WB5LyF?^+yQDgW?LSy(!%MmgB#CWVs zG=@Jt9=~d24Bsns=wf&)khh6*bee!|E1f8`HP!n~F~K-KxMwLMo|q$nTULw&;-BWkEygr z`#4d+cAEB)jqMP5g3wVD5tbqH_(1%>Dk%%x|1WZW?rh|kZGXo0qpgQ^k>x#$+dRUw z-1xb%mf;TlHr-X-z=R_BtN#oC$%hL&+2ElObzw(6vIHy~ID)I6w5S>oYT;&5BXT-tA;pc8do|>adzKw0QSQ|qWBOQ>%$6%Cg zYGl$sQcuZOC71q;V}BTZT0H3^Jpf2OX^bkl^koYxv-A*yNdpVC#*< zqt>gEZ|y~|vBWT1lH)mAqWNc#d!$j7eEtW&XZhiaGz0iWef1+OuBjz7d@u8MbBH)X!C8Xeo`K%Cq(6_4Oqu-*bKn35@>3|-$Z>j3|Le_y;;=5!Z zzr=UhzckAsjC5~2M|!yT4A}?VtxCSVNBzPM6_GhgWBv2Q{geBo`-uAu_b&Gqcd`3^ z_k8y(_aygFcMo?HcY^DZ>y+yg*Fo2A*ORU_t_NHTT(e!1UBg^GU9DVoT@_tA z=g-d5&ZEvZoh8n#&b3a-xzL&FoZ=kr?B#6jtmmxc)H{B0lsZ0jyye*Ac*?QPAv^B0 zZL_VnEwkNa%dkzejk5K%wX-#_RkfL{SFGPzk6YihzG!{My1}~Ky4ad&^;$<;`&rvt z8(OPb&6eLRXDy$DmtwzVyX6tf3d`M=IhN^`F_!+84wgoi8{qcB?~twVh53;ACG!sR zqvi+A`Q|KhqIs-&fVrc&vAMe0YPxDVXZq6gzUgJtv!;!vl_tL_+mvJ)XS&7I$<)MD z!(=mFGoCkoW&FT+z_`=6$+*gRk1@ySGmbY7Ga=m` z&6tk1XG&8dU!&@z{Y1V>)!VBR`FE;L+)U)(s5+q@k*`p7+;$@WO4TvH5&1GzN8dx_ zU#L3r4w$or^z3jTC2RZn&z@*b+5_<+bIRQ(42bT?JMf27{47U-CGs|^zW+9npQh@eenftXs_(u;Qj4&yq2n4;eTokRkti4axqmmze(gGsy^PB$c0qhw3^7Psru*vB0ogc zM_Leh6;;;{Ch|(Eu7e5tAXV2KCh`iZ7Q;`roT`N|C6`h4p|6QtK-HBOi7Zof#YrMd zR9&`|$PZ9e+DPR4sk#(K&Qhx0w~5G0sCqB-_dcrnpCIzRRL!qTi4rt`<=>7iQ?4RLyQi^r%_RU1jqiV{HM9!sZGOVIGRQ16O&8BJ+bU%x#(~F2ahpJvTku#|} zHHXLfk;utZ z9X^G~GpIVWHIaQ(9gm@r z&#BtvJt7~cYGe4*lEezId!Z2$xKQ>xa#M&zSZt+$BCpHQ_9>~oG#wRSfme@xX{ z`-%J!RcpeZ9;RxIT}1wns@2;O`2(s}+f3y5samxfkq=R|avvhUN7ahEiTo~AD^w=( zJ5+VGA@bW)wLeDWx2S4{U*XM=T5=ga#|NqUGwjXYpz0-9`d+8%PfdvY8dWcr5cyTA z{xF2duTZsSMX2;a)f#zFii4^*z-Ms)Rja{d?@!e#uqW(C)k^1~-~&}F!eHn_Rrgw` zlt5J{bfFhj9UY+5099?bLlFR~T57=!eX1Ja8`_PkdIwx{rz$xGSJFc&)Iub3XR7`w z!!2*BUi%boVpH|^*Py%=Rjcz%Q}q(8S8b{KBP>vDsQSYpcww8W7odZ! zsCw=Zc%7Q6-@^yUL)GtYC2|X@mO+1;Q}r|q{$^A?3Cnd;s-C!q$W5sFHGIn&Q}xTa zL~caY&)`RCNY!JoiZ-C?(F`KrOw}W2iCmwmA5S21J*pmlk;rwa`T-2!I#dm8^J-J| z9auJRqUynC;E7MFKCzU@HL3de5hCA6)lKjntU=WcpTPr@R9)YN$Tv_mu+OPR)wLdY zLXoP)u<}=-YT;FQfsm@JVOmw9>Z*%Gu1M9D6Ny}bsw;jbvYV>Q{X}+AwE$KmCspNH zM0Vi)|F;71|A(9>oNXO<+Yj4svZY!}tWL{B^A6J=rV+-ihF=Ur^$+U4(6vaolf0## zCI5qDertcR6}&H^u0H1ms}(AdQAlXYNN*eXS0VTRvZd&QS+?7-r}m@o+(6B^t!UmBD`%$}K&85$G!Z9?e#HgTa(|L`aa-N|2U1ZYtKxN@L9 z+3;X>@cC_IzPGU|`Rw1$V%cx@7aM?GR83@L54b-=HugV(oc<^HoWCAtIa~RQ^}s30 zn@>5R+^9M%=-kU!5^VD8@|jCZS?2owVjVE|5_FptnIV5EWZK2c(6oz}@i8yG&0;q3 z7bgIws4~tW%&_%rkx~<85x*wP>8lU2upWOg0a#H1V+u=$LCCy!Dlwfq`7xc--#2B6 z8~TeD1MvW%qX4tQLZl0x#euNkS?)k6bzERcp%%$qKq~5kjJ8$s*P@treszSNU!4za zxu1mw^DYu@Ufe~5%$tWV6qe*|<&vKMOH&pI%zLMB^D6tDDCW&o>eJ-%>(i80^|R)M zjJt&ZEjp`F4gcaLMjQv(%~Z*^vim#>3}MIx04ypDsb)1Qz+qX9bCd+0Is62kQ-3sK zks;G{J|K(QQ>w_pAY|YgApNdo)<6?y*5I4Cc2AZUl6K|+uc$Rx!;1!{#OX@XPWpN- z@u}Y~v&2v-WiAkls+6J<2Xcv(dzNU|)OS_Mr9FM)V=OHU;k-BuVU^aS+`&fF**B|_ zkF3{xI-pKbE+C7lQxtAs=H@ukrrfAXK6O>iyJ`^s&jD&t@&5>F=K49}CJ#_0AKSq` zg&eH^uNy}6kLX+IUepbP*nczE0oN#a3ozGN!LiZN&HjOXhTUK*w6%p;{H>O6EqNA` zxzOCqwBOX<_>s|TI0G*LSQEZY$V;e59{;y|0=%npvyB3-VBv9I**(CUdhmoz&V2YH zL!c|k2)nD;)_7!{2f;=P1r!Tl8-a2~vwi8ordA8My`pU@c)csw)jU{Hy&&=@z{#|fnuH>ySSt&WbR-tDq zk}?vrTlwaB(=uUi)2dC&jxFc4g8!L3UzTTfMowxtJzm=03IR7PHSJ|Wdzs$sY}(}VxyJn20+&or+6=EJ%a@n|zrlP@Vuo5&c$t9Z zM$^?aPf~}#zX%SY0?}*sEYDm|!21Gu45FvU^swn6i5{dHk2$1b2(TqO1eBAM>gjzm~!a5brVFzhr0?q*HPFd?~gPb%0ALX#NLT)lhc@yvlf8CT^4%yIVQ*Cy*9J^c zPQehS2VX;g9}g*?lT^v4J+Ojx3PP0bCZH7+rK7a!Mhqc$5>@hHCH96&eg}VXEr1nO zkDtOuJ!c^Cj$2j9C*Qu0HFHCMaZMl>6|F<^(AN?PpE;;XKIxOQS<)8%;v0cfRAh!F z4IjbV`XTVPeth7`ZWg$uzqkefi;B!>fECvTjT=0rJaGLK|AFh%<14br5N)mw$f6=0 z(U3#S#8zeIZ6$mozxESL47n&b0I{fC6b*4;@_BP}W(It*iC%d1IK;kX0S=HY3;65> znnVN`Al2eEKo}1)qHcaum3-twOIdTna#0nK#V!}2eJBz>t|atimp7GHb%-PIqsm(WkMiFNIQ`i( z>`;KUq7nd$T`Lq|>X}92M_Qj$fnPrd79 zmb$CIxB^g%x=|mEI^0K$*z0zvl8;|Jg~f*qM>pV$O0v=7vyNtjU2|BKeCW5Tv(WAQ z#V&vr^%9o`I^0{0yv2Q0$>&bhY&kmni=DtdTTt$mhMTh$EnJ20g{%1RIhsv0d=4D| zFLuAAEGUfM98n+oT9tg{Po8AQ34CPifE<^PjOu(x&XpHc$>)8#2g?g9pbdEAvI1&7 z_(;3rq$>H;a~m+!82_I}^iS&t=#J^8xgT;jbnSJGb$;WV>vTDuarCr*YEQQPW-GAO zv%YM-#qxzE!+gcO+}yyl+tkx|#5fb~zdvZGns6dvHu;0(6Y^iIMjMl|#OV+en#F|e zyotg0LtCi>GWbe$t|!Zr%7n&CV&Z1LPSfhZf-BN7DbRVH=7M!Ym_F`WY|LNy-}Y_) zqecTk!MPb(NgleNfSca}f)uz=s{Y$3#|F5)EWit?X_ndX{~yd5iN~Dure~zjPs_;7 z){K`I1h}g4hf^HYA@>>79T44C=uQO`H4xya*7Qqtv_ZiH;Z4oVNXI8Fo)s4PSL3*W zraTb$hpY;43aI%bJA_SdwOwT`3;M{n3kV@=e!EZz`56Ije@#oUtqgW)o9G`d>i!i< zZit?8sov?n)PSQ7>UoHs2WpKjs1+jGocLLfmg~D> z?g!izTpL`ioqL=E97i2K`?vNC+hyBAo7uX`TG_JB($u`o+|slM^8XJS2OB;$Bqv-= zn3rH65B~EYzrzzf2?jV?NB@&Vnxp$ql65oZ=fLKXX7Zv5qU`UMzXolVLlcuWRVM_K zO}cy&wApNtF@NrV`)nTG&xo42QJ)zl%kKt)CU+Y1a|IG8J&*QIC|N!Y02=bMl?kyQ zjpgQhmN(Da3I~FUrUq+>Q~<4g9LrTD*qWMkqs(-gyCltm_72DL!JlAz^ygRCmfYzO zE=hsn1c6<#Gz3~b6!TVR`n;(*GlOq&&dK%V`aEeV$yvekT5$g(HHF{$#+d9RGiPR& zGpFfkd)WbKu6j(iTv3`+Mou;x4k6261$9)7$uU6FB>g#6|Ha&t)RYYP#AoEe_9*z9 zE?Wp~SB{C#rku9b$r7ztK3R4jG^$Vls?1U7nGfo*3{l zWUHQI-#lMpuIhJKRvlWk#^fnTO{+=X9Pe~5Yy#9)vvaai(vv;j9FWsxmSa%Fs_F|KmPky~&KS~tXGXA%t%f31(%edPwE$F z`BF?y6XAUho5mrR;wRAJh5zXw5HOsJ<<2VF4Ls(&_7JppMnHREd%4gf$XU={X-u{o z+LJb2FO<=wzOVx|Iibmu0v^MQn6A0m-ejLADK{-p*9uAtLc1pfcuB&iY_PEk(AZZ3 z>>4pkQ__=s^8!su7oo{7V)E6|{*+Q3P+{0WOo#&mM9ZR7aeJfj*^)+in%UJUk(-k=7FEt!9G}h0Hd-2rkZVwdAx-uf8T4wyIb)d#BN^EQEGy_Akw*!(Bm9@M zRLSo|NqZ&m`Idyz6%h20auw>(b*@7BG(`(xX>J0*aao$xoCoB6_a#;G4ZJjiH86~h#_<{* zQ4=Q+`t6TY$%mhRl!b>9w~YW^REb+$Hv-Y`&=h?09CE&Sj?a0o=4D106b*$BieQwU zrf?wV8%jOPH?C99a`h6{t}yEw0I%3t7vyDvtqAFHrb<5Z#;IY<_2a~>$w)!gmp7=A&)in?Xe3-!t_RFwuPO%zhT@q-$o;2P z$%j2$g*7m2gz5sU*o{ySR+AfpsQZqol8?NYt?3T={|U>DwTb(8_a*l^_i6W6?oZtx zy5Dxc>fYym!TpT;3HKvV6YxRE3GllYx^vuV?iuc>?uqVE?ji1e?(Xgm@IGK;cU^Z4 zcO|#oZE*eR`qg#O^_}Zm*XOPyu0!x%;LENO*G|_{uE$&tyH>lFxt6#VyXLuOxf0>^ zz;UkOu7R%Jt}d>&uI8==uA5xdTyB@emEgPzuL+)qDuiDz^HyhnXAfsbXDeqDcx~`TXJx0uX>|PMxZ?QH zan?T6KEU47-pStD-qc>-UK3u{bJ|U|zu{)XPqy!Er)*!^j@mx3y=8mFw%7JNyh^y) zw!v0pTVcE3mTy~N%eJN3e6~Am6Ko@GgW;9JZnpL|kFAldj;*?_qRnR0TmP_Lw*Fu} zV?6<{7Jh7f&-#Y-CF^eMv(~NFP1beRhpYwG`>c0a=fW$7Dc0%MN!GE}Vb)u$y{w(B zZLH0#H(P62t6E)Fvz1tWw_LKEvz)ekW%<li!BdY9?Go6ObB zZnMRl0IwweY&vf$HGOS5W;$$o$Ml-%Mbp1b+f7?ckDAuNtBI279@CwsTvNI!*)+{` zn`yM^R#Sgd4^u}|D|kh*p6NzYWs}2XH2!70V*Jr~)_BtRh4B;P`^GonRmDBV=ZsGq zA2+Ty78;iumm2Rj&NpTmXB(4@Q{a`w5ynBrKE|%bcE%RQhQ`{Cla4POpE%xkyy-Xq zZ%97pc-rx}W4)u$vD~rLakpc>Bg-+{k>r@-7!PkO4s!Hybak|Iv~VdMziWTpzTdvfzQg{ceWQJ?eU)9d-wSUr=GimsGwojc?e;OQ zImR1|6^vG+&TtLh!MI>3GkjzC%s|+%{{kRCKVP+U+ z8oY+v4Py*L4Fe244V?_F4NVR8;VsB21}9X~_*?%QgqZY1PYMpAcmu`jC|*PHDvDQ796<3hikDFANAV(xeJJ*#*n^@3#cmY4 zQ2YzU3n-pP@f?bsD4s>J1I2a}&!E_b;%O95q1cMzNfcX9Jb_{}ipNnrhGG+njVK;P z@d%0yDAuER7{xjiYf-F0QH-JpMInmSC>}zw3dKqk529FsVmXS@C`O?eiDCqb;V6co z7>eRn6hlx9MllG*Koqy27=WTbihd~iqUeL7H;P^;dZOroqC1LiD7vEPf}%5uPAEE} z=zyX6pE85zD02Y#WyIvM)4JjFHwAf;&T+o zQGABt7>Z9(97XX7iX$jKM)47f!zeyP@d1kWQ5-_?9*TESyo2Ix6mOw;6U9LkZ=iS` z#cL>DMez!X11Mfb@e+#tC|*Rd55-;-dr*|1*o|TrihrSa0mbtuoadP;5f65yhh@9zn4I#d;JEqgaPxEs8ZLicu7y zC`7Ru#X~4op;(FHK@=-cEJv{nMF9#Kg@ob(6!)W8ied?h`%v7A;vN)!6!|FbMzI*h zT__fzxD&-f6bn$yM==k@ToidIa#7@<$VQQcVh)PTpeVqu6kt~huqy@Fl>+Qa0d}PT zyHbE%DZs82U{?yTD+Sn<0_;iwcBKHjQh;44z^)WvR|>Ez1=y7W>`DQ4r2xB9fL$rT zt`uNb3a~2$*p&jMD;e0MbQEbQQc=uCF$+ZsikT>qQOrQ$Ly?3c5yf;AUKG<%Ohs`A ziYX{2qnL!^b`-avn22Hmit#AMp%{x|Oi;+!6&brCV^?JCii};6u`4omMaHhk*cBPO zB4bx%?23$Ck+CZ>c16an$k-JbyCP#(WbBHJU6HXXGImAAuE^LG8M`85S7hvptaN2G z_GlD}ktjx>7>;5XilHcOMKJ`$U=)K;3`B7YiUBD4qv(gCFN!`WdZXxtq9=+TD7vHQ zhN3HqE+{$&MS(KkJK?|Vh@u0E_9)t+Xp5o^iqXo{iu3*5zDda|EcYkpYz|M}>IKiCQsH5fVB((e4N&F5Z)@C~ZIi=m9198hK#SUo8 zRi3$mM$ zmlJZGv7;83LtB5N*!&y5&5J%{^H^-Q)uc|s7UHhrdcxIASKs-pvz_B5#~@pE>lSMV z%K^)H^J#O6={M67lhe4#*v|02VUqr${!YC^x50kgKH2uI`+vBaT}C0n6e7PClN+Mt4J6!r2Ce$4kXzj9 zHj!;YjxensfuQCg+G2O=L3`U@%zGHwGRzbtgep|lwF#82dxT#d-Em@VT%=N-K< z6X6FX@<%bLu2kMEP@86sFzk>y9FM(InrDUw3yOXilRMMp^;I)o)Pow4_s3)QhxtZ` z{9-(&MmZnKeL~MyikSm#vmOZ|?}d=BLFhzMn`TBc{hj~6DAX?WmsJ;wh+p<&jQ^Js z_Xt<9^Q5z-V}X4S+io!q;X*_g5d=N>~ z0lNQ3<_0;ct93c`q%i_`&+Wu@U0vR*aE+m+9ic8 z>aeHYB1EpYh>!f$RTdeB`IvYP^Qeak1h4alD)}97u3|d?!+dl+hk5wP1et4hQzf7M zbD#m+lf+xPGnj|Bc);prJFKXWt-UubG7 zzd+4y+#VDy&_vqdYdQjY5Vxa9R)*Vv^>KJ!3Lh8i#rk0-MlokG^??NrHUUU`rm zDX^~{2F&93wc#Nygsrw&m3-(bU07&%ByuP~$L^8H@;2j9;$+BMwVEpV+|O5Kxgovy zR^S$&UL53ROBU>@+y{Xx_u&Iy{fz;J`~MLCKSkWj-8aDf{1(oaoVPkYcg%uY(o5`B zY+G#ItRGsZS$?(5x9H9HnJb!#Otl~npta!zLpS{%eRtjKx`_#=64J=;N7y%3Qqp{3#y%tXtEBWe?5k83pIJOTBO}%4O%LmGX-poK2{$-AE)$9Y%<%-D=8#W| z3BxiirKG3iqFPj5cx|XU+S=4 zQb!1pzYsHQv|dLhkU`|n#Vjt`7S$L8k&nlvIVF5Rq@ ze;|(?i=&D*8hLN{+8Wg8*F{hav0+Oqf8GQj~ixS3hc(<#j5204n0n@-GEBf>ClbX73II)sP}|H?QbS;IHc*QT zEJjdAI&YA>-yv1<`A42$`MdgyX90gk{N`?i2MDqICaRK;e|86p59UvaulXb0NXXq= z$z$lv&tq6QyE@C?-d{Wu_!Hx2e#RGt;JsF*3576Vd+DCJ(A$hmSs^s_J{^e{B z;6;`s=t1mWWC{P+vaTic&mm@)Q>x_R7B_r~#f40OM8Fl8y}&q(7$+aHcAlt8K6Be2 zSY`-LPX}g!!D*IR@f0FxM|{O%Pe<-67M+W`?`MJG*x?0WamNmJOepR~>plhY`TW2#z7Suzx+9q2cx16=K zF)uW|Z?YRl8kXrl(O1!pODH5q;(6Hrx7y0@;a_8gUm+fAq2hNef9E^Lk3Y&BKlevj z`PVd`Pl_8t9e^w5QP>>-sdL~&21m=Hb1#7E!s3X2Zw zrVh~KxNerehfH3IJxE^4@4+IC&!ee-O#<{lTqQnw_73FVg`AW#>LBfmI(*ua*I9eF z@vk938xQ|RFk3K~RpJX2KtS3gr95pCzdY^AA*)$x$jn>})Z#KTwKn#sOAF;r9EJRe zqxjbDFo)#^=lfm29S`Sw(AsobQgSbr#oXgv#wUL=izNq_z#<@z$8sJd4+RY<_*CT@ z%vAn0n3cD`!GgovU3UU_?B4DQKhn{mg4J1YT->4fFYZ{yxAMI0EG+EZ7Xqxfy}Jh1 zqo#Nv@|32kYWYSOE%*XzsgvEw4^jyFe zcZR0e7%vU+PN;`wo=}g^`>CctHw@~$I1OqgzN?*zkh&#fSRtSUEQ6ZIHx(zIp#Uc_DAgX;59st zb+5Ijum=_AuPH}*X&F6<@h{#-mDbw^wePfT0u1-dGQf#`sVo(a|0AGEl5FCA-Pu(jVAdrQ#0nP z7Y_=m2uanWt%gGOq@c3kUsCa#YktW}Lb?}aStIflAz5YNO@%fGd)-vf{%e1qnhvgW860QxkMQk^(}v{!le5HDh*m z>zIBbf_^M@@CMviME+aIt|qLHbo5}Oe+izZk^VX&|CwwAms_mMAk&VbtBuHi2)VVQ zX@}VeUlTk;!yH^hzAAW#M);eno28NC@)MLI< zael4jJHHCOO<8AM2mhLz09;&QvcB1T7Djp85NMg3 z4j1xi`Oy1~*n#_v{0=N0%XXl-f6Wch0dbyx+JP|7|B?da1yA$c#=<(vM`6+GCI!Z{ zz!mh>1N$5=o7cJU{k1GFtlHIpSDX($oHue}-q#qx?`zBl->Zpp!m3>rz~ixME1vAg zxp~k3Bk#Qfqbj=p9y*qPv!}$E(@6JAN@t@-XpJzUE_T0HM=bU?H z9g@#k$0xthnKe07t5gPZan&keCNJml^w|;JXXm4DfJ2~vGqY&yqJkEM;N6v?`8j zb`E!(bxgAVVt>SbyRFpL(7MIi*K*pDXEB&d%#BTNn1&k98?z0+8+-=0u5ZlA7%%yW zJoF!({*{oJkZ^9A*OQT-7HGpixxicCO~_22kc%D6{6Rpey^tVa_^8k&9r~qa1=`n0 z?SzD`!Uy%FV;dl;t&mFRzRChW=p8~*v|;m1_U7iNr=}-ELJKF`Qb>R|Y}~+B z4o6JPFcyxAcrt()F{dCYA+I1QVAd9*7rInf;=Cyd6SI?Wb_qffWX$YR5^!eCMbC_J zm4GRm30d8knI(IY)36Y(sgS--%ut@J{PZd5xdr%}H4&1Yg13B5+T@HxcI-@Ig$$XO<4wjlpTGV#@Q~CK^6m>6H@5)RnoQ+w zTUYS25}x`aQXL`NnUGo1Ck0JgTgZ}12URluQY|5GLCrWpXASsFO~F3n&%v{ybRyLd z{6P9gq(5I^lGOz-blM@=!Q{pvC2L!k~lC0C)rvzp3PN-sI=OOzx*Tgo(`(y!+)ts z?Lb9ABEXBQC<&Uy)? za}t19Tsns#)*h0PcIO&Z@~Nk2F0+Bp>6-(!xXIIT9LQ2b%B(3+i%Xd?HdfF4Xx*)sRLSREFqP#^^et@yyyE&^F}!Tx z09iLHd8W;rJQEa_EcoqbmKkc(8UwSq+B7vPphh1M_LW|$hfrae z5C(E?T&PMu@AHE~c;kig2KPpZ!8izVZg^LfT;9dso?&^R4x=IPMx)9oJeY#O>y@j; z)>q|%KV#4|)rD$?H~^1Et&Re&IjA7|TBUMvt%r-g_@B>Nn?t5L7SP3IszZH*Ib#LG zIyiwf-Bih+z*)_O#qcI<022`RCZrQkVnayzf>KBad4Fyp-K#0Ax#1L0A85s$0<^Tj zGdtamu8KweRk3{TbWLXn*h|*~ZgG3*5bm%j6+%BdO_hB3tL<5%!(O^Bz>C{UhrlzT zF2r5%m@4_$&#hpv@%-;0?t!kSogX`EI8y8zY&UGZ;QarkrGvTHbk@|!m}Phs&j0;% z3t~>h)FGb#{P++5Wg+~i1BL#m5bncdd!kawl$xBGkdvD|B|XLKzl8^_a`7%za;>xE zyr!TD_U!`zUfjMt3_kF&Uy%CiV@Un=F)sDeHkX*+6uRFp?GM!A%9_HcJvmu<;WqyY z%6$LnYTWr%KQ8@}4a-@22pRPQdT}A6jO=7jhBq+~zRmDtO(=jXjp)*K{!N5F|0WlD zK|9UM862grP)A{*lM8Zly;;fW4D}bik@^dMqre4Sz6mjPpQxESIU9oWxh(YO`w{x{ z{d`l`+QCA%_bu%W(Bdvv*O*#`P6%ArLfzzScVs`?ozH$-f0i9KpS^%x+~%`82$9W7`=(+u5$42p3(E~Y{=qdd9(7Vxj$2S@qgBbZ|>L}*4)i~OM3vdxQ54C zbEhy5U!GW>>(CN^mnT zKRXxi^Fz`P$E%W0e8|NT!*Qbv5Q{r*Fa}nL69Rr5wDj@C$bEbYMVluw$)qrV_ZMGzH* dvDXz2sWzdcyUPYm(~$*AUm8u0&To*KIDH^B3pW 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%0DQkBKcY~HmEh|njL%30zJ}zFT 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

7n%g%7tatsT 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

  • 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 Q%?A~a-f_NJtn!%u2j4utrT_o{ literal 0 HcmV?d00001 diff --git a/.aider.tags.cache.v4/d7/41/5f8dde2b6955c58d88f39cdb650d.val b/.aider.tags.cache.v4/d7/41/5f8dde2b6955c58d88f39cdb650d.val new file mode 100644 index 0000000000000000000000000000000000000000..d45c92e4edd2e69db33cc1f232496ba9eede1f62 GIT binary patch literal 45747 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 - if ($validator->isValid($host)) { - return true; - } + $validator = new Hostname($this->hostnames); + if ($validator->isValid($host)) { + return true; + } } return false; From 3c2b88dc86eef2859f0d563481626c47f75e8eb2 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 14 Apr 2025 13:02:02 +0100 Subject: [PATCH 014/343] chore: remove unused --- .../46/d0/0f82b9649c970f7aeaffd81272d8.val | Bin 55096 -> 0 bytes .../a5/d9/b57b6547e797b53635ad0d3c93e2.val | Bin 78981 -> 0 bytes .../ab/37/ab16032a4cf3218215f82e6b33d8.val | Bin 38416 -> 0 bytes .../c4/0c/131572298f4b919688b848f0d865.val | Bin 47855 -> 0 bytes .aider.tags.cache.v4/cache.db | Bin 14454784 -> 0 bytes .../cf/bc/6e633cea90c4e72d07887e4a655b.val | Bin 77806 -> 0 bytes .../d7/41/5f8dde2b6955c58d88f39cdb650d.val | Bin 45747 -> 0 bytes .../d9/2e/bde17980e9b4fef0f06922d7a9cb.val | Bin 48781 -> 0 bytes 8 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .aider.tags.cache.v4/46/d0/0f82b9649c970f7aeaffd81272d8.val delete mode 100644 .aider.tags.cache.v4/a5/d9/b57b6547e797b53635ad0d3c93e2.val delete mode 100644 .aider.tags.cache.v4/ab/37/ab16032a4cf3218215f82e6b33d8.val delete mode 100644 .aider.tags.cache.v4/c4/0c/131572298f4b919688b848f0d865.val delete mode 100644 .aider.tags.cache.v4/cache.db delete mode 100644 .aider.tags.cache.v4/cf/bc/6e633cea90c4e72d07887e4a655b.val delete mode 100644 .aider.tags.cache.v4/d7/41/5f8dde2b6955c58d88f39cdb650d.val delete mode 100644 .aider.tags.cache.v4/d9/2e/bde17980e9b4fef0f06922d7a9cb.val diff --git a/.aider.tags.cache.v4/46/d0/0f82b9649c970f7aeaffd81272d8.val b/.aider.tags.cache.v4/46/d0/0f82b9649c970f7aeaffd81272d8.val deleted file mode 100644 index 504e479e2e2c63b9c47faea63c10f3d5d42104de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55096 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 diff --git a/.aider.tags.cache.v4/a5/d9/b57b6547e797b53635ad0d3c93e2.val b/.aider.tags.cache.v4/a5/d9/b57b6547e797b53635ad0d3c93e2.val deleted file mode 100644 index 4d93f55dc9c89af6518217aa70e6f48f134d803f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78981 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 diff --git a/.aider.tags.cache.v4/c4/0c/131572298f4b919688b848f0d865.val b/.aider.tags.cache.v4/c4/0c/131572298f4b919688b848f0d865.val deleted file mode 100644 index 7b8ef30857218e262d9386592e86739021d1d3a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47855 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 diff --git a/.aider.tags.cache.v4/cache.db b/.aider.tags.cache.v4/cache.db deleted file mode 100644 index 77c657782e5738664f7e16a6179727691164f4c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14454784 zcmeFa2Xxd%7dEUdTJ5f+UApO*7OFA5cQDoTUd`HG+l$K@H+ormG2QeUdJnz#-a7=6 zP?A6bBq5}S67t=d*_E^#TNpg=_nrUz_#8hPU9Ijsx-*)lJ2Ra+1Ur)K{t?cESX+{R z6($>_)iMqJ{TYVQGmLl+j-Ed=1VD!WjDQ+ z7sG|k{GWUsb25lO{(ZE-M+ZpSZ#~}Y``(U_O3`vUB@egX-)YZgHs0XD>JvlzymKo~gcW&x#URk4F z&cAI?H$puVPf^pPmH>{pM0-NgyAy!?&ixcE+ja`-*g1;{pm>Um5}>M)D^LUSPD$Sc z2y-UKC1ob_D1S&d_f+!EHaH@8zNyNo($0j*3GM%d%`>Lm*{vO||3e-ZCe~9pHEJ9jJG9=O9#IweQ%nO{0!I{96b0D31%1 z#=-3xW4)fAl=qhn;}4}>aCv{l6S*a}urPaKA~w3W1m_8lDkuY+HR=-F*}r0W|0G+a zKZy&MW*$C@U&K1Y?djba;fS%v*<$VforAh}F7GZFk*YGCH3q*zg*3yl9XzF|=cx0t zhDYjO8b38s<=?g){C5cs_9y0dt1c6$HTX3tq+xKHB@T#zK7EKSImwC7Lp+K?DtSVv zACLO*q!W*O^63G~FuMC*z?^_n4DyBdKV^(a3j(Y~MS%`}R}B9Sg-T$+3{a?yN5Q+a zpgVAsm_3J15&Y*7kkXpSHnkAcMo>ro9lBZ{$r@l8I&I>)%A7!_&7=#>(C?ZfXn~+5 zf>sDxBM8PnM$iSFwnNY!K?ejK5ph5Cr`s z1^9PiNEVL3j_!>{p-2Q#2prOnqou2{=t3Mi9UxtmLy72W61qANUzL6`$a9)us-|}# z6PY2s+td>t-yv(3e=Mi|2P#$M94TMP>J?W}hI_|_lb)ZD-$|z=$4aL@SLIXTD^P$z z@mLw%#-wvWworOk<%n>|=QQIxuwBxL%|`(_#jm9Fd(P-#aqN zUbeWVlvgs!r*a6#flp8Y2m;t(;r6uHmU3?G4*{k?C?P@jAuJ_Y+In~yN zbd%NNt61g}@;Q}%l8Fnl`V4Qw#PL<1B$MxuLq1Vr^%-8x%7yfZr>9RgdwN%W=*p+* zsh6+%gnUl5b3E@Gxgee53$o_)u40*jv-iFDs?Tjcr^MpYZ9Z2q1K(tneymO$tCHEv zKbAvsZ0S9MeAOo;pQfi?zUmY5IZclS{z)cGLVhPz{<13VPu^)Moyr#!oYT2VNM_*z zVUHB}rkkWxW-qgnLz!TZ-XmnV7P9IrPc6GF_bitz$Dw@w z`1jEQA1(0F0v|2#(E=YW@X-PvE%4C-A1(0F0v|2#(E|T>Ex?O9KOO#R&&+vg%BIU_ zjCCX?+7mgeF1Intk(3B@IAfy2Y|-V`p-=bhKhN?Cx@wwmM`CnHydx|+#vT%%;7oFc zIb+zoysnZCUx{_Zg`h9@*n^50#pE{YDw*70(-Q~Bg+(PeF(Jr9V4y7~52p*%x-W$x#|M0qKa<-aM}a=rhosoTl9OXC ztgfggEIB47B*qczNHS;F>x$~plaTX<5Lqdmu3Qa!iX$w^;fxE3cg8rv2FKWKiAezo z_Aq-~Qq150>=Y3$Xmv%5;K~q!odHCRuBb6F$(H0uOmc)JBB%armS>EWvu?MRwPv?o zwftduW_fEpW?f_*XN|RXw>Gl=YJCJh`}p_K0v|2#(E=YW@X-PvE%4C-A1(0F0v|2# z(E=YW@X-SQAFzN~mrp~639=b=xix5*z={H>S8Xxr{4{t#LCl-MFoBRqSBZ=tc#RV9 zNc`U+0&^~1fJZD15t#gRRXjrF@PIM5F3=;F#|AisX2r;W!QwSCz@k%mU_hT!S5D(I zD4-K{MKn_XUn}a0n&kdJ_zf_6>tjH%iS?EBH|vkq$JXzyUt7Pl-m+e?p0l2?9j{!UAEoFjbf! zxP+lXvfvaPLYUA;=q7X!S_?r!1EH2sMF+E=o1G3Mdsf#w0`XtUiMV(ww?WNu?_Zf<0*W3FZnG?y_KHy1MdnX{XDGi&Pq`k1qNW0-+$O8ZWYQV`G5%%z#rT8qvGIZNuJMNPlJSi3nDKyd zm+>>>dgDst65~AMOyd;eIO9m;U}K^&));BD8G9MK7~2_J8k-pF8EY6T8Os?<8jBe7 z8FLy%BWKibuem?CpSh>px7TuP#K&}i|oGZlnaoIVZV-5crUK)Ng{ABpv@U`Jf!!5%V z!#TqV!y&^S!#2Z4!)n7a!ve!>!&JirgUc|~kZf=o9ELDMA44}o2SaN^kfDL0mZ6Fv zz);Fi)KI{X+h8@A3_A87_AmAq_6PPc`+&X6-e51WXV_!x0d^Pr8M~fc$u42%u`}5z z>^OELJD5#mW7$a7#`a>nua`cL(X^mFvn^^^2t^uzT7^#kVE-$UO?-$vhD z-$-9aUrisVFQYH6FQoU=XV>$oFj3))+f4!Q+^zt4`?eq8t=lj!NO%2KG~m@+T>!7# zstHE@z@s-sz#}&X0v@_y13Yje7;xW> z>VSK0_yg{`0ppOmo!659w_ooIxb=Dqz%AD+18%xr5OBkF1K|2=@qlZt^#ojXEeLSs zwLrk-*YW`_y9N_dbW5(r0xr7R4RGPrMu79LmIIu7H8)_|m63q6t~dZ^T+cWwg8T}gq~>FCGm;sRsxK24zX=}4zUeB zhuF3{I|#7(*-*fsv&jBU&LaCaK8x(%@GP=_{WHk^b_5aSGYL*ePUx|5M2Rg-;^; z7dnZasK80|MEOplC-OUqo+$T8^h7yNpeM?40zHxS1bQOz1bQOj1bQO#3G_t9 zm!rJ_e?Hm_@cGe-fX|NR2Yhl=5BU9&IKan8;EA-~9)Ty)esct#Nc->zJdyVPVR$0# zy~B{Bv|k>E9HqT`xE|o=hv6O3-Z~8Li1x-Ict^C?4}}9>J=7NP@}Zi57Y`K!Jby?4 zJbN$&@XWz}fF}>O0z7`OD&Vn$g#nKoL~IWoKx_{lKy3FP0Q+nA9sv7m_Z$HGYj+(0 z`)jxF2m5Qc?MG}s+mG08-jCRB+K=j|;HICrlIID5}Pz?pk&fHU^A2AsO58sL;YMF1!7fgGisxEpem zcEWDRQQC34AxCM)?1mhrb?q()IC8fEaQLoxz+t<30uJ8Q6ma0K3VjrM(pSa7`~$}VCard0Bt+a6NPL?Ptcl z5!+^45!)tP5!*&v5!;4awSe_Miw3OwSr@=MpEUri@mU$bYM-E4^^Y?mStNC+1u+{vrZV=#a>p}s4 zSqEi{=Eb_|fIqGC2mE0jUI`d0TT}CFE_*{*{oo zHG5YU1Khn5a)M^p3djkX9V_|)Zd=g`aO(=l37X9-ASY-xu7I4N+3@KAz;&PY0$lSc zyos9CpCYy^K1FPoe+v0lvuru!Tg{T?i0#7Vi0y*qi0!=Pi0zzZh;7=kNWfXkIsndC zRtIqUvXX#PmstTPFC7dxacLOf_@!+C$1be_IA&>4K-W?paO9F?z~M_E-)e>~fqbhO zyacfwv;?tDUV_*rE=Ft<79+OtixJzn#fWX}V#GFjF=FdjgxE$cf^tI>v8WMX_@Z)v zp^FgPehU%Xz6+6U`z%DZ?X?izGEI+#p8$4Sm<_PYf+2vN7K8(KT!7fNTY%WMU4YmI zFF!4i_bx}Ej9<));|r| zws0DWoL&@asln0s~-V9wcn0dvf54w!9rB|yvU0)WD77SKG)322(t z1JE$537~#f0HAJ`AE0KIhGCe0XGR0Qo!JHO%}gj0m{&8)0KS}=6Y#GY!vX)80c@Gy zW&m5}ml?p8`FRGgWuDIfw#<*y;VomHP7eiqG9BJB=DX?D0Uu5G2mE$Auw@=j1Gdcl zX~34bHx1r0=F4fombp6(*fMvf0bAzwRA9^8oC<828&iQTb8RZHWiC$zw#=oei0y?` z#P(b&VtY0fu|1uN*d9xTGJ!cd1yPTLW<n%u`nTc+DTwrX7wb*cI70*cEuz;;PQ!a zfJ-NK2V63-G2o(!UMMvsLY$b^nXcIYw|@;uXQEPCE1V?zKNjYX+Ye{65SdSjtXV``4=23UP;Gr($N zk;{%~r*~#?K6lr{B9Bwo~ud1|Rr=byhj_sy@tas{O z>t^fxw5zl=G{-e8mj^`yev- zJJ_FfbuwuKyTCFjiGeZB=){U~fr$xWfwuVgfeEmHfgA{Th9w5t2iaodW9*566)RM# zSYc2g+?HZb2#9tj#W>;u``c1%fslOs^C7HjfJyiMYAaQ!E^Cb+oD}7ZljDT7BhbPq zfn>>zojWI#F)@fOpW#tl_oEKRXGEB$C_lf#X`x2o-)=R8w$l(lp`KJXMbp=7$;GQF*3mxA2lFG&O^wj3tq-R zl8^z&T@7Ni{{k@vCbBO3hd*PwZzSZ*{`RmWsqjgRO$0=^20N(BFg_5*OQOj#XK4&PeuvaV+X`p5(>O_A7)+@r)tJU#cX_n zJpx76Wh%oM&d0E>ZXXs|W!a`)r4KBsW(&1}n@Q zw!fm`myBDA=v8qiYRz5{SC44c)#bzDswu~nehzY{sprkC@)oUt{o(P|kmK`uGZhUH z8?-0`QXC1m*a=((jr0{CZc9aj*1L{|#xhioi8$Lt#MmMskCub}i>~E|KU*b5JImeh za38!Pvw_1hZn>7K1*1zpWidW?nQDs*PjEWI-JJl%vpM1%Ne&xs(-r#(;+q2v<&Y1{ zE0q+@0B>W;4IY#=!|m}g&cU(JMggN1J_?c6&O%2=QCWHA81gFkR#W*?pfmUFhgOZy zufp|IdJS{(zPp=OUe$3P=!I%hZLF)&2ijFpU3upl5+`ZHg3EL!nz@wxa& z{6f4co)!;^+r@R_QZY@OERGUW#27JD>@Kzyn~Jr?iegDIzi1Wp@Kye~@U3u1xFj5h zZ}FRiPldUbrj`bl+LmgTir^XWiKVEepvBLU1AGIF7M=K3d@248-T}|V$KpfrOYt`N z2V4}-h{wf4;$H9&*dneMSBcBSh2SGFL!2Uxhq#A`Nn)HB1@ZS5yNd0_R=}aYSW~Pl zmKQ$}{eej?(IOf}t?)+pQ+Odf6CMfofzx&2qHtO`D(n|_3R{GA!U|!rFjtr%Ocurp zBZNUhf)FD_2>pbfLT90^&_ZY|)D@}=6@{`w38Ao%SI8j&JYd6jvodA@m; zIn_MgJjy)8oMetON0~#-z0FIprOpQ%-P1Q{mO=V3bOodH(O*u@0$zWoPuZ+JNpBtYTzcGGgyluQ{Ja0T{JZ#)+ z+-}@tTw`2rTxd))PBTt4jy4W6rWoUm{f*(qzQ*pxj>cePGh;(zZDUnq1!HMrF=Ihv z9%DA6*{J8D-yk<%L982&W8Fg!CnGTb-ZF5A;Qql(9_V_(ALnx(AZGdP~A|` zP}WewP}q>yki#Gt3a&uwSva*{ke%_9T0l-OFxgH?eEjjh)6$ zWJj~Z*c3LN?azj@ecA48M>d#k#x`VYvsKv&Y-zR_TaeAeW@F8)UjJ7AxBgfCkNWTQ z5A|Q@Z|X1W&+3os59)X8x9T_OSLv7P=j&(bQ}yHZqx3`cN%}Z_ls;77Ti;dRUf)XJ zR9|0TQ(swMUjGTJgKa^q7-41-ghh-3MjoRXqY0xCBZtv|k;SOTsKcnmsKLk})clL_ zEyjN^zQOn!<136WG5(G5FN}X;`~&0f7=Od~E5=_izQFi1#^)G+!uTV`A22?{_!Q$4 zjNfDY4&!5tk1&3V@f(a^V|LP;#+?{oBgxxCY~DjH@uN z#JB?Erx=%GT!wKe#w8dRV_bxBA;tw5=VP3QaW2L=7}GG$#yAV(OpG%yPRBS6<5Y~P z7^h&IjBygii5Mqf9FK7v#<3X3U>uFng>e+dkr+o{9FB1q#-SL8U>uBb5XONRQ!plD zOv0FmF#+QMjPV$q7~?R;VvNBUjj=yQ2gWFjkr*Q|+A)S>48s_T(T1@f#t@8sG4{dO z8)GkwJu&vc*d1dxj9oEy!PpsNCyX62cEH#kV>^s(F}A@NjIlMwRv24iY=N;k#%36U zFgC^51Y={2jW9OE*Z^aFjP)?q#aIVpZH%=r*2Gu?V|9$xFjmD_1!HB5l`vMs7>Ka~ z#sG}vF_yzv7GoKVr7@Pm_zA|67)xL*jA7eg@c`^E7 z%!4sE##|V4V$6XtJH~7ntr#sBMT`PQ9-|qf38N7shtYtM#i+-q!>Glm!N?$F{>Atf z<3AYRV0?}76~>ns|Hk+i#y>Isf$?{YzhV3p<1ZLrVEh^5bBsS>{1M|17@uK$it!1? z?=gOd@iE3n7{A5%4aToAKE(I{<9&?xFn)#cON?J&yo>P;#?LX{#&`?kO^i1%UdMP1 z<5i4TFkZ%Z3FAeK7cid3cn;%PjAt;O#&`;hL<57%9FdoKu2;)JF2Qco( zxDVrAjC(Nd#<&aPPK-M+ZpXL{<5rBHVcddoGsaCAH)7m?aXrR$&<&bp(190M8hp67}MWHzO7;CDFLNS*i zgx}9-5r+41UUmdS2&Z`D6bP+Bzq6l*&`1l^7 zeBK8>CUZC+^lA#BrRaA(#z1Hg3UxaUp-w2&6+Sm}0VveDA%yUI-4VVc8*uJ#e;7hI zr?mYCLi5n?+SG+m0t&T;kJ^S{6l%F2Lbx<*{t`m?oo`kXMkew5(G)(tvp6p`-VLFd z=#GYeKqwZ48bCTg`xZj=z*zuVw-Bnc9fslFpinL7r0en9RI?(4aGtB~gwQl}wdxiK zIZ&uF4F2ewqEIFHw5P}AWneT6c;QkdU;~8kTUYKWgm6ABTN*+*WlBdvC>-7U$r=bX zK%o+kA(R(|ikE;9p5IWYD2$?O@q1Zh1%z-;E(F<3I~rXr=ntX3D3m`0LN!q+?@|cm zM4>$QV0hy>3gw2+avJ;==Y+vc%}ON8z7RqqP{?{0LO6Xbc_CC4$pmmJ(BSkn&xLM0 zPG93K2;q00%LSo@=yxn~kHB~6Wv`*5==Y~tM_c2q zeWAZ!+gjS1$Et^Z{zJ=U%R$Qq=--dGBw0c&?V(>^-jd&96#s<&{B`jt^s5&`KYoxH zA$ArUL;t<7C8k#DY3YyHuzm4A+ZyJvqw;GokQ;kE6QO2&urpC%ff1`za!#(5faHqMQ z+zM_6H-d}ddU7qe>Rbsf2gewm8@@7}H|#a6F{Bwr8{!Rp4Z()mhSG*S20i;L`;fg1 zUfb)~InW1lvc1`sY<0Fcn@#_Z{uy{+pVV)I{?ruxAn>#9sBZwhrhIyX?l;{-=r2Au zJcNGYNyBdFA1*YcLccKH5DNXlW`>&34=iY~K>zPo_7U{^&a(TVzqgc~0dXX;5zxPD z#ny#>oj;oc`g4EkpFltEqW&=S-&W|;px-t~-yiyGZS@VIpH@PjM{m@<(*3Brue+){ zuG^_wqnodrtQ)3_)AiGJ)HT&r*Ok`g*9qW{@k0BJ_NMld zMN%4av9GXKbDH|{WR0e0Dh(^Ot;f@gDQ1e0E_i^M`zPei`$-e0FXT^P7Bjb~5v;e0F96 z^NW0Tx&iY-K08%~`B^?YS&VrupPdkypX9S+Zbo5ayGvg|Vno6Q0@jo!rp>hx^Nuooamtv-u1yK=6bkL?{ zra>_#h>~dkUwxUWW1$XyBZ>Acb~35kK=f1+?XB2_nQ|XQpG%_MlNvHpco3bIM7zY& z%w(u<_??ny$DCQrB=Dl*S4g7mC7&}Bp=9J|NTRKCqL>LsKr})UZMn@c<9`HEtR&jp z{TVYpABcKNqK%LHG2@znsFftz;JnX_g({4%E{WDn31-GD2T@5$wB}&~Gx`#Ua!R7r z0}e5+S0K_zqE-2SWL)6kX8u_ctvEiA83k<(^B0~Rz<%0j&&a_bIV(w)ovtuqK1g;; zlBLZJ!}ow>r6gIrvFNbdAek;n76r5!3iYvhm?T+nCjU^VSIkk8WPXp8L#lwJt0bAb zZR_BUAZaW~=9GO2Ig2p|N|M>?BuT1r-d+GCaw;cWFBo1MBtxa&3e+P-2%8^}`_00(_OsPa> z?ayZQsSJ|GlAiF0$le`5a$S;yzHQzs9wbL3iEXfdPiQ}Ln<+IOH$js0ezvk3ywhBwBuB^FNR~>HstKPo$^nuolBA01WW!1z87xUEE&8cJdyqs*l8Plt)`$KB+ewmCSbU=1 zG>|luBmtGgx|=~Fmt*CQzNm8%Bn744lnp&l`v;JiBuVKf&1##W?;*7$*iwCG)hYuL zxg0C`xN=SCx9P7*ca<2kzXtR_^l}a_UaEBU@gR|Nc+p*XtE~pfLg_C5)}d8Tf<(^Y zg`b?N@-0YGq~8=u?N5yso__T!ECGqsUSxCK+ZAvSdQ4JFiOtz*U->UV@{M#?_J^0tK`p1dBuTP` z<}3%*s&2m|v3&nqS*XW#>m-TTgewCL2i+V=!r%5Q4J{SjXh~vDTvcigNSu*G>ED*Q=|2@DcO=Q1)2oVX0*REv^{=C<7QO%ysSMY@yw|kQGmuDS zxc={fMGKigGELI+=gZjzq2H>N%5eQ3X~PRN2Z>aM>wo*rl0O0@QcbP@HC4zr4kS$_ zJ-_7NmvAD%o80~&`CgJd zy%v_M0Z492k|)udbM^(vQAzUM&s%Z~2gw#m^4R`3`(ltRmL%Waotf{pJqRUH5(p5o^G28c33_M&A^=f~348`QkwjJ{ctW zCCS~MMspfSq#UmQ{MB*O4u(b2c+Lz zuXEoJ2$J=Zy1kE$J@#CM51zfocS{PSJ69?mEj8Vh%%gj^+nDY>5gC#7%(KZph`(gUS z;J`{1qXWX6v9Zp$fOxnz(3udPh&$swqi1`L`cdqhB5nf1(@LkZv1m`xwC0WO{vNvb z^MTV-^~eV^txsBV1y}w8z$@^Bc||zmfSn^Q2_{{n)C>Tp6-OMnVMiv%*b*uXbVfu} zCZwYBdyW~CJJ9~{-?wKg$rZ>C{g_7|hd17#x7MzznEdv2xXbinS`l z#)gLyR$;$*j_T~LK3A|Cm``M)-;Z0Tpe9{9w(Q&koO(!vAsao%j3d6oEhzQkg(BkQ zydo3%ei6g&r%l@gNzry6L89$GBI9WP`KD&=b_*5J4)PP3*bj*|ph;UP=8iQ;%pGf} z$K1S-BId+AA`|w0F$cG75(K*@lgOH%@fX9FEDI!nF@!k*Jq(!5)&4W5g z@z(22;;q*^<9Jaa*mkZW-htWQ`%SJ8=}3xqhF2II8$%+jp3ig4IAZilH94b*I3?SA zKQM|IoXBCLXcAwUv7Teb@uF1Tol6m~%V>pym4Cl6@m^FcG^oI&44CrbNsZuw0-;h+$e0Rx<5$j7QUOOn#^sk)t0aa; zqgfj%4*NivP~P)|P~P(y6G8?3EP2OiBArN85mKrWpYFk%jAeuCsX&e7a21ZG6?~RVYWD#jO8sMV|kk~8I*69dF30k zi3XWCM`RSN&n=VT=MpmfTy-)_t|%>IG6ESft9b@y&q9+<=E6-QT)1iKTo#8ax#Zx0 zOOdQ{34<9Q17ZSfuyFd|M2Dil(N!R%bQLlth04Cg^^~Nt8GuxQER%wFDlQpXmT1{_ z$xf|bt;3Yym@y@kffneLlyb8`={-9K|1FMzNLVzQYG99pS-W8{=SSxC$8N&wkKO9L z=EW*`iF)9b`@>At9`>UT=@`_Z3$%qoItR6BAKa+3)B9@>D4_Cejki%8Uk7iAnZ%8=71DWVpk^QdLIz_JhsDE*BrEHXpi z?|D!M7$ycqI3i)%KfL)c+XX+3eRfgLQT3_*{`#=usg{;1WKs0k4%E+V9~>qWNl}NV zk{%2kQPgPBFZAc#%|?~y?k-Z)rBg*4p2(eGk9We>5NWBp&bG+3+0ZrT@goxbX{mwl z$tbP$pi~a#!nANECV^6zDw>v*=1Pk)l#b$}jIC$N7o*I|3rkW37*%L%gQ@57wlI5| z_tovGx_D>2kMKvVs~Pkzd@ejs%?1oQCxD(tiJjn0i;ML6MOvy6w$QL8B-jS~T-lh) zITC|nvN{kF_|}1kc>r9tYC^eIB7u zsu3=w_i(LLWF;(RasmTG}J;Hez2PYarX=M&wZ zsRnq6V5d*6Z6j#lLV6ESEj`>l~>zn;UUsZ)A_2|V^hXCZeGThj%D;V-%(4^?^Df?K5g(K7`|!uEQ80&rh&pP zInMiGTYrjQ%qS=ePnIo};f?du zZ@j8jUfxoB!iO1TUdS@QH2o~|Yx?)J5j83|J;r&kE3DN4ixBuEQ%yC7$*L(lPW2@_ zmj0`JMJ>L2>6JZ?@GIE~uYBZ9z6}rWzatK<)!}`i^{@=<wpPPnd6g#~0xb#T3re3EKRqLv17sqD&P)pQv`$aXikJ8Va zty`-VPXDBG18oU$|7};`9)ZKkQkH%|3|+i;{#Z4%?~$)xR5Ex3^z5^WzG5(9g# z`CPZFWsQ*;=eSX-#mJ8tHo~4~c;&BDy(2Ed>BH}(N`88qK^nASHAt7k=UGv4o9>HT z2)_Z1Vq$#aZkk?Y)?I~AY(|ZZL%1yO3?Dq5$v&)Ff2(TAfb=*7spXUr@5+E9RkKp- zQ5n{$sp-8XQ_~~(_MQE&SsC<6Q0p+A-jqGL0_y+gXLd8zk(L*h9^!s6kKlr}>bshc znai2x8Q&N~xN}@3nA2=#lk|7>jdh!J*|jN}Z#1porvGPuuIx2oxT?^H4>7pc2nkJq zj~i(DK|5>;Ss^}-3{XdQCZmmTR2_48**j9|_`~=0+%?{RXiqup@gGiTsU+yh$hQY3>D|>aywhE85%bYrtBb+*vQ|Hw7n37Z8YQU)+#qOH^UsFH$R zg<~Db3S%`5A-tM~sPigYOvx)}dCHjz@lq5HO{|1f6RSF_Pj)F;U*=6wlFM5b$Wg3?+~iO_BvWhXPwdvvU)^rG zIVH91Wq=yR22L1SkW6ae)Za@u)!(bmDZ7{dM$Xc7a~N)YMait{bt0_lby8;~C_Tnp zIZ6R5iiJdIf-Oan?duu|sk%mWQfyvj^5yu1GAZz+h?Xr?`xqfr`;h}S>-4}*Hp0Fpfao1bf;fU_4NDuFRx5hv^bEe zN3Sk)uTU5OtAiqMA>34z4Oe{?NzUr4)RXgeO@y{Zq?>HS<$NiSDXphvM;XbTU8rTP>vK@|<5RYjvt>xXNv$UlX>>PEpjb2-fq%&TFYxcX+^blWuCRML1Ic5mxvEY98K zCU60U%P_M&fW5~~W$WsHde{2@SsXlQ%R=?2$@Eurw`+lKbHeWK%U18gLPLOxIz>0M z8f~q(2U)c}3!T6$bCo-PRXVWnqEb*O_1h}bd2pXDS0y?RF87uy2D8xN$?}7fj!s}Z z7MdYhSLW%XROrY;HzVu%6y1veN(PjA2Iaf4(730=QQ4?3M=Af1&Vr{sUY1Uo;b}^j zp<_+C6BM)VT1ks~`IQirg)eA|G_K+X1j}Rekh(#7tc43cX*knVCs< z1>difbE|y!e7OSMS(x&c=`?cd&BRo<{FyeKVwzgM%KFI6k&&jD<*lZVeV<#%^f14Q z`moI1<(}G=r4@YhMA?E^m<5!ny!Kyrb7}UEH7i=Ai943oEX=+6KrTLWZp7v+Oq=;YU5e>4LRR!B zX1efM(j!k&F=s`OVt$FK84FWHKF~h$)DUClYwG`IpLAw*aBWzanDK$M!h9!W7&2ex zr^7DYxfHPO8cc_HFM=6OgV5K|56HYGc?yFrK;I{m_rdf7Z8g2qWXeo`xPo%(0P6pj z)s}(nyLAI}1+*8ngRR?OrGJxUwWT$zqQ7431S{Te7y1eUzn_oc^PA7ZO7SI47fb_8 z1z{ie0mh=-6>cO~4pu^+V5kHuIu2q>>Cfn6^m(;qG+$`OXsR*aGIKN2*Y`B}QJ;)X zzbqMl(znrRTP24D#Dez=8Wro8`OK^K;RkIS2--rrvaW#4rL&s0L}#QkIUv><3V!=Y zZC^T_okT|r9&+oG`2s+dCAcm+5xw4-e`VG5!F)%_N1_IuC;m7j1j$pS6YDBPAydK* zdCoX+l0!+}t0(KKMnNZRx|bXm=`~K>GlX?Dps!jQrtd+g=bLDYfZY(0ExN-7kIiWi zMham=zObk`Cv1u}SelLuadhj=(?>N;ma zs3VDZB($f*Fy5Ykzlpb_lYg8@UqF&GIShY4Zc8Vt6RmM}k~nQ>D)qD-g6WJQ5vE9~ zR7SO?sX5%9Vvj+Qpj_38rXf6ou`MZOtT?opB#>-DM_=5)3jJ|G*PPC)1RqiplM^Bk z!)A1vjgaU_TM!+7v5u%Dr!xj=Y)VO^Z4lZ!8)j~(F*gPkRTWqmq{9pQkP$j(7XV?8?Mk6UAa zXAA>0*QL`~@@SUIwg7uLtgu6}Y8^VgFi#wwQm!_g+!bMqi6%U2QR?Kl{oQL4|NlXZ zwLh%xUs4<|{4Dh3kML#8X{OhvaN{LoZEhuJF$`uOunqN}>N#Dk_PVy7W{oC011kZ4 z_@66JNASZaMa>T*(5qcVJTa1^JV#ZBh*#6{D;y$RIXVC_ivDC$hFXtn_HbAWmy-e@jU?q&4WO=ekXFhdiUA)$x@(cc7F!Qu}3A0%De2iH2 z`53P{)KVsA!PdZxqMKVfO=m(cW`^geZn!q_Ui4c1FX%~i6slPXt>{3{QJr3^wn}<_ zE&mtk>Z#rcBgZ4pQJq=C4oYS@S^zVe<*cVCK*&Tb_8iqoRa@dksySU!Qg?!oiR|e) zs+01cuOyYL8IYprNvY_Q5IPa=tQ8TcPAgBCl2*1Lp!J@sYpIP1xjQz5QusffqdFx) z>CEWL)s(KK6ul!tCv3mxs7mYQ+s~Dj%GHE2ExC(D=!6dP9Mx&vYOJJ{r!ml?*aY+H zrx8N75}u8VJi((_k(+^ejq6w`YqdiA;dMmu9Hh)qF=ryO; zZuQWUnmNj@I3d{G-B0RXTb<~%lS(`0s|`d0=o9sB@O1s2aP0cMI=4YhmE3aH0&Wxw z5P495u<0_ub5v&)p`6Z0`v3hIYn0`>rG~gf_+9AB@8k2CN11*wbu%6?mgZ&}{xyWd ze&iMPbM!i082AWO)qJX9nf~wB`*-Dyf#;`KR1F3{P5U5e{F^-df;pa}su5nd?yO9j ze9?5XjhmVc9O4x-0q48tb;aM`Kz0&v2qb@ zS8fMTqBsS1pbfrXxrY%+^35TOibu{-SyUXRlD#g_QE94NQNW90;hy41vBiYr54MC> z+BnZq-CTJ`DQOjo1X|VT6-sVe0f}+8_{1ouVy4zCcjYtdnmWH+Uh_Jw5x|e)#P5`v zat51OomgyUb#+GB?kX*o*A9#*78S5xMN)D?s51gqfR;Mc(+?49(+{arGjC8*^9u)R z6o+ttniE#ibcSKK7{X|(!*f(;ruo^6Sr~O@F^-5N*x5t2*_0}T*_0}(%wE0OsAQHm zlzMW)!ne}cJ)tzoT`5meuasZ?`Mr{w)dtik=6&LGMi@Nz269x@%=qVbxJ?hRZ_~=7bsC|?D@LT5l-W( zdXDPco+_7Bc4hAa+$hf9_xRxvE@RD}qdKRDaY}pT=nb4GcB{b!h&b~RGNZ}Dbz!5QSc)E|903@Q`b{x)E>~^%r;JWx9_}O;$K^L1F!V8)*kf!8TTcHFMhaT#{?+E!T+xix z)MB19E197%TF{4e)sY=iVTMIcllI*+7Bc%gJM0`FZzABH=^qhei%bk8o;l1^8mh4S z43kPj751)UrqEC|0JYJX$uv~qjtDb}hAQk~#Z08*5d}RZWvf5*<0O%UFqGv7f`>BB z`%*yKNyB%!3*Q!QUmA&wod=l-G*scC7G^vRRoGdO8An4E?*B4lX{f?ebC@wSRE6U= zel*Mz6f;wbW?VX=N#2YLTs2F6u%0m3;lYsvtFplsrGY81od@PN%DcRGMkiK`3rx&x zruEX9j6UuMgu$|qHrNam`{R$y(qw-x?Mb$T{%Gw`7)*m->WcH|613 zDhR!F!t!^vxc=DA!?NVc>7_N+fvcpU?>8~sXRSVOjj%YjJppA5lqH7HGeE2jwj@lz zb=6>c2IwD#2ge7!-;94X14KE%r_J;H1L-jZ_k3j0lq~tJdLAk7ob8W-bSpvNbU`vPuvhEjPK$hkudD#^SLy3tbe2*` zQtSS3*FQ^HNYS$S6<>A2$oKyljMZ+rVyP>x5;-A`zs}b*FE+ELDC0F_b#6YVF+{MJ*fRR@x}S9Y zv{$taHCr|Q%#8Q@{-3#Dy95{7v@`1qG`c(f^2b|8g(Y~L1dgiXBd=FI-1Mp6}%!ZgOdW&wK9Do6$g)wAiPkbUi|PSXz2h8M4N`iz8PFV1sR zr#Ri~LsiicKr!n}0(((Ruj5I$_4vkfROdMPkOki4MRho( zPA-F-)8Os3PP*>de2dvmcxryzGR@4bq5bGn<+;*2&Z;KJV$kI5ngi?{E~oM z)<4bqaPth65Jqh~c#i7K!fGpXTE0a3R#T3*5Ke8%dyeYd`mR-S%aZ`yC|6L@pba4u ztnnPxiS^o}B$j^w5TpEhdX4-LQmsyVj_TyPPf(J}9S`Ivx7s|zM}$vH()N#P`Hr@K z*Vam2*_^;D>po%1cR*_4Mm0Z6s5L*Ev8hl)A)bB6w$~rkSJW-nWz&w*ywLPxt}+dwe~h-Fpw%A@m7SR# zZONWda8!Sudl!|a7F=lG32J=sz%{n3BbZD{grhp2J6_wH2rfDsPLT18Q2c#{@M-QMQGXw`yCJ-t-kUc)%jfadSL}uVVZnoFKS22;Ix9f5=-a+is zc!#=uPHMdQ_|fE}7*B1qlJIG?Qk~DSS>Al|(Bz{SPi;7j@M$usN$H2KJL;T-kK5I*(FsPj4C zGv1toCLiq4L3q^7?m4RS**DSKKG`YqvB}$II%x-IXKAEHDJLZ$^+~S>H7MgsLWj;055&P6wr*5C^r@Z-y zH2Emn^VNG3KGoH?2YkJ?nKvJSCLcw6zFJelr&?2W`+VlLPLq$KJzupZ;ZwDy zI-iXVyzOJA$w$$iuR?}j9aY{j{JNg^=3}DCN70_IoS)dIa(;FDtaWU>uFyk8tmK8p5pAelzw2;88~XO;4^7V`fO)YjBl`&)}xZdxW;>TAb{zlrO_ zK4K2xj4;d`V=fAN{Y`<9fIo~Ij3LHc+&OLpSH%GCH^~p5#OF?&3ml7v^6z9X;x^uX$0mNlY;yJDEPmI6W{VfG*sag?wNx$ zRN?*ubAW~_;w!wLf~qiFi!=LZsKUOt%w8I*a9z&qp`gl!t375K1yy0ho&7T!sz|=t zLPHhtjNeQ{74E_@n`o#aPWBsVs3K1G8)&G)eGFzj4OMst5oR3?Rk&r(tfinTl)TPs zXs9Bu^J*HZa8sCBMMG5zYQ-`uX{f>tP-X=URb=MZr!-XIW*@VhhAJ}iYZ(nyxUt17 zrJ)LsdooLCs3H~pVj8MQ*}jN|DpJueq@jwG?F(qAB4zu08mdUyK97bfQnt^fp^7w$ z=1@=-Mhcl-po)ez(gN8@Llr3;cF<5o-stT#RFOA&8x2+DjowN@RVbOlCrO8L}eaRM0c-f*=?eqGdhTiE_g(e@x_mh5Pc~wWhcPy{^+G}k>!Bv?iA4UBY zLe@Tagp^RX&nvGLvjkTqntT-gM}5hH*^a)s)cL&hTDM4WRiw#BQJ?l9({LPpICVaM zi{AMskR~6+_mf_)Nq+A2TAk0IUc1c*t_n2yDC+l~mk6Jpm(=&|jU;*IqmN2(A(|`6$|l?fViw?fa_pd1&@dui`ZMDB6eZiW5HVimUUv|60KZ z_5TYnhrIp&MSi&XCvzXuB~v})W@904s^K3)EPIy?(r?oj(oNO=qm9+v)3kxx{@?yV z;fWSOrPX(bA4O%i<`_w@ zHOJJ`t4WZzebCya)c7czTUT!*d{%E$=hN_|l20}lTD3ImGrY*~Wn^f;z!-%C-YWNk z9IKY7bE?0=n-khOlp?3ZFol!i%8A5ID<`URs^vB1GMfu+8cLB<99f8sa9QDAm}7UOHyLz#Ah3vC!mEq^N-Ps?i&KFe#V^QltJ zn-AJ6lop=|#bCrTcV)axy)u4N+0UB~+8~q~AH`tA(wxLTOLMB*r{eG4e9*R_)c7bm z|BHVid=~$r&L{AwHy^YaC^bHc&i0~vgwLXT>U=5`^5%nf|D?u8F_^y4ou3!JBR`k+ z+LBRlq3u4Y@lkaC7m)3^91GO9<9bt4@U{=y?>l`wB+A&9E_B6~>e&g>oIBRvGJw3C&9SW)M z?TG=(sx{3$ew3y@e)Oi0%iBa~PfuzlQWVj%-Sfp}tIrpEQ_ySEOu>aV^Q6W{(dC%s zo-Z~_eZJV6d_LnxXctdvd=y=dnS)7|o;g@OOZ)kJe?^;jQsbj&;?KxU_{_+y&L_9m zHp7Ao?b}I>k7E32x=8p;7uEUX{M$P}qa8bG@d;PV&zkC<4>k3=I-hJ+6nv2Xe+6wK zBm4g=z5j(u8TkG$FtlP{vzu5On@4{^KT2Os_e{4;*I8%M9@ZvGzW@8pPIC$H|1S-r z1+z5GnK#U~EDsn^a5-@hr=cGysEQ(PUq8@LMI2$C(NIM^$ez+rMclrg&`?F(zP_iR zDl#5B2;Zlniag*w8mh1`USNFj5JhAQHjc(W}F-T6#xn3C~Q|AF!l40D5yI``-abDfSl_rM2pjgC6^m<4l{ zMluku&MOpDk&y!CG7VM4C-4#tRiym7NJABw`gDPYD&lE>o`xz?6rQ7?iu6U9voutZ zivJ7^Rb-0FX;^SPUlvOWsq@C1qChN?%rkmSLlyB{eMCbQX}x_*LlsHHZ)m6@iTE`Q zRiq*KkcKKU&*%XKRb-0^<|GYOq(yRqhAPq`IZi_rX+|8Qp^D5vJW4?o=_@ivXs9BU z&S4s=NTu^}9(N}E|0&Mnjv^KGcNF~p(ITz1#xop>A=L|O$@t2Jwd&&;Njuupv6|H@lp8So^C+wbGm`LeTI5% zLoB$^BCFK+;L?`xI90`SROd6;$E5_Vuu6@O!vFSUF~a9$F?BvE3%t_{t*uIpk7B&} zgnNAV#5=}!la&5cQ2xZwqZz6rx8@5yAL;A_YF8l6yj_UTYFZQ-iI88nZf7iVi37@?e)%k?g_vRBu zlaIm$V9yr9XU`UOKK)8~^9iNNM^XOlcCTN%d#*a4K0fc4jV2#Odv%wS*k_kholnm% zyzSGECLcw4xU&=Cv$K;rpUyt*=Mb8F6z$a=r3s%MrPcX#8tQGIzBKvZ4_SoAcENL0 z=hLB;H=jN<`6%j(t+xrEt+&P?f6qQ3Yn8{zX=Hg!I2|Mj*{FPeN5?bXe_ z2%pWp)cLeI>CLAnO+E@2txfLyvq@0r6Rez1m-YVtXqxNI#wz?Po|Po_eO6Nac`kMF zvhQe`>&?b0Tuh(3=TAOWpFjEL!fkIpG}oJrQOt*V;$9#4Np^MnoIUQ%hvs^-F^c&o z-@EhQ_wUGmr~dTjLvy{^7)ATwJ0rxjZw4@zWJG?*Ec__r`J*MDL12Ot~VQ_=ns7T z8{zZyZ|ZywH}SR)&Glwu6y^Iv_k7NW%hmZDIOolW=6bU+it_ovbYh}l!EhvxpSF^c-)UL3K{y*PC~yPA3Pp}D_nw8B5|t3HI! zSAEp^Z1&rHT&zEh~`D{MqZ6BKZyGASew_mu|1OGyOJ@7Z{y!!*A z(f+Qq#vh{<<>B3m#6EW`s@rFc*S>VZXtc#EH9m^|$sPB8On21xV|ugFr+Xg}|Mna1@vIwn)cMTyNiVcND>Xg}|Mu%=h<&b~QRg$;XMYy7F)KAb ziti2Aju1ZAj;QmQ$$O_4+KQDHpZ<#X{c1z%ciJ@q4OMtNUc=K+g`0*N zGYwTF1x++m;Rc7sNJACwTWUBOs&KbZ1Cx}Xq|KVgJn7MCSPH60XH27~p$hk-G&&lp za2H6UrJ;&sQ4I}Mq->|LQ%p22kePpJu)+m0^OlAx{NgbG&`?F3VBgSCMVw$?(@;g6 zU|&&CMOvlIOB$+(=jz`yRFTZ^7Y$X!R)11ZMLZ~(KWL~Tj_AKrP!&bqK^oHtV{sPM z;tC8xz8z7&5HABfk*Q{rB6qqtO@DUKBfiv3|% z!S-SkvAS4BEGSwgk?5L(WMgr$us>oR%d^7Fd>zY+`p=f}{-~VaY23k_9A*h=_=YfQX2QfQX2QfQSf) zfQX2QU-hY(sqST~`2pp<_jx|}<89uloilHrI^A7eb*jp--|@ak3+WKw*O*3ZU54~*Z!`3t^GC9!!gmGWFKnpWp8h9WUpo~WzS>B zwp+G~wv)Dlww<<3w&k|DwoF^9Ey~u<*2&h)R?}A2R=}oO?^rKePg@ULcU!kuS6Sy< zr&z~WW32o_b9^s~%JLsoT`G>LN8u9j_*;L)4yXTeX2&MJ=Iv zR7tt1Tu@FZ2b3LTRfVO>Y$cuatwbn&$a_ZQ$){K>w=I_}r!0poyDXb6D=pcU z$(B);7|Q@lXG?QSElW8|A&ZUd!FW|ZBOj6X%3I|%@&b99JXVgE2g}{%)^a_$l3Yx7 z;rsYHK97&%{dhZGj~C;acp^^1Lvb(M9yh|(a4BCOjpUZCzE1WZW+5wMXT~6vvG3!N z!r18-k%h7ELXgbZsn!TH_H9js7(1B{>3;7UEd9&MzWzhH&)D%_q<ZEj!v16Y~ ze=~OUBk3+ zefqL=gR%Y3OV=6uq_*@MWBbZV*BJZQE&a;ao_o?&#&%zjt}yn|=h9`yc5Rb>VeG?K zq)UwLoGAUw*aripi;TU0Qu>Lp?T4fbjJ>x>`jN41^QH5Qy_+DNV{B^==`3UKRFZyR zY>P`e!`S8%()WzLl}9?w*qi;O?-<+Yl1?$UL6W{@Y~5k$Bx7s$O5ZT{#wXGV#@6hS zzGiIo+tP8yRxOdfV(j%P(lN$XCQC;dThU26!r1bL(wB@adsaHk*wXyc7mO{wAsu4u zweO|R8C%p)I>^|cc%0)V{=AJ zdl{QuP};-TEVs0qu^Gptj~L5(U)sgkw3nq18H*Vr?PM%ERQiCis3Fo0#v+GE?=u!r zP1?>_xGKHJSlD~gHpYfblHO%3beOc2vB86+cNiN~PTIoQzyi|SjJ;@;HZ#`$Z|N<@ z`h6j7Vyy2@=}pG^Y?U@L)_bG0fw5l8rS*)xuvl8hSkITGwT$)1kltXddy=$=#s4n2Dzg8 zTPHBm_xyN9`s^OZNbgt2GSVycB}QHd9m7b^s-qd{es2^b-98z~NY{0#jC2_@f|1VM zQWy!Tmdr>el*CBK{lgjQketX!y8{UU61liVJR^(t#WAw*l~_g=3>wDBt7T#sdF5O* zBiWOp7@2!Cl94&}A{d$VVK^f*qK7gvy>=KQQ-2=9$dnzSjJ%vZn32gbgBY1qXCNb) zju#n8-!_1eiGTEGWWxG>jEqm|%gDI8eHeM^TyI9ktm(zb=*Sls8C9hxBdHsDFft;l zJ0mHLx-pXUNmoXOXLMmCu}f!05{iZ}68B9fMq+0NGcqiwBO}olIxrHoxIH70{n{}S z5!9BEq5rgDBy2}(Muv=P#YkwmmW&KK)Pj+LQ=2pLV&~@>8Bm}ZBmIsxWu$L<6Gr+p zYRpKlpBpjq!tjQS^sLc}WrY<9$2i9Sv(~a7U1jpB6q{EHp7-=6_ zlaY4$f*5JDvIZlq2UTaJmA4urE#_BcqjMVv|EF-niGmKQPStdXtVpo+8knnlWlnRicS@lZ>NWWq8N-z>ttT-cK zH;OSbXhTs(`iw8aNcZ}M8EN-vAx2v4F33o|Qw0K~N6T~h8EHBoA0zdO=4GUEW}X1) zRQj@)krFNsBSj9n87Vl=#YnzLCnKKw4n~~w?TlDw+8B{*SOX;Z?pl?RKej21T#+pS z(rV@`IY63}FM*x1)ecXYCZ%3;xMoUcNk*ObruTyPg!h1Vhj*iQsdu(F-J9Z#AaDO2 zy-mC|yk)%kycW-G&n3?(&mqq)&t~%OpY56K8Rd!b4DfWeOSYS~3$_!s1GXKujkcw> z*|v0BiY>y{$JWu-#8$&r#+J`!vEH^`vYsM21iP%8tt+kB*2&gU))?ymYiDb7Yb|Rz zYay#my{leT&!|V#z3NtVjk-XcrjAwP)xm0awY6GLt)v!HUCMpsx^iAQuIyK~E9;fT z%1mXVlB5h(dMWLdMoKlMl#)lmmRpvKmXnr)mYtSOmgSbYmP|{kCCbvz(#g`yQqxk_ zQoy3hcgVVhr{%-)Zj!yQN}exIk;llf@<6$(+)}P1SCEUy4tx(^!)Ng^ybo`~Yw;qS zg~#JWJOuZ|ZE*u!1((1c(rc0A8tUrhYVT^~s^%)?%HzV$TVx%?lcdjLr*o5YxpS^F z)0ygwa`tm}ayE0;be1JO7OLZpdGV~it~^jCCsv~<*QRB#k= zIPCZA*X(EQ$L#y;+emN4B72s7ygkuA#NN~1*51Hg#a_bh@ih0;@|5!w^4Q#WNzcm} z_YwDA_g42B_X77c_gHtld$7B^yEW-|spKx^cDe4muDi~=j=T1|w!7B57LyS0{R^~4 z66ZuA*7`|^4nnN;6CXATvDQ!Ar>hWa{lt~~7O~dPumdv@YyAwXPyn&kPt2$^#9BWw zBYU8UfnSeF?TscdHevu8&sfR;G>)<4u4pV{N$t@~j13P)V;D>9iAFP)P#=wAEWQdF z$yl6%QW+bz3yokb`YK9ctX~zB%vj%&D2cH?HZ+{EUiVNUV=vr735@kTh2k0OaSX*V z*8L!gWvts_G>oyX$50GoUA{umjCEduq8JMqh$0#5R1HNi7F-F1GuE*p8p>FQ(kP6v z_9_~}SlgQ@l(9CK(O||}e~kt)*6KYpkg=9)(2I<<7>5Qh*1Rq1&sei-s2^jEHlx0b z)m@JIFjglO^=7PgMbwM2=PsZZ7^`^!^<*sQ0_wq7jgzQ5W7WSz-59I30(E7q>O$0o zu__BuXT~b8Kp~7(T8cU`R&fprW~@Sg)RD3BZBYlt$~8po8GE)eYR6bv7i!B`nJ-Wq z#!7#JS~FH^A8N%|$?d2mV?ts~mcc zF=u{MlQBmT6vUYAGOEFt^&G0sn0gddV@%nDsxoHTj;b&ww?mZ~!;MiT#!wYhF~Fk# z{TWqY?EcTFJY)a-h{`c`?+kjDvA=&nWf{Bs4SI&LzviJbjNQpbr5XD(8 z*dGf~3C3~L<<-@ ze+#|J*tx@KK4WL6p;s6?^Et|9tbKPhFTiH5zJ%rm*o<>!(HzFwY(ldGEGznLG%LWS zuPBXXGG^(5W(3%@E{#!EfF*6%gQhd4Zbs7rY4S7Xry#*SLikBl9jiq123$c4@^cHkm9%h>*C^aEobe}~R6w#SaX zXKYslI?dPz*U@*3y&r~7F}7_3`j)YGWpt9UcP6247~7HuonUP9T=X?#Zxukt8GCac z`iilQdC)P&*1w95GPd>>I>Oi+W6+n3t=@wUGq$P;`hu~Q>(C*_mfuI8Gq&^tbda&v z&Y{l&Ec)znWMk~<=%Ifc_5ZoiL-OWVLTYZ@|1XboqT{+_u>FX=xoxwpjCHnEQWKT4 zN>|HnOHFyXoCi-N8U2H$BU1A;SGvgkX5-oV3NhAma4R53)A=6%I9BWCGY~x@_nVDp z^QmIgqg0Q2)Lf5!o>7m;{bqGraK$Kei#c*M*JFLps7K^}v+-<8z!=MR>L1H?b3LkY zJ;HR6`_0Bf3J}#Hll8v-ZEA^;+nMW;uNeJPN#OjPcs5@;1~;a9aAR{l*kRNoa=+Pl zHa|HARiS!N6>~k(4@NyA_nVE=%}@UKXV61lk4*L4yFc8hN92C9ak}}*_kDWqKSa+x z4&G3qHR(m%TO zNB;hS>iPQzb3M0Jqn>9(>d~z~a`zjm=k7P=dTtrF08B3_6>mggU{*+^VsA3}ZKzcUy z%kMrtzduCJkAsc=DJoJAk$PBrKKjNSs^`WWb3H%gXm1o2 zsYkcI&vl=k>krX$CeG-eLL&9()<^iww?6A{4_Tk}bdGo~C{mAZeS~Xaw7#x|nb+6J zZ;k#bAW{!|zli>I5Y_YRAagz680Y_|=NGAmyG?$J(X9`C zr83oXrLwu6BinWL<)8o0X8(Jdx!00B{d}%ZU1Q1qe~&f)-?#&y`}hB5{(mx^bJa<} ze2-*0=PFo)DLUt>qX<)U8gmB`rs(vo_5w^L(Fw!t1ei*s)8m_oFh%DcHx*$D9_pxx z2vhJpMvX<7qANHw5@CwY|8FS56rH}+K!hnev9rDiQ*>fyJrSnpO{T60Q}i0FBfwMw zjjP%MOvOVN45}r<6kUVkIT5Dl&Xq)%qL*_;0j6j-D5@aB6kQplya-d!`H0F1FqK3f^le0# zqSs(+5vFKdwGv=zI1PrD0!$^+8f+oL6m6_h*pt z|MnvFz-^uCDA&+`G}qJOM_vC4(bG<#9{TQ0bv#S^dt#n7@9+8N`4&b!ZAI!~<6SXj z>H7cVXzrh;os4?gh}6Tzmtx9%LH$(b3v)e3W7Em98~uZSuA3Dr~j6LUTFbL2;~ z5~&ATJXA-ieg31lo_h0*{%I*t4{bJ49VLDFBPAb_KT>zLQBMnjdT85=>M60-e>C?` z?Hu_&%|+^AYt(+=6b3b_ajViDpC&{PmU=<_ah)jb3IiT8U52lq#iat8B;ip`loQ5xt_|u81*z3 zsfUeE#uQ4TdI}|(>#30Ae%MH)9yUH1Q!tt8DVS`or~GoGe;SI^!^S6L3ef%A$kAL+ zxh$ie1|s#a@yVF{G1Nc#W6brGEp60OU!)#3J{gmb?q@-c=6XsS_Zv>HCsGd^pNz@d zm-;7fUvoVr*BSj&SEL@@^F2>LswYoBb3Mh|8}-x?sYlm-_WJaAAEKv7j`m?~fqH1a zIrWRDh5u;opF&one`*QTLp$H84tHJu(Oge~Iz~NYp%P*1$;a#3^R9AKkE@)yp1kLc zdTNT)qkEn@^HV*}{N{SRgN%BDMCxJrP%#d=9|1X<>v0?R*GR7+QjhNa!giVZ$9CCV zk5j*Ywt)A4k^A4K=-LOtmFW2doA1y0&$y<>`W`CKzbU%*LC1cS z{rQy7o#N-}Tw%A=hV8s8Nr|{clrr?UmMFQ~$L7+T1^huNw7;-2XO( zioN<4kbdmetCbRhwF)hYXJuSwW z>xucw=pT{$-zKy95i!ku{j<#<(mxwz-2XORtGY<@&cvuo5p&90gICnCrDe_w(3 z!(=ueA*Ru0s;ALrb3H@58tbc%NIkm#n!0rV$e6mz&Gm#{HR|atQje~`rcNsLPn}eA zJ%c_o>ggp?kFI@L+xL90{gCJTK;wS$=`V=XqifGScY*rnxeMn08PLb*pPnN1==zUp z`t;O%h@O5g8};-MsYlm74D#s-dWfDrIrMZFsYlm7tZ|aoSB;bA_0@Bl(Ldcp>e00i ztA9!LRR7XkPmfVXJzYiW(X|h&t)P0UtuWWqEyw=QT}0~9&F8I3=d;9AHJ{J&PuH_X z|8y3qN7r7h;?q;*A$qzrH|hxysYlmdt?a9>$`7fpj@ONPI*HVy>(8pRl*Uh`rRMR| z{(wG$z|#0e8&iav3Mh%iMT6QLqZ z(L2Ln5vFLneUJ!K^x-v7geltUdr^QXIskwMh%iN)YW+o+qBDc~i7-WPeSJlkqPM<2 zB23Yzb8iu*=v}mz2vhVf`ho~k^e)=-$;baQkihYM9%vyf5GNRfJ==|*+L`__+)uVSv}jrB%7sUr30uJ<^F>WWj$^}N2xsAq&o zJ-Yt*VY{fFVY|%rtmtmklOj@&?s*Y?mFkJUYOZJLEu)@ffqH1qBh}H*7eDOa>KQIlk1ju=kB#c-V>8z?Kgy^lQKTN-{jk?Ps;AdI zb3OBJ81*EG)T3*Uy>N@_dEu71p4p3ydg4Xu(cKSwo}zkso-)@nvxreooJc*o>%GS@ zs;9>>b3IvIjCx`P>Y?3jR7dxN{-e2`={=2lhKbapd%x&*nCj_v*j&%lVMaYMBK7F< z#k%_HtLsDR>*bY3J<%fd=-TsLzM}r=@|C%NGIO+7qeSY_F~|If2$6bp_vcR4sGd&M%=Jvrub-{G|68ONC2y+d3jTup zN94cE*bK!hrIoZ>C96%cA!$m1pcj(E$sz=?3B!_W#s?)Qg$0Esnv9u*CB(*thowX( z#3u(0CF>Uq2~7?skI1M*I90Ouod2ku@?VIGAD3MzONmQ~jtkFj*W%k-L$-f2i=}v1 z%5sNB4-HSMkrbYo5Eq)5ohA1Sjm(}$zEh4!@voM^{o(Aa_M*-qJJ_0~hK)#0Nr)pV zlENdhQ?k>tqtr@K)+k%BEl?Ka(0^W*^SO)jd121yRXLy6<9yzN^LafkH!^g{&N0=1SJ2SG`NlHdH%{;hs;eAR@3DJ=u|BHvyxW&o zFo9RFhgXA`=XN)*Af8w7J+B~}S5c>U1sixZ_#@9(op}YLcy3?93(=iCRl|9vFi-At zyl?!;lbe@kDxOy`hgWcjS1^rNAah(2{A})_8$2cV&qG|iIDCm0hrjX)x^gsy^yd{s z@Ct_W3YPF{L*;pDJ?|=C$_t)!UMS4wo%v**6C-&S+6Z33T3*3Byn;`81^@C+umJA_ z+wlryo)dTT3SxMs_VQ}5IZtkN-Z#ece!Ky%K05OXhVlw(^XhyD?;D}KZ_MRY)Ja}J zG|wgDc?IQpF4@DoKDzV1@j0(x7q4n7@_yqA?;B@%PJDys#BH2{;Ey;rxUYFXF_w3a z*~Kg9%d4jhUV)o;;^la)m8Lu&X7CE8^6KebUO_XC4?{lU`HF0;?td9FG<<@ua6Z4y z`TT4ypOd!wvuV~0nY?=218)a|AHR7Wcq<@VoWolIIr87SZ~ryp`W3?}KWYXhQml_H z#lM(e0(%)I+pAM06$Cqn=InR zT^?R|_2rrRjCVDB!~2a%JX6(pKknf~YDh^=LGadGLQ?a3S>DC)Gp{!IO=h~CJZiJXGq z-nrLoa8mA{hairjkhQ#f)g@lRZeERF;MMqxyc)m2D_G3)?P8t_OY*8|DDNA~dB1U< zS1^iq*#z-?wUYOZ$-Md~$1}Bs_l-upZ?xeRoZuB)(2nQBo4o2+!Yhd61^a6} zC)VJdU>jb+5?+CwcY+0Y1yy(jb$JCNc?C^)EMf%KHrury#fw=SpkE3z83b1qXQrgLy&HlXv2?cm*zAb@bqQJ)7q$vKx1< z-4Y>dd0yYf`;9_8Q>A!69>ps-$0-Otl4VOy8QLl~G&woj(2WxEzU6@;GGwZa|EtPW z$^Ea(WBXm5r+Nr^`tPX+o_gS^2cCN1|C|TXP=?bjO?d1c;qcV(_!QO~oU~yN^ahio zd2jHivvs|}M18_;d`fL-WMQQPc5fu6bhrHlA8y;JAP@Oj36W8B%uwKb4);=<#)C2fG99 zj0ci*f<1vU!!tcN59jkDoX;y}sgdC+ZQ@gnZG+%SoX@LpKCj08+!{VAF*adnc#a?7 zeW7|5=Le^d>tI{$o0mu5)+dWVn~J}3;M)4QE=sv zqZVvS^3i+9gGq_=**Z)n!S<{n*mD2f?5uWz&LBH@Odxa~48xs)GD8@K#PXW-$9M%l z^9q7_1%)_oCLxn}uMO*X1r2$x4HJ0%a|xXUXT!3)nhq<}cTe8#v8 zl~j2Cz`byC^CzhA*n~)SAB+zh1(i*XT4m45^`WbcjQ{@e|MJi+&AAWye=|F)l>p`0 zy0q&DDmj?Gud$vuvbs(KR$FG%m-}e@c$u^{2S=#sp(HH_wpyyn?@Z1uF0IRE1>6zyeZ1f3 z!F!%@2RA}^&JE>N;4+@vi@YDN&Xe1LXUf9+@eE#pmvaS%l;jn(=Bet;Q}qVVSBp7k z9$YND30;mIAr z`^HPWZ%pCU_i|oABJa#c@(Skg3W7N<32vNwl?Qj@e4bl|pO#L=&1z`Gb5s)Vv?udU z;wxSOH&-T}bJ`(=c$aH0&Np-ud5jNh?#!DVyz@KCE8va*a}xop@=k+0zV<%n{6fCu z)e|>SE|eGP@A6Cy;GOv^yaMjnH+RO$G~Nj|<@stlPcAnz@GfGl?t6NTp|8^=$^&OAB5`$k@#s1m$_ioAkxyn$ot0oyl-%GDfV$Z5?ns_>x`GY zAHto@$emZykyqizcm-*^M>TgE&{f_y)^W}|B%SvS?u^OpD7SHV+7tGF2etX<#`XmF zs@uvt-7wx2k%yOx(VkaOmgno=c)!t{7vN=hq45l_pggZ&F|XhgUcryNg3>%EX7LI> z;uUbG+4bT1>Lky*vv^LN!n;dw+g>W~8@)Kc5zJe>pd;tDvL^S>Lw@J|GOvFjI3agS z!9#QZJY*r~6hi9q3L5j`paZW~ukZ?{^D1vXuONgM2ZMOu_>of({1?X~jd?z=%{z@% zyn@xdf@U01A%F1-w(?H=Fs~qpXKEO);3J+X?o5QcoNokwn!9s@f6M*zkkY(p+sZ3A z!>gu9Ucnk(;C{d>xXr6S?hK4PJh_W_1xXyax}JOE!wm7%w&fLk%PaVmSHPWw$(^P1 z1uv*Fc_Gq(6AD#$o?6N);7u0^xySoPP2P!fJ5abiX54x!9j8}s$o)ewC zZ&cvbxxy>h#XEEELN)_9E(v}<_bV;9Gw1W8oX@}GeEw7JpNDYAQ|@wpTEZWe0J`ihuq+KdowRM8u4PFKJP;Mm{;&7&s1SvK?hEOZUrvmLxbD5@jdUv z=kiW`5HH4Kcm<1i1qXQrXL$uHIVT>{jOW~?yjbhTE11VC@bY}+<@pNn&Z8i&U_7tj zJ>HpflOk&J&f_4jpggA_xC7_1>Bc*8?!ZiC-ucz!Rp7V0g0FL$BIEzs{(sf*2r1Wn z{=RU%>}uq^>|EyT>O_u@91|SR+i%)8*az7Q*bdk-Z4IqAtZS?t)Zf)vYHj7DGFmBT z`NR@qamd@`c)0}r6pz5qqN8X6sxEyeO$|zxdMarZ?O30v(M?HvhJ4b^cYL(v0b>)w zLSw^&Qj$XBlS!%$EE6~+zD7)PLOfb0&SDg`xK^CSNNVv7aTdd=#Wlh#hK`{YSBtZl zOf9YwXEBLdeEq?=`X3gT%q@CCld8vsQll%y$&8>DSF}^o+{W;K1exJUaXtqw@1dlX ze|$S}iR4-dPYz0sORlahs97T=F%~Twq@*={a+~3Cq0zC`M}`lHN=O)1J%W(%p~<;J32l-Jc$M2f-ohmjVRk; zqynQOqQgk6>jUxC7nHQhqJATA`OF`nq}3N`wR&>OX#chI%42Q#0uD`^EE*GAZgq@?ipuxOv2 z*-vt6VF@GRQk;(G_$Re=6vi^BvUdVH5bk3q>u%24Nb8B;TaS$ zA|6&@CO2K*{S4fm^}J=mBimv#mC*FZ`hH-N5t`OQA@hVD^<=`xYSO;xL1?PB7xiOU z$bBLPn)2l4bSdZP<;My|{o2+3^k_7>i$WISesou{6E&>AjV3)-9O+gmC@w1V1o@?v><&joN_Hniww!zjT z*5}o2Y6WGXVz)%fhva8*Iy#SKT)JQ9nQH&^SELzzE1A0{3MY@ChtczXEHLhQ)*H|K> zDA8D3xJLb`Al3I1-JyKePbNE*Yuhod{YS5_WJVF9udZl)#-T+j@IpcV(cFP=4A2WK zpHY|yY$IA=?&FhG;CZ^Y@vQR?+1vO`f?jChj6y_cWzj-mZ;%}4IL zN=9CyM|o1`(9vTMFymZV|Iu8?(ffMGxHIw)AqAgQh;ay-3Td;+e>4|#WQ$&qE5j?I zrVQiQpd%~#ZU2$4M_at>V1B(GcZNrZgA9Y=AY}TA(*C2lppRSW1=%v(M3D1|Ys^2Q zPBmD%_>X)o+CAqBmrl#Zkr^(s`WD--_GC?cYUE>&%Y&3@T^jq3nj~u>+N61~MYHPP zfFzT}*7W<;=AI4k==;@j?2yUChVH>Ed8l!3WNydN150-OZ!c7~a!GVhE4MK%dpT{O zIy8Q0t|MN~awI_`X>?*jbbLx~-!4>+ED)KhZ8+UMAt9x8bP`!BG9hVnZhxA$Tq@Zb zTgzc>9UecrQ*?5!2JN9qNui?$X**ZvG5}}u+sM7}|Ao^ub+)Pg|6?`bqCSp@j!g+q zdSp+Up2PoE$+qbDL7*Y`ANR#cZiWAweZ%FIOBnsf@14H&-~P9Y^Qo5qs(+X~5GrZ! z|HY)~l6Qb-r>C%cyz7RmpL4gfvSY6OZ~IW&7q)uVWmcOyTsft*vTU>zl*i+raaZ&{ zDoeg3_Fr25jJo8>{LGU+nGLf6A`&3=8lHp;CKUG{`44IB{q&YM@I)kS&HNd4#LJ4- z$r?A7${IJ;To##gWzmwbvR}*wS+&K>qN(px&RDPiXfEs87^AFO!ex=vMQut4l`|&A ze>9hM<)%^AbK+&`V{5dP${KAomvyPNQC3ayvgiaDDrY3!o^-)TlkG{hkpHQOQC5(6 zS+TlGOwB{(rRFjB)_JEVma9LscD{=UEDr@+7b6MXGHp;3hUY6cli3*jKsF=$-p%`UV5iVJ+y}e2AFndNBBI}9!)k)8QZ#pIw(f^SD$QPq^ z0RB=!FQ#BdX(Fcl6TkBKXXO~?bb_E+R}T1(=E8oirx*52Mkyk!sW@T0iJ?^7WuM5) z2h2rYY^oPoBBLY`DSTwpFuRoM`(?ZTXs+*qVQ`>KMhT)%_~>wQ&MB%?+ofp#k*`r} z>Tjy9^Px8XzbbAdSt`iK<#f3wCd)*5H+ctm9iHu;2u}g`UU#Cql8*)6v9!*}lNu)^^Lb($>{_-@4J-kMt63Q-`Ygl-)|aQo?f3G72|Bm(YCFTDmDM zd6cdKI`5j`6HUC;-_R0Mst@r^6+bR)R(B$Op+R4Xv*??7eoUCf1m9U76=pHsx4gm; zaTa}k{8E@jU%MNv7iaP5q7sihvCf}$qrVWvFDeo5TlnIzu)2;P0v#3T3t<-h>oyz` zXVG_Ee=g3V?VM zS&XAK^RY0CF}~>8E6$>?X7&iP810M4-Qq0L_f+(eIEzDR&Fm6pF={lm_@Ow9BdEol z;w<{^j~|G$NJnhY4sjNJPp=pS@gA1-V$cfH~xb*iL>ad>oW|r z-V0Wn?Bq@Qbxt;(VU!gjUKVXFQ!lM*;y;>ut6`W?Rwv=I4E?Yx*HKw3*O|+zmqS*t zcvm7B7o7kEopN-~2~&S*3HNHMJ5ii@wWKIrGx} zM{`*vdm6pfQn)N%hX9o`x1|4QE~{9MM|BJFvh*Q8`$H;g_J`)O3LA!S^Jg>{F3Z<7 zLFLTq<3F0qDlptwiO-9dr5}f%@h6ov<4<#0c~2N+H4`t3c9KvzSugvK=CV9L8D%vU zF3Z=`Lgh@S^OF`#FKaH#+14nliFjGGn}N!jy2F1omt{*d%4#fLmcG3;OhoxoQ6%HOgurT$Zm3i&kEy zFWV~fA=y^<>KbL$7cWbHmrq|o<)yDMt;BEsT4$71Pq-{!XBw3=@mK%RT-I&uVSzq5YmzAF5rE#cmSt)vNedU{U@|F3dlaph|8od=JUY5Q?;;3&L#ZmKV z6emYtGRhhvUY0%``S4U)iHE0}S7Pd0Mp>caW$B;Whg?+FA(y$Vgce3wgT>3zKOhfW zq_PfNG?x`;G0GYwTvjq2MW%B0(*(H%`=iZe4Xa?3HBh{);kp~d$KO$TAAe^qD=O6} z>qYUh^bemsb}DO+-CS1qyGB_9#LLp(Aa+GiS-T?4Wev%Zi`-wlEd5>ngX>h*2iMJI z4f?_8t$yNV=^xeahf!JYhndTI(QcI0SG+9!EB3YxRMxf)=CbZy)(&NR?n}DvU-V^rJwP*#W#m4HqSM8SeLFwWj+53Wxm8?s_3l({-e3FPKH?m`7?S5uS#F` zGL`e@Jpa*LRtLjMD)}?IiBtZj}twcUiv^5s!eFRg#oe>C@2t9|1ru_2+8TtTC#(fA1IVZ5B)1UwjP1 zvC(8D7--g^e}xFHS>w67L~(L>5?Swq8ou9GNqg>zJ>fH~cLn-Kq~tK2FYbw)#NoTk zqpw98{r~yQ5K$FhCr7OQEh<(u!-iPBD^jvPR{s)ZxONU-+!5sq&9K22e~Of>_r+~d zhHK^U#UG-4p&2&#;+9CsdSCqBQc05^{kBVP+|gmaZP#u-&Q52^VdU{ew{5%eSgC)$ z^}fhfpX6ak_d?Xx7lYlhu0PgE`7MHp-yUn*F29NDskOk$wPu!akL=tevVj{tk6#~a z54fc8$bcuVKGp_=+9s+I3ECuJZ3Dt9?Ugj|BcDY=ixDYNU40A0QA3x7J=)kf2l_>% zQQr^+y7X8fncJ)|-{=DRS(ruNzyP`^&LZvYK|cwz=>MDk#5vwypigC4&&mEHzpLkL%im^4 z8rG63o-u}~drq`EePfr(>f!bu&E*a5tnY~`mNELjaGtKkOjUIY^&idE_5RGLZj@+s zIbO%8sxEK(kLK#S8;0GAXN(kGwK?DEsI1OG{-e3PPNR*^OZ_jL_dwNlT1?e-T5PVa zwIKznSjGs^>T7Lu@Jqe#if5#VuG*Zhs8m*m5dYC!UdbhTdBrl4{|o0m zP_^yoXw$NGCZkQ{mN)Bs9lbhBMiNmcKmILG_p(gA)0)nhS=RbK-%DgcrTYsFo&P9f zxLca=_%Z@-+#q7e`gJPP zT^R{vwRu)Y>G6-a+Pq(v_QneWmJF-vKWakO_!VLCI*p*Ttswakp8E#vl>5v(ClDamP+<5ZV?+xek;khl6>fh z8tH>F;)y@(fndq>Jm$~%dNRNji;ukSKWZ+y&2`D#nE{uWEW2MU7oYfkE<3B)lj+S4 zc7kWx#HZ>!<6E3tR~F^aZ3Im|w}y{Oj3wJ2WE%_I0XNgn$>tiw#c>{K9P@CAM^)_a z=Ak~V(ZPSzeEUzXzSV}fUis#K@ofRUZ~Z@%oz>uRHD(8gXE}Y#^M@xzhUenc;l@8O zIxx;+%om4wvenhV*^FB;D+ z3NFO^so*}`lD6EEZQPP$ypj-!D=wrxzo;L-s2soO^9PHx3)YblLoQhFV_&cjb{fM~ zvhd7T{v-do{kLw_&F}mexH;1O|B6b>B<~Q<$DZ=;DXz<|5a(uRKF0|ANqZyP5}RZl zqJE-QQl?pcwRDxY$OZ8zbP6>kU->`rFRfUnwkwyo7k$!cAD*02{ef0*`f70Avh>yF z&f7gw=e)F{nc5y*)gQYmb9O^KSEHVBw2X>ME9^h=#c6ls8>{rq@RLiqm%W5-Bc6CI=NYcAWpn z7e`*T<~(ywFRoaow!@dmdey`|Sg&JlQ*~o*o2r|Ao3-u9-K}V*w%?a%*F8|Lqv;FC zveAj=;?Di5cU{p;ZSOCU;&SaZ9Qil(+{nMp#eEm97gsFPCAeO5W=>F5skD8!EOmyt zx+4qq>WXGM{{z=OP_HR8Gk95wNoKIt;ku{4QJh1txLmsolN(VFCO0zo+>RT1am6z2 zg6lQ+9>d|jyUFlz=IXZmu2)wy)Ak>@?tywuSWaD+u-shSrj15%R>9(O?JtbCP;v1V zb8#CDE9?}@R0Y>-?%jp4baDS>u_lZAYnQ~j4o250|AFfssMnb5)O9f?^By#Ds}1Wz z6wR~<7WZ6k?WSl%#YH3YdVRgH-gCt=Wx@5TiF@$*8aa`wi=1e#ZrKjKx}ur*KXBax z^&0*M6&L=8xwzNb8^s~P;+Vcn-jxCN=j`@x$jxml{$3RC{M@vT?M+HX_hr@o)e$9T?e$2klzRkYYzQ~?s zA8${z53%>Ox3xF0SFx9{dpxx~?mF)}?%MC#?pp6!?3!tpY&UHeY$t37Y&&clZA)#lZRxfYTZFBT zt)s1pt%j|PEuYO|y=}c@J!L&a)+5|(U1`m>PPUG+##jefJ6oGuYgx-#3y~cN?y6VS zGwKm_uew!Tqb^XVsbkf6b+Fo9ZLQW*E2+g)mvUdZuAEnnEBlr0%6et7GE9c zUP^nVky1@5rQ}ht<(B25iL&&wbh0$F)U=ef6tJlB9r?0+ znq)}qCjBC-E$2n&N#{Z5PUj})a_3yK^FpdK%GuA^ z$=S?V(^=M8z^OX!I4(O*I}ST`dvAI#cu#l_cz1X=dY5`@ml?Y} z7*A&GmqB<{18o252%N~6v>zt~*e63HaD0I6+ntT$0_@|T%i~za+D*j60&MTn z(>Nx;_S`ItqXTUBT{n(mtoB+Q8DJkd7vhKj`|!ITad?33tUMME4X_;-I^nPYdw=*i zJS4!juQ-iE1MEHN1Rfk<+e&Z8g97Z`5(V+V0NZl(IDV0_LIv@F0DHSwN!&lcHn$v# z`vushAQkrwu(b!a;y#S!kHEbHY|WzYajyV-{rGYGLV&IO^C0fY*x+-xM}V#P^ce2W zSoI~i8)MbFC-ZB3yy7x3A&yjBT!g%Q3cb1b&vW`Dbuh#$HLo z&oGu<2A5%M?pwGtV{^LTQjE>ogG(|tb1*K!*bE65XKeZyT#T`)_i$0hrp&`d7<)Mg z7iMhIN4OAUnT2pc#?n{g0*s{<#`zhWuo~xMY9R48?ckHV_%I$ z7Z^KgML#ljcq%&2*dZ4>$Jl|3=qzLVqtOqHef%9d!`L1>`kt{}5$H5yA6!S@G4_5K zI>p$w4d`3O-j&fw#@?BPzF}-j9(01S&2!P$jJ;I=9cS##dFU&~Hs(Rc7+e1;I?CAE zTj&U5Z;U}-GPZgTI?ULrCg=;sR<1*b7+ZcHeI8(k3UtHk7|ZuDUdveC?)VMHyoc}_ z#ylPHYQ|h2;8lz{8{*d)vv0sF8MA(mS1_iY!^;^{rs8FcS;pa|jNw&y31esjUd)*E zE`BY*KL7V^yoj;;AL50K{j(o0VC-HTewDGmo8$S6-EEFvVeGFaIGeFMDxSyKpB_Ay zvD+Rzhp|6YJe#pw`S2{pepm5K#%?$61X1b`no#?Akdzjj>;6;Hd$&EMYme zF&1yZR>oqpu*z7>b*wNJjj)BW$cb2HEc_3Q85`=sh_N9UONI)GT@9Z zOA^`wubqcd=i<)-WrtFZ;scB&{fR$iEb$AxpRu?K_!Gw3#NvI7wfYx-%vj4AcrRlu z3gA7AJwG4sW~}Kx{1IbK`ruuRHM)X7WURq4ypyr|q4)#F>b{M4Fjl8EexI>g+wgYA zo-2*tV=Sl+-o{w<_4r-Js@23>8LKi1zr$Fin|KRj6+7d%87sdAZ)WV-1Nbe*N`Hbk zF;?Pj{3c_?^Wu$+6^+0f7%O-XuXi|#N|kU$s!{|>V5J~-C6lVS)#PIT(-=yG?dShcix)#8$1D5bUjDb4NP-ZavX7t z^0Y=@qLHYSv|mc_zgv=HZ}N_vR`ro*$N?Ts@H@;a$WZauKWb^_;qG; zPPfOEo?t?0PP_X4UtCe3V7((M2(p`FR1=pMWETcF*x~@Vq#(OFdjD|=K^2#?;~p0m zC|F-{#RS>S(Or&<3UWlwo^D)3pkTct3O|8hw$_I)%SShGfC~wkcJ5CfB9o{|!YC}t zfeVV1toKEMC-5=z#REA-IKL3V52gd*d;$gQ9g$a%-5g0cIFBGlViu>fnoi_ z?g7K<6L{hQ!@5v=aQ(8!Ta_$l+tnh-5f8LoWkHSr!#YRcClIW^HXe9*loPo=o4zfG zo^Ej8{U=PCEf+zdES}csoqTQ1n(H{2ydcy7#V2}^$zg%_ICG%c-wnhd7F6~ zdh2+Dyj8sA$=GvoZy|49ugh!oV$VOGJD%S?*F3*?E_i+*qtRb`j(9%z?Dy>P?DV|n z+2VQAv)1#vXQ^i)8K0izndX_~ndo`Rlj<4niS@ADtMmpl<*YxaHjnJS@BYhu%l(`Cvim3ZS@(DD6Yit#L+(#WR>Ftw?e2Hn zo80TjPKV3fi`=icXS=7nC%Y%Q$GB5Srb3i^h~-vPY;$aOtS9*%OC1Xw za~)ZZ$&QI6?<2(#?}%~?aSU+uBKaR39jzVB91R?`9Mwo3NEt^lM*)Y&VRK-T4|3an z-G14A!G4C!5jkc*WZ!S!ZQo(vYTrciLsr@s+vnS7+o#zxNuJ0kdy+lY9$_DB??>`Q zI@{aZTiTo0>)C6PypeMDQuZSDe0G;zB^e-hZMSUKY?o~3ZKp{l$PwE?+dkVa()YB5 zWQ44-Ew?SQW!q-jrjX2#v9?rOqAkWY)HaZ0h;+AgvbD7}w>7fWA(#eJ-ORWp6bFEnM`|@ zx?kO`?jRW_o7A=HN_DY1U!6@dPcqf<>L@iyja4H^21-A*r`lO?Ij3+bo+c>n*D+ODzjXW=oc3vSp%Wj3vbqPcmGFSO!>nS-M&}T3VA#mj;$v zmTHy?3fc4ndjUOwZa^2H6VL%@2ebiN0aZW+&;lp}Vn75aX^8#>ybt&f;61><0q+9- z1$YPWPr%!Ne*oSB{2lNn;0?g*fWHA=1N;^6D&Q5s%YeTCUIP3X@FL((fENIN1UwIT z4)84C4}fO?zXv=G_#NOWz;6Lh0)7K{0`P0Vfj<0`39a4fqk@F2D}~cLII@xC8Kg!0mwV0d50)7jP@!JAhjN z-v-{G_zGY);5@*&fO7z61I_}R2{;2V3vfE%G{C8VQvhEEoD4V#FcUBXFdZ-r za3bIY!0~|N0LKEp1ULq8G~g(}k$|ayBLGtXlL3F~FjLMF0x}76L2?SO73TU_QXSfO!DDfF3|MpbO9m=m4|>+5oM9Dxd;r z0h9qTAOe&$l>P<05BLw@J;1*K?*je>cn9!Lz}tX-0Nw)p9q=aL4Z!PwzX4tY{1xyj z;1$5jfWH7<0{j{9BH&Me7XW_*JP&vd@GRgDfM)=|2Rse<9pEXzZvjsNegk*{@N2;1 zfL{R~13U_N1n^71!+>7^9s>Lv@F3u4fCm6S1>6t#3E)1!j{)}r?g88l_z~bPzz+d; z0)7Cv1Mq#o?SStAZUcN5a4X2CCEyCc<$%iomjW&UTnzXc;3B|z7!5{iFiL}w8l-A4 zLW2|yk~K)uV7LZ}8YE~CuR)v!u^J51AVz~|4WcxN)F48Ga1DlP5T?Np4MH^-tid1+ z25Ru41_LzcuR%Wz`fAWegWekS(%=ORdTP)^gYFu1)1a#cT{P&dL5K#OGziw9qXr!` zXseNP~hJ6wn~Q2Kh9|t3e(Oyc&2kaBJYwz^Q>l1G@$`4Xhfd z8YmiAG>|pGvMkvhZWZmesFL@t_m=k>dHX-_JxwynkC1o&ecoN(?cOcq&3}z|xp$E_ zo4of=A(`c4y{Y7_KgK)MJCJ0UclUPkw)HmmHX?8QHN2I)WxXZH`+gp;gJhiFCvW>V zJy$&!J!i?g{&CM?&jHU~@}|FyWT3D2tRnCE3p{f@S)R!b$$r;RL-nNR&G+1Dp zYs<1twoSB+Au|r*ZBe!%wgI+YwytF6L2FwxTLW7yTQyq+G6SKQt$@vAv)Qoq9+`=7 z-Fn%2!FtAe(t3={NZ4=PZQWtrYTaaAOJ*i4w$8WCwobEVTE~+a3Q5*jYlL;MwV$;o znW@m;+S1y@TF+Y3T7}G5C}k~T&1ZF4RjWj1F5FVDsh8CA>S^@^nZa;S-KXwSx2s#! zjU?-0xw=TrR%fbH)O0eVAyrLOW7MJQK(!B<+0aRCt2S2~sddyEWQIdowS-zo&7(S0 z3z_L~N4cq7RW2%Ll~ZKK!(rusvRB!uY*RLqnGdU!rOE8+aJVea`_4Pgo6f6bCdFCj zDd%zLVdnwoUNWO%8(HCEy>pdwsdE9DS&`+O?40Nv<4keJlNlC6oCBP_oL!wAovq1C ziw4eG&T7sI&N9woWX6TZX>(%7J;!awbu#nfg5!+iq~n<5kYm4Nw_}H6t7DU6tz)HQ zF_}j*+cC|N=@{=AEUao#c*nN01pf{oFm>o!#x-E!|DX zOq`nTD(-UbQtl$|d~TOp)t*9f9zZXk2ha`Z0(1g80PTP_Kr0}%puqnvfHEKkM1auB z!_dmZ(8|Nm%EQpg!_dmZ(8|Nm%EQpg!_dmZ(8|Nm%EQpg!_dmZ(8|Nm%EQ;SU%|ft zUIY9U@G9UHz{`NY0A2$88Sog{K}VrhXKC;JOubT;6cF801p6u3b-He z6Tp3d9|P_M+ye-$JPfTo46Qs2tvn2^JPfTo46Qs2tvn2^JPfTo46Qs2tvn2^JPfTo z46Qs2tvtLLe&sE|O@MC#ZUo!_xE^pF;99^p0M`Jn23!UBI^asc6@bvn!_dmZ(8|Nm z%EQpg!_dmZ(8|Nm%EQpg!_dmZ(8|Nm%EQpg!_dmZ(8|Nm%EPnaS7rgu1e^hw1vnjW z8sJpGDS$5nP6nI=mj2gUtOfWSU`@avz#4$n0jmL41*`&C8L$#y zMZgMxCpz9|7(H{19*_;0J&^0N)4P4)`A6Ho$iQ zw*tNcxCQWSz|DYf0d4|(6L2Ho2Eg@z>j2jRz5%!fa5dm6z}Ep+0Tu1Dp#uM?;(k&)fdsLr-w zS;ca}g>IYPO|xucT1EGe{LT{l%=p6!~ z1PGk~384h|?z1b|+L`-)*2cduebf9=JUoz!u0{aUu{e86=m>B+6>j@)$f4a{(7_e90~Dw&&V^O~9S`!#y1rH=tz;EN(@o6L#Q+?Bb$m{Zrdu z$3Gc^9Ra#C|9)Y|)%9=L{C@zt2wrcwAP2fzF0euO#_jow+pLop7pn8lE$XH(+JEiE zJ^N0_#SLiLw3G1~uJ_BW>c&CszxL`Lf3D-|`nPQIKLA|>uh%!{7I%HKy|{bV$zR;Y zoxHeEd2()1=lrex*IwKmPj+0~fR>Fq8L#0Q=iI8!Uflj`ukM!bID+P`JJ{{iSCcs)ILPR1pt|Jh#L8NYM{UH_JKJ9%-T8t)v$PCKam*IwMI*L7Un zfR=SS8L#0&@!YCTEo%R@S9jc(9aq=CWx)RcbP>Fsa%gUGryOc8?&!RM*!^4jck<#w z?UuPko%G-KUwd&!Y}yfW16ulZGG4>g>A6*%cvkzby}H!X9aq=CW$pg~=puMMq3zJC z6DsV*O-IpcRjeu2dO)k6PS~Jr;NWp!;OhUiU3; z>iTNe9m_63=C``!$&zhx8sNXX>{E2l|H#*0j@QETo&eBxn&&-aP^dvP2hR_$YX8-6 z^-kK?c|_U2WqfCHOm1yaH|T@mxy5}j++N)K|LjPU{aVI#KHwtU{P(tLo`1Ked7ky= z_xWoZ+qr9_PSAU8lIA^I(wy~jWyiJkZyD3MNaa4zJCEj&`p%;^QlI;*?UR(0zj)3devP0*tjru+> zeU)3=OJCV*tIdnF_iq{1xk%-%&x>tQ*%u2$Wvgz^2i(Zc2V4ZH&%c`k-1G0+fSdD0 z{@O-#?%Js1^IRL;o+|*i1C}1wmOU_Lc;_OO`#sOJ0q&UsfZKPYe86qr`GAWc_35EG zq&_{=M(W-nP94^nYa2Xh6q~jGD-^Z(Ri+jAv zUfhIK$Hnz)8QS@Piy-yUwq)X?1(J!oK9aw-A)ULnkqoJibjiW(5&K|_vvxkG|w8MXkN6lU(2A*U7Jr| zcNl1pThjwm+kfq~4cxo~Qqlj9`G1u~rK=#fzh6md@%4SK=`*eO59q?5f*$&ddQCu8 z_PML0Xn2!UHlY<%?YKr%oQnq;Q6?|Jm zvLT**+0;&0TB06+%f4;T6#`gxqglZ3F{uoPT^29r39IcWOf)RPpj(0YB^~m~;VOaR ztyT`DJUE?f_`iE7Wi%#RJY@x@xGbRu5=|`*I)l*KU%a%Ar+D|yAhhT>zsa4kTr$mX zQs*tVgB~rO*g3Bag=&i@bPg0Eqx{Bq-f}xaVO;0DHWb?|9@{xk2!|z$$8_FuJ3?V} z=e#x)3@qNQbD$88;}!4PdCTnxgc}jc&E-=ZbvBW*g3Bag`0|Z z=o~17BSpodI&Zlhp)j&@UK@(f6p!c}D1<{R#lt&qxgDXfeP_Hj63{3f))`QU#v+Qh z>%8T5gu>9yd2J{HP&}k_pb&Q6iwAe!ayvqyqH|swa+!+bn;F<-T48=wDw4Eg`lFxhT;&qsQW>~Up})w>_v?VD~@7;;*H7rSYvCZWJau}^{m!`nGIr%joyh@-)zl{ z?Sz%Lx+l71N-I-I|LIh`y0xiwacgbYfwkqe-Q3#6nX<-MDpucG+oR+41Bx>xHSwm< z)$P$|$Nu_AT(67Gjn{?#{vRco-j&Jv#$-Ct6rb$9_Rt@ER_G7POEbOF@ump?(yVx* zrZ%*q;Lc2sSSl4;G-qCXQ9AVUnWdSYsdzeZDEoBqTBd8F;ox{>=#8!`Aj0-iEg-d5 zai(WOye7ssxMoRa6~F#OUESDZT{0C~;&uXXZL@pPWX3E>xD74&iPVPZNraNG^Hv+hm$Aup0(S^f# zs~HX=S^)QGv;Z#R6q?PFDg ztG25gwOxGZp!u=7V|H)ZyHC;LvL#C9*xKb-Pj#ZEVty=@h|R6b1#Ghmz#)+Bzh1fg zy)7D@uUt^Nchkt;%c5NRwJDd#$67Nxt;kwi-OeSM@*tZYkSd)c&iND!L*>Cxh_m_93vv8CCT>?&}UZTqiYjVI|tr*>RT|CT9O&9=XOHI4DgbVWEsAIW!q zc|&$_IAT{X&dc;+d8MxdS^_Mt)A|$J!~7i%1j?=Ii*?$6?bU5MARlzQ{|`Xd!I8`@ z>a*M1f9=KfZ0xwWel3%+xK1p$4tb-wHGR5e`>$TxPw$P~>8ooxuC0H|q|O9fG#!## z)W;9B|JsZD+lY>f>(?@|^8pt@>PP)^Yx}6by|!!D?XWgjLOV$R;$~roZ{dBJrc_h1 zxv?=G_Pbt%sY;x@;7e({JOUrOI#Cz4T|eo<9TnH7Bx}3MWgiX?rzVBPg}v4y+v9aJ z3fcNM!sX2Q#OZh}RaqOd-ajkN^gX0Go?7I6Y8QtiSQ%PEuv4aM&Wg!@G`O4E{lP;N zmTqwu)9rfJbW~lxl0wUL3$RgGnpsb4OkHwr{%YOH!iRJh7iao_GUlWa+i6PAS&(Q7 z!{|qNB`xa9&I$f>x^FjfVeG8Gp>Fs<_ zms}9xgFWF@N{4@b!OgmRrC&L=#PHNzN#R!yF0`>KE4<_Wi^s9Eu^@5;3T7;740G;X zU{Fs5@rEi&1BZ6WtO4p8Ul;dCPLElHsNEj1`tWPw!hhc1B7@)_%1LfFE|y%Q3cdV- z;8UAlKOJ$d5VZ~j@t81ZDb93DG|b6Li_o+4?7-ErA`&=8?BG9LGTmcURg>Z|ghE4~ znp&LcUX_ZmkV)`gE?ZU+p@y9yrK{rU%Fq{j+M5~5qj15tnZ983ctaY|nmKhzEWIl9 z;$yKb1Vq#EInAkX@N+CesP&0Zm?zkc@qdspspTrJDuN$4aLPPo>zJt<%(v^#@_v1K ze0^gi^oMApL1s`m-E#`Zhqv?N$k*gTI8qJvwB8*2hhp;`2um6-8l}W`5u|P!j2>EC zmEheeCN>sZg6$uIFoy}4k5YpFK06$El#2iUvyj+)2WOqP1tD2n+;z1Lm*B4~Ub}Vy zlG{aX^WZ|u-3#F)A)*cyFbIw^@poUQ&!)M=&e&L8-P~B^ynM0<{*~z(t0WQHLD&Q} z*(5=3QD}Epz{**YznBwWm`FE;j4}77spkG;-hI#CmAtoiae*X5QmLKpST-b#VFtM) z1i@z%C47(IAl}Jy58K#cB)Eo3!r(rE$(k;iRq?ISb+C!1#j6r2q=CY4f8129_e1d4 z&z(b!#5$NhZSps&l!MTpFQfa}fSypkQWx&!sT{7kP{Fr1_I9>ISVR6g=;!jl(CpNON#TQma&NLW%nvR4 z;VuOX!AFV$tGV1Y#j-w1d8BAfcl zY;C-2skC6-aR6-r5r3uDaZf;7w-F-Cf4gT3U^e)c5z0Z}nnXHiNG=GOr*43}lPJu{ zXOzIqnwJRMfP+jO1vyJI*}+C_@f+s19$OHo!D70W*Mxuay3X4E0Io{Gc#QZhJHdR+ z<`P5P275Rcd15P%Ssr&O>{Q~ud}oJBQbJ7!%~rBMK!%4PYdh?g1%KRLxIqghZe9j4 zeOwmnU7{0SfK& zO|(Bk!R2;TcG-wR>z-v9nZd>e;(udN#g^@HD;B>sS?q4_j2MxfD{W)a{RCm(Zqksr z;-CG(grOR|C0vAhAh9~$6p6-e3z11Uem8}UTiT-C`-Egpp=cId6deseT{u$iI;jm_ z=7E-G9|{m*9$1QYG1yRxkQ~M-8NSTrxZ9>Dqc*oYRe^JXj9<XWU{q#RpTn2~>Yh`Xi;RZdp7AmWgdhsn3Z0F>S^{sX?Q1dp@;T~={+%Hjo_4xwM4U`rS^!64M4IffQqSyC;kk!E72`U%@J(n$= z&Le2IdSPeCn~UvM#3WL>>{?AixuI=~;quaZ3TDoNgEFgB*2U6k9#2GGT=4F^?1D#E zR>srm8OeF!(&FHC5&7tybL}-(4gf1zA?ITREA?rE0sQ}+!f@EIfbeo_3E^^!u*Bwa zf)CEmhWmXX?DV?kki0=Twa*cD0NMD3jfqq!6cxNlwg0R9ezJ7KJ>UKq87T%o55S~cGkvf7Wa%RHV$q{c2c zaVQlafOJQ3sQ}W677@3%v+Uy)0QWzF<4wdI#vQS~LemV;8n?n?r(ny1(Lg9M9X`sK z+&CTieBOHy%(Qlo^aC}-o-tH$_THz>qa!vQ8{8ha*z) z*E{S7&4#t91>qkY#?|fL_~zz$=Y}POju+%LrjS)NzR(|hQ0Nc7HVE*Zg4A`G=V(@$ z_fTPF_&@!78XTOu%7~V$@7>8w)cWR+aAXbC21XkaY?ei2V#h`9R~| zI|bhRiU=aWKj;B-WO}?Zi7LZrkTnWp z{AW-$LhRA@(@P7`nfs6025PUhUH7wHz<0e#fOVNZ;F)P1bVCRe-*bphQcHF76k}Hi z>t@{o1oWj97DAC>&$jxycq-CD{TI+4OV|Y$=nl@&g2s-vZF%TQ%OM)AgwH=jEaOM0 z0%fhAmFe1?u8YTgGTC=Rc5F_sMGPw4m`XG>Rp(>Uouru<`A+7kx*vIj=Uj+lZ>T5( zz_+&h`@X528e)G3%G>{d*`~iQsO;T+h16m2AP-vwo5*saA33c*2PhCTXo#Ta6BVj^ zSe)qgDP$a+pbYlk77Tm2i*wXDHWf!Fde!K#9{btwWsb;s`r^@GKht+wl{N2hu8q-~m=?@@?V5qT_@u zI8XEPZxf} zr%(bEyQoUjdEZ0Kimg(a8yzph46Z?FMikZBRkuDeCMx+}C>%oi%*e^R%?c6H?FJ$J zpe&v33%&IxnM>RQt5tI#5Z)4%pspUSrInHTjbia9y}74SAMTj~w#i>D+vI&fpnV%sNqN2bX~c$zUJ)p*!A79$ga|6XSj4WM=!*l)AB6ygs-5O&} zwTXu6WN7PstiqjVp*Xw+ny8#NHL)-}ekrKRbk8ONqit(&OuLPP$ua{Yqw_x)oF^Z0 zqoFw4K9~QHdkQv7+nsUf`Dbj~p5wK6ktAsz&iH&k@Z z&d|bd(W@g%hYhc&8eB0L-=8~b_^?rxqecv_9ubSjs;jF;4jDRPXl_9#jcVBk151}q z#Xe)?atztb8&F-DY)B{TaQ;%;yv?g0zcsra{Q8+*L1~T}^XHcOq1clrqYgHAAo}tS z#qRLU6&Q-$@hw50CGo$=4AWrXl6!e&-@!J#oCaMFw9FI{CX|>Nn02!U(5P2x0fEaELwJb zcJ##3Pqt>ptoXWHgMB;XG9y~np=yrxKA)$OT;GeTrS5ourt&bdqH9&WE*?JTAQ&!W zj~j=`Ih9K8BlVFvNR=_s?_OY~cfpmI8sOpH&?)#>-ZK7 z3-Og{ODiZM)P_L>-4p52jg3Aln4g~tj?0w#!zDvk)7kntHn9-nru^Xu^cEuZxHZ*J zzYiCDPRaE2pP5sIa?tQ02%av~D=*6@fcCRnf(=7^&bL)}6Hkp6*QaHR3)CSEm?Kl# zR2yyybeke^iDgefQ+ar|A7}bDrjqrEbbLl~{K9x;|F{n|8mAK|b4 z2x7z$v-v1=7!&Dh@TSEUOpPt_ZC9cDyMuSBvEwL)Qgp6==K~6stuY>ikDp?u5Uv>;*Dh{V1tYJpPxiQ zK9E_^x7jp*xiFb$^ABHF2t`}-=XU1)V1s~Ci@oSKGXp@m;Nym>SgLAftS$kc8v{(I zHAlJTmrUt`SlHik7%o=clpO7kRSNM-0DfU*CaA5oCn^U=6!-(TK0eAv3j94=7v`cO zbA7Rx^#tH%QNnnE4{_Q6k_`nZ*}Cg|C}2D`t2znBh~+#f81rJW%)g1hpGh6h6WLWa z8Hi#$*o)v{`tWB)y%`)kwaq_vAcaa51hg;KQ3VL?@S2_$Mf;xCIMyX+UBOJ z$XK)BLjL-L`Q=7|$xFqaPUfI-7=|nu3HqfQDwM`0QsG&M#Wy~k>WYUvXXX@mrlcx#fLssMT4l?@Fu2njlC1}C)+N7M zeRE$tD zbPQd8@I0q!H<7=_eUIy`4e2g^Jvd!Z=y%GYI)DNcqhEX#@U&zy6k&7kqL4INABX5D zIj8VZpoQuw3|D{*iwuIs7+&UyK7o1_EM~9fcypXgmGVsx^ef{y?t|$9MsKk_pp>7! z-94*()Zk|6Te`mLZD=>+ggO;BsBMhF_`*m2B>PAc@*nx)%k3Z^L3g2enJ+;_hfnln zsK4bmP!&gSVEPs%<;nParqbN|Acv^U?7E2f!|R+ST=(pH$Ptqmo<@jv+gulbqPCfI zz!iEK$g57ZUv(RM2>sKHH{h7E%U+K4OeZVnVUie`td0?8U45Bwc(%4Xhke>%L>Ae_ zM0OPkj*>%5Q9Nn7{IqB6poI0wmGz%Gj;0+*)!W~ z5Vhysa7tkp0G?4x-o41d{HA6#wv=FJPL094^rJ9UJ%kse5~$D!x2#~)W)xzGSVeVL zfFKMZ5%fS&C_W&lb0GFg<@no7i@KPwWj?nphps}XJ(h)Z)L09C!$InLD0;?$2Gq91rHYgH0s4J}d}umjbSu2we=5yLk$1$k5$xo;#pE#~ZmV~vj)yws_!taoyS9ueWbMZQoufxZh87 zCgusuOQ8rJQJg$m-FV7&-XB-o_PW5+Yv6yX?obcn7af(LNTpMC+DCnQPj%xhY?5kD z_+tWKjfQL4O=*uwTr%|+q%%^1q(2uZ!2}ABU@RjBACduB^OaJtP$+(Px`N#wYzjR= z(a$Kc>GJ{d`SFxLy)m@5ueIcT316Ya(@lKd8}*UhyWcUZJ3vy562~rFZ>TX%w*!K7 zjYy*UX&-2#Z^RIs{7pNYdCZ@}q;o6Gy}ux7oOKcPX55yFViW2Hx`4Tn>t2+1z%xv! zyW2P*cjJ-*_1TQ=gEIu09u_3vhng`Vc_;s@`+*Z|P^roC8U?*iaD&lQaJ0a7ks^cF z#A*XBB3#exl8Bl0gj(whGERcyVL5HiXME%)t1qM_#hj!bxkWt^tjCawLt(ii8YpnU zZZGw7Ekf)FtEbGz4#JVhCjknY_t;A7iC_ax$QKztmYZR#-6s3?Uj;7&dvkj9$AL3u zbL;qN9JxdS`ZF33hz|kkYxY0 zScfjjo1cFv*T3=nOTMmtvz|E&=GWE#^xnvw4?YrRN5L*h+P|^%lPl1_(cvX9E81BvemS^FK(sdnld6fu5p-mk zm`$DEPLT%^SFTK^jl_*$JBg(}VjBl4s|BOWCx?Y zd!d3u@V?luNx;E>n0$GeGR_bMpyL&N{E@xt#{qDhT0QwwkZveG zFj(z(qMp@#GKJiy>P_Esq5#Lyl^&tqlWWEy5;KrUo6mRcRu{gWF9u<0=U}pcH;Rg* z(Ll^}jb3!9uu)|(eJPd$iJK|p{lQfJk^_V!SSVNXxI(~<6z@1-IF?SLggZ}Z1P`kB z`=cPZM88yh7!v`QwAn;`0)bbd#2wwjp8Wl<@yj2I+-XDkr0mWY1nXy58zW#_#KQmFC0mj=9S2>5ZQ@n!O$?zP zM|UvtBWM~~+T@zgU?~CUV|*!Y0%x%0?;XBmKY z$=q!PiS796f0OO_VcP0ql$S*&ins-e$j(?sazSwqMZ7l_C@)-&?2%-kpYS%O3Eir> zLtItkup1`fe-2JFs>-(Kk4siI*GC66e~*Q-_+$#Nq@?T4QL98@6nz!S4CS7KjVYX9 zU9eXLO&mbMZT!zK<1fDtbF#Aq$O0xleM23{yD0+$nz$jKcagaclh!qVP141jI`|3o-L zg`@cV;n30cLEkh+{AIp2m+pGH z=~`A%qN^3}Iz|bGRskws5ldLWy=5ti59pfS^^JC#+1$2aG`8jcyL9PWg#TOl4-mMw zs$~wcl>NJx7nOG_>ei*`hi<<%OIhFU&MzH!d)o$gWHXic^_j}_`YcoV%l2E}w9_as zV!=%1#%$7D{%2b=6FO)8t-(fZvLTwU97;(zxQp{)aJRVrA!ScY?Vt=Y0ID9;ENb$PcWtGATa&V5)#627vmWeokpU*ZfjvU;3y$e z3^YP1`fo9>$rVFJ(68+q79O=-2iBI?b_@Q?vFT8e$lnAXlOlAEY4F5z70e<+=N4dj zxqwF~6t@A300py55CsQuO8l*`;m~eEEs5YE;Zg=KQ2mH1I%;mabwO!B8F3fSQ$&m2 zI;!k$#sk#q!C|cwE&aHq>9!GQTnm_>AHea`D(oAm#P2Y=reKEP?Vw@V;u0uSpw{re z`RD#aFFROWifK`Ksd;R^!r4t!tz%}GHe%0K??U98qH|5!{EM^f=wF{H-ZDP>_f3`I zb~%K1$pj&XT1@)-Lvfwhp#e^fW;RhZH&4$MFbL9|ozOr`*(}(f%8CaS6aT$lc{u!xmyo4pek|&{uDI9lhAjfsE2}d=G zAs7W<6gCY!?4v|*10|W@a{l^1@xMMqeDzLo{T)Uy?i!0>|0{^qJ)~~zY&o$wFqmU> zH5qW&iX+Hj+AfY0jSO%aiZ4)$;2)eD5dm4I*f1KW87cZ1<%}Sb9Ak?ML?=-zMkI+Z zXkwR-Q>=a~|NHltyBvJIOaO4(3-0|x0r7Dwo+A))4~qA#%_Ee7;NRIwcpRW^;21)> zpfgn*#T^Q%LL)4G3XN8Fw{VJk!{E07wM39#(WpLZ_qjLJ&-Om9_k`ZX zy>9PS*K4CyURvdZRd(w6bNdu6?MsZ>A?*Z=~QI} zT-|I-&(i;xo4_4^XgH>?ZkwB;h<3zu@d?@YEbAMP5X4->`grm2qe|1u{$b?&o8#N2 z;!UYV#m6n*nsbk4!*biEn=AeB#^RRoWsAEn@7Hs$Xq*3t`t0IkN0%+`^6TDG9m7D& zs^Vj|FP*pSFUW-&;>C-X3v~4{^kBssVhxq?;-i=Adx?fLW=z!;A2qBrvFxj?O8Nn0 z#Yc`TJ!IJ)@==uq$<(}f%2&J>AF*rcQOo||{6u^~x&la9xCl=-)z=jtKA~)J&*gnV z+g2;$4fESxbJ*@>IAds;IKyusw~qGLZ_3WlYJbzhNo9-s{Mt3eQ>mm!mS56>9ZH**{XOmMkB1wJ=Px_|co6&Z zbSiN8dv+{pHpo}p{HxwjlSm_ZoO?slE~Q5-`|`6($h8&Z9#1bH7_-m&K%+kgtD-uY zs*h!H+gO}hp%-Pd;kgwZ@+&~%Pm{uw?Y5;fEtEx6GruxNYt_rgH62&uU(@WZp6q(!EB2zMIL^q(zNqTg(~)0M8mco^lOxH>6mg)q7O#a3*8ZSTs0>L6E!#LqIT#W3>n6EDScrj+5-#9#lm zj$L=f2mX4V^AKCwcvgJCioI#+IY!0%uNdSzoH0|p--^Miy5q@`#rv+<%i6VJj=W~C z*d{?EOT_R#EB30`e5mO*=`d>rUsaiP9kN6}bGconInA^~_<(32;-&2>YNv2_dSH+Wq z8sV1hwcG?5eOm)g;K{yhY9}l$QJ)1pmbRz&zkL?(yi8gAkmm4oah%3PFF%$k_mRRq z!>0oI5QKIP9)HII1^VD+v(@vJ>?u)`;qa##Vs+sHr2qj`5_0|`Hy=gidUr7s z#jB`@IP%Us(B^zGJi%u028YEz`Q?5*@9DEj1kPgCP4Fdu`JMdoPn13!3MWg`^Ah1v z?x;cP%CagBW8!Eq-tDSFxWUzYK{qjk25XVJyQBUk>r}hvs+I7yI-C zL>Log)fj??iSOxIiO8tb3Y%+>2943W0F+8|s)R`Fnv=r$dva^oz#Chr`30pZLK57K zeUp)lsG2s^MS!!82(bibo1n)bB$P6IMxQ0dvJE(_YQbH^REI-#QdwQ1K5_)vYc!RN zybDLdj_QU-0%}r}knX9TL$-#}0Xp*ifr3(1{NBDjkV4ZRE6yZdfJQtb4sg;R#pEyM zw_OqF$#YA@9`aRaCF$n+5d9trDkE)aD9y1T3L>!H z8^HByGym367QdiJl49&KDyVKNkVA!qArg?twsZE&4Uda<-~|2oCf82V=t z*5FSTNIX&*Ox#_R#s8w@>@z|MsEPEwZSjlzHPIcx;~eQ%nma^NlQCp=x;hcL4o3^p zzrVUra`Y1g9JGc|apk%z0f)*vierbu3;rrOigqXQjo@L5c=V7n$PdYM%|-S@VyL&R zuzyR{%3lFtVk^5()viCo4XV$4(It-*Sx{obo4(`MUin{sfGI zb^Gg?Uu?~cUg1@@V!nIM#E4ewA8PCDlkD5q*i|OMiCi+>BrNWrMU>)VW*7{#@eSeQ zkzi{v3%!rxokP(!B~FF+J)PVS2rkQXhiyA9>1!48rKXr?9#rJBR(o~)ftGp;e#`vg zM}_!#L-&8di#5DSv_e~5%IK=2;>dAGV|J^rsG5?j2@lbjf)_Q$B1OS45(&l-7U32c zf`Wc_4{7Ja=rkh7{jeXpe$+cr>u9bbm4zl0-Qjo+6Ts((gQTufy$~*M?g;OAL#3~D z+GFuY^IBqki;(`T&MS?P4gWpB3sdMWi|no6l1GY@RsZ&{?&hC)g$ z`DklqTxYDk)%kAP%4P)g>suq@%KZp5GE=W#8Ap3X8Rs8&L7CN1`$|{J!0zp?)>BWH zi;vCdMp)Zj*i8_y`H@uku$ED&!%>FVhFzxsqlva z5jzxz5Aajd-7zJZ9=WLx^WuxbLh!EAOgSnOht|dy<|_{O+pg5>pHOD5?ggNpd5rF5 z&^haPavuV-G){DRc}GryaF}@A{FZ}YFs;5s9KAAh1v%R16thC;_M%tXf4wj|aZM(S zzWx5xZ~pw$vIwIM3}NKI*_s*K2`g_6u3G98L_`s0%~6E{+ry+|1c6vIe#62^A(V(4 zdflPfm{G2KQ(T8&X*IxCmp$T$$@IY zQ0~PC^9!XGQR!}yC(f@H@IrqPmp%93294#TyUe1nQ37(l$Ixqnu<}AL5tnfYK?&>e zcCne@V+vNckxnXOumpDx9Bg1>(z<6o-x0t2b92DJxBO+8xo6D(z$6p40?f2vD+oSf zP=Q1qkN=;vl*W`Z_7&{2Z2CH%RI`NLF`&?{q5G&v*N-v>ixUQo?cN6+O?EE=~Jj83-USzQ@`QCQ*n3p4fb?iQy6G0u6xslqKjO>yKE zph>o39}8kEx1~DyV=|6>q6cQW^-C=z{1@{pQ>oaZIrXt{K6=+O!Nsnn8zt}SVLxNh z(TU-12h)CDw^ZQsN8pWb>H`IbRblc|+IU`BYMTk7*&L=hL(NXzWMA<(rDFaGG&6KQ zAY~ZZ_u8GVykVE_P9dc4QQuzEVnTOwsjYr`OCs0{aASKqR$0FFu&_z?c66TIyHp5l zEZ~1jIekriH-pUGbrNZ4H)h+w;9Qmj+(qzf0$RdbH6aQ7lC5yRD-=sFE~Sfehrx}3 z&lDZ{8O$?-Nq0a{Go1YmSmtig6ybOu4ylrj!O{7Zw}K0)1rk6+;IT2us!%PJdrgqj z!ypgFh6vMBM#q5*!uG&8O0suEy6F2KFco|g_ez~Ve4ZKU8vSlCo@z{4Ez(oNwc zQz?#-1ZJY#VJ;g(XK=GHRZ+~S7B`4newgmWB{M{Jsjuu0Z6AJ^Kz+SL{RF|MwJ?kT zN>$a-1Ej%%ajjrtMj9XcSVXpvGPLIVxPnh2_(ZALJq}tWvb_}xV$A!TWe?yWHTDo9 zK0N0D``z+tw&S+=-i0U$!!p=1+%?L2{sU|hO0-)FC|m-xFkvy#jye4uuVdJ}Im=AZ zz}skOM#$W36f!!e=t~iSY*rG>O)V?HgFAP(RPiOS_Grkgva5;5xhk03SgxpY6eLe| zDp@}P-LoMIzpgy9dSi2{CO$Uio0LT%@o*swXX84-97dr^Yx-dxUz`mZU@Uv1l7NGi z^K&HE)c!OC#)4-kd+}3sW0VLmyGDi4*VT<0!4V6jwRvROvfyh790o3+_5eI7)!l&` z;HGFQ^HHIjHWB)?sm!*d4-)T#*QDkY&4d3xxx0`mD4L;&9mC}oPB3O9>rfZUO|{)| zgU-RhoChj@aH0TR&=oSO@QS?C2MUl;?UOKw3FEmf1X600*SEQuINA*&#hdfdlELv( z*z{5IDW%-o#}zAoT1K_$!5{@n!r zQ+W7Z?v{a!GASIk72@O=?kaW>QXLg_mUV?;K5UC_o-o#M3O8sts*j;RDG1L6IZ*UM z;V*-(@?}MYWr9~#qU;9PYzP~Meb&QZeWYRyRmu7}a~Cy5hBW^JSl}_4Cxtmvq@2M` zluZ6ZxtvAkV6#R$ahyNPmO7kAbJplBXMn>AYP&}0wrI$g)M5L}EHP7wm_A;e|8 z(bg1eYEF~+UgK;Vv4u;JySv(NypwDDH>Y~C~ zLLiDs2RBG4NPh?fBjjLT{vM1d6qeV%S-BJyg9vfktoAR#qnAN`GL!i=zD3{YkqdEC zYi3G$rX-T(bM@u6F}JDUhZAs}*(dLV5V+JlM&0`CJLs*E!L;o8+tDXHfEgi<==n^2IO|+(5N|k_Wv`2euepZ)KZI*9ntp zE3B2h?pVR{{RD=PgIEU32-Hs@=9K;MVi~hB>dXqY#bW7cDH#8%0!d%VN8T@?hW-=E z>gXwG1si0hU!AR*p)9H4`o~fRuDz9p`v{Q`Vs}0RGm(bRerF{x-JVdrjFf(a9O0n= z*uBJpTpP^J6rQ`;^c2S|E%Eb1@fu?F;Yib3)D#Q0&y@P{PNA^WkbFLa|G#@{d)gk& zs@!B)Rgm5TDoMJJV2Fgww_e1P1ziO2*YVd$sm1C%uDqF-jw}ZAm9UN{+veVN%On;a z6h_;tW+w43Vo67FGbfl$?IldUM6L#91> z=;b+_(SuLT$bJ^Hbp@HQz}FvyXg^NuXk52k6d3l^^mt`+D(tarFY+UC5%#!C2DkR%d2)wdYAU6C zb3ToVf=sLcmirlGWNHInj2Vt0Xy|$W84!Xm|>VBLuR~ zRq4m0A$GVV`-BRKJ%CMqG}rMWxcRi8ix=V6Q7dIv35|!#q>uBV-(Y&Wn=v({Su2#) zheOsm8V3vVdqvrypDTlYN2nLN#Xs5V>N%yBcFi;R;r|D%OG{#%tjXC{h=%hN3cAZu zu8W0p=nBVmjTJh4n{dCw1f<~10+}{gSBzJ+SLP37HSok$UMQkl(^G*e{?tlWh zfm@{wzPZYTUa1R}`YOJ@QY!yL%L^#Y>pKAQvby3fBm!)6;xQ2uT1$w&fr5rEm5v}P(M6NQ zBRs}-nj|NjGAtzfSwda~hbZwHe5mgDLkF2d^IHI!`sSY_z6wN!q;!#r9Zi?|DWM)| zgtTK$&Pf23cfF!zJJ+CQF{e&NrC%JcB-DrO2{Vn~&WgfmZHEhlcA6BxcP9v+?Lz4q zKBge>q?wC&wSWZs46miA+fW!6*Nf}tLcLJ;zT9Jo1b}~38@f%{s@F(%8L6tF*0Mt_ zciJ8YV#kaSTm|$Mh1p~Qo3n)|`2%2<%I4`qbn}+&qJu(h+4UI@uKz5ovx_~7NI!9r zu>RrdQ19bpemzi!Mt_`}iI6?IU`BRIbqEe?7n%l!`ZbE8YnAzi%n9LQw?7z_qI92Z z{0TAmL^z6rVN$ZfcPa=gS7=b3JzyiWt?LAxoCgKZl(DN-%=I1!#Ryu?%<80QD5NjU z{is|{(Uc<2Sfz{|;Ph^mO?HO}lll^2l)bEQbyqf$7fr^024qoDgP6L_7dt3x;Loru z7zYdyw(J+e2smEIuD?lh9o5W~f-kj2z#~GW3==H7u}E+S`|+s60j7zMlkF_ByVt($ zr^qm0+wGy#T5C%`@t9IwA-IpyZit_lK?L~2+~*!B5WKy>#}h)dPRTLu%=Yp8AqlaQ zwCLd$(=gKG;zK)NCseW}ls}00tA$*obVxk$Pd3U+aMZQ8sYKP0Lo=84&D9j&9+LG4 zq5|$(;VJxG{Qdq)rJpPWz>Yuz3&2$>A8nS97#M(R?fky>+wlLVAQm&XInq>zS&Eb* z;1zWT%w4>xHW^l4zZ0_f?)J~oPX!nn9&KyGFiWZkg3(l_26KhBkvaSyG4>&n9q${?Pk?2S5jBJr|+n*KK z+(vLHCR`DffNo<|q%zd>S>F=2id!FAk;kw9B+&g5ID(oQBb3W{hmGz>Il3Jt6B!{< zBr}NMbQq4qnssg$0{tS$1!kmvBjm+Dh3@(p*I6cNgwkDaKs!>u=^}RzHC#=yp!!6|a{9=L}w}0#6Jd1F0Y7 zb`fAll$)9oKZ(D;2khbJR91zPb;A|@E(0K#u>u_^0+7>Xq;Y=%)Kz)N^3yDCqXybG zGCubM)V;^LYIoU8Pz%5!gu_z;F2P<{8e z!c~oE#LnVX7mDi(bqXS8H)dZc!kZ6@-Mgz;vEov)N3f;({3x*TKqK9I=5t34z;{7i#CNM%tO z(W_elW`MP9a|`}1={vG~ z?E^+g4fJH-Wtu6xT62mXg)Bv}*ID z5@|ACDDZQjz|X_7YHKx_Wx5qohj|l7Zi)%BM=MkH1Q0zVn}>w@+)?`_XJJX9n**q#I+EVY3;9s6?V}S>RxzOx7ug zve3pbLns!v7p!`$xc&?0nRRSfZ;|x{qssz`+UCa|Fp`<PZv0!_C@}*uFaoUYZzT{}qGBsmpfQTC-ImU!BAvx&iSN7) zUx0Vr;3xu1TLm+@<9D_x|GqTu4nz?-*hED-QAx&V!p#;;@}MlI$H~3%g^hJl_kU!T z^`ka|p=B}PLkxQyQ=qc#If0XUvxfw|^b`uiq~F+V_b_cPBtu38J6bXf*Pd6LpsYuk zV#nbbsu|7}Qua@RroRx^j}!oVRTxCUJ{-WC!%pJm%Ck{N0w>6yx|&Kfk{J5_90v|v zkv62iH%IEC$dGzbbA;0p*CF$xWZ>gMY2r4hkjTjr***ypwOQRCO!NK_Q!*aI4IG>@ zU_{KX$}(`&j+rV{<#kHK-6Bwcet1hoxH4s1pd~_a3es7W^IwI3z$AjRdzUX$VRzpf zLCyYy!AX_L=5Rr6fUFb9KVR&*VJa`#MZkCsz?iDso1wP#r0Y&~XCbTqWvO?~n~A=2;V9Z~H@^hzCzJg~2&ei2P!^yca>jGwJ#d83DXa z7$Vo8Tf&UdV}3RL)TSUCqs-xN;8H3$|ESpa@&e}fmr9tlfIgVh{R>aeEwIh&FKz!9 z#}^6yLOmBXe0r!p1#}53t%`KqQZX16fgn@${w9xx1Z z5^I{NENp~I)ZXBrQCF&1*dSe`ESzuCz>#W9MDTv0^6isAAKWf@m}lC*ra2$?CJ@Gm z`hFfCc}C#z(9%o~=+mjGWb|-wcdn2kx9|pBoL;~ksRM**zm2jhj->|>9#LqrHafc~ zhdlM@)r5DN&i^|(KjY2)x0GhEgHX-=(!UzE93ETr`?TxTlnSQVswQao^uD1C4h zKp<5~N6H$jYk^u&Li9`@%$4QDaIZ2g-VzM`N7F)hM_LH~QRdeG1^F^*95kp$E)aw? z*RF|Jtd#$Sid-g36l{tKl~HD_1M*o~3Kk)y@JSv0il{_fr1m88IWL1>34%3KUCr!urw7z1EsmHXVAw~ifa&gj}uz&w~im37;<5_FF}iV>Un-DK=7pzdItCe%S1&iX7pJAx`TiIU)EMVAb>iNFM^a2mNQxlseN}i3IOX9m8oP?A~JXK z2p>qVs+tk2355VrEY&TMo|7#u3*ACDgW+`r8_`t+bIeW67w#g44hwOFJCwj57npra zTt}}WwajpCFC`H-Qr*}CH|VQ8ECJ;43!750d{_ooh`dDbt_KKdE)6!};2p+S>rcSu z?|GQZ-;V?$-0EhWe+xl-JDN`&mW>jSUAjbpH0_P1!6DmCd3$ z$R7sCFoPXq4z2g0MT;`?L5li3S8A!@ri=I0SO^N%(>-2_nQaFk*#b<~ot5 zx6^$G?-fYXq34==EohT5vpEAyY36_?^KtNY*K|{Aek?poAEjBgHF}l|fgm{IyMD$c zF`_@z(i1$b=Zs}XaFPMJ!O0BHPjGnQfOKoWD6);>%mKz0?X6>jcr!tom@*F86(B1g z0)nrHqq6^2vbbP&+Y4@E9?IH5k!oD=Hl(2i--*yKpqHuS z>_q7ID87QLO$EL&=fIJIU}lOOOVDJ&ri(y&vAEtF*O?d{u3(0iOn&;QOWV*y@1@46 zKk=8~1kV0ZJdx~Wt70Q(cOlD!RImmU(`qk%^ zpKOyIY@sNpIuN75`N3bTwquBLs&?UgXhR|Rfz}DQzKZHlT0;$$5$b_a;s(rtUeKg- zF!d%qXF;N=Hs4hCLf=fmp$?r|V1bxR=Db?cfN=F#CnG-xy@VNqGveuR*~9{hLX-oG z+9UYrN^XP7sKSYbftU0Dr*<7!>rbjjvYEAwHX@+Jv)vCOLTSLjpPRs>?gb(=hlm;b zd$ciA8rjCiz!>E3FeN8Gy)qWI0FVw^4eM@`LepXmHSzJ0Y0CR?spBdU6J|o(T`JN; zua;!`E@`ux6JMA}H-#tFFShf%h!T}o#Vb>b8pA~MGU7)pE3>x9)}YT0xSZ3_To<-D z`y+U3;BpsU8SlGi7>e)B2GEFa7VOC%7~=a3Yid&Qn&|1yuuvFX9s+7kHaA7f|9Y)U#6(B_qzX0bVB&7Lq=ZF!OrspNXabC>6 zVwb-}_ACvd77}Osc|77M>}a(vhVyq%rf@`;FG>tO)swbQKUb)Pe;3RO$Tho<6|({m zbmFQIQnIYJxjw>yuwo58=)UQaSv|y{(-Vh=%pkW`ww9R?nfsj}%iHaW51gRaH<6y2 zO3a7csEJqk<5of-M7yQMCU@9ew6JS7m5~)Z3&XrT6F9}DJ#~gYdNJq^ccKT#&Qyds zP37mRKu^(=aXeQtG{MehoHsC6_Bu75s!ycTm>dyim`UJ38q8V<2Td1nI@C;wq8r>Ib4=RQUXFXjeDz4*CP|eUMwW5Simq)BBqq17Mad;@ zjf>aCBLj?{DJ0m?-6~}ziqOS3gEwjE-KNrkI8<@NS6wn|VDTO85Jn^Z3}en5vO4({ zVHXSrxDx5njg3UKT_G!ZR<)%XDm=O)LOlrwy+-6E4nPxNbT<}g(`&^5Huc)exquJO z<%TaJEnI-U4wD%mJ!OrxoUQJ4ow_XI$?x|K;;a0no>*972HPBF zzFNUJS6iSKP&L({n_1!o^rg@}L!~IuYs_~T>`q0UKQ)3VtKb$PJ$x4&vr#ei*^+U? zvVb37-`KP$q>lIEeiCXEg~|7m{Ur=AFRzU+9143e^rcFaOjOo3H_QuNM|m`J&a?H` zOz#H2H8UP=U16p*;yQRBoCkIf!dh2iWOA-)V**U5NwIX;5C5W=1uC}58RjI`<<^4~ z0Edpr+O#1sV3vum92pa;sNzHuX6=jyu$hnb7lRM3$tnY8 z&s=6!or)7tTtA`p5!RpxI!C!c{|Z+~A^pEsoBxk7r*g0#P7|=0WvtLQ-l8Jz%XzXd z?*!qvVsIu!f?dQL{Ej{qeD5U=V{NG@)>i<<5F8SDJG;Qy+8+R3OeXDOYg*J6atrCb zGQ)kn#3VU41mcW1q&21$hrvS@J-o<^toj)&Gap>Z*ldIyWb)N+G#qnzVdMN5K~(U! ztj!(8<;0JY=WohtI7V+z zh0+Tm4yK4N!Bb+a_moD&w>D{h%RSh>g3z~A%md^Z4j$%}aQ7akjM;Ya3AyEG-Qm5X zXVYG6Bg{vW7@oH)lr7&F310GazVuF-398MK*HT`>N2E$pYa2ES2u#*D?#W zrVwthjg@bY(aChdIK`Mq??Y&-%4x7y7*`>XZ-`DDv0(+iTf|;4AKApf6fXDI;;#$t zRq4g@wfEPkJQ9B_{69RbuHg z+@Ou(Whz$)kwpBSxS-Nr$g+~R>X(XBDoRGVn14v#^*SjxfsazvqwX~grbwcG)*%R)2CB|sGx zU;ARtrok@Ms0uD+K{m`pq83;wf44*VE0tbz(V0ymei$)GUyl>FdLYGsBWjbV8wxS? z0!T5qk02 z6T^&q$WkO|ARuw%U=NOt%Zyn1mNqQ^uCrIa7nTH0NHCi%hugp$VBp~{+ylQ*p9A_! zD9GakdX6xJaBs*c>Q@}Dgb5|gK`YQLEuXxR3dO85A>pYj($IQ z9nh2$hfrxuL!{*vgSyE8Dz8t*q-ctsOG>ga!HKEZ{6tfB^ifz{pu3it^vCBSX;~#5 zEi(K_#Z~uGanQq%rKd{|ZWRK#QWhqBE3JD zETBs(>emt~6{Sw5b+EUfO-v~e6*Ztq^Nsg$8}MmdCRWt*G}X1vGP*D@n`AI;J6U?t z#D#_1C>PP43Y$4(W3>wC;_U7Mk%8b06Iy82WwaRlBpA|1Q>bjhI9S_Fohy`gouuwf zzz@uu|J;n@-)DOWF|mwUN@zjxSRw!+Zlx12QH=_Jhj0Xws`Z5u4dtj;CP_^{-H1hc zVe2cy8;96(L-!x-yo+FOu@SGR7>3X(Yy|{kRzHzHl!9*OGJ!eNzlLLK@c*Z`B{lv9 zMNils1k)X{LP@hl&}K{sTqK-nv}o~wszYPA#U`lfFzDa}Z^JRWuhguL1}s$e z@=DvfdqL#GFo~4H1C#Nzd*v`#j#a+}0e{(}xh8BGlz|sbZAo}umTSIka4h@Nd;f5&KG-vpzNbDHfE?V30%A1A# ziw#=)cnL&EIs77p#=$V|BO~k`>_-ClU@GS{w5%IaXD3@^jfI=aW%iv=4nT7x5DR^8 zQgVq>--tmLa0OhIdKQ5IDzY$kt8alWzfY9ijC_a?^H(<@<;CTZYCTn zKe#$JHyP>Y*;?_}bG8g<;5sc^nawPQDv<*XzUBx*vt)KgX>1Xx@AymGm=cxiyW18v zBTBO;`LwmM5UcM)sDHMJ!a=po1^AD^Y+0aNOu2Fg6mH}@KDh zKsZ$R0AF$7f!(MvV4pF!m7Pett&k-l^c04MP{FnGAa=yk zK?gz!y2%1!7ua-sEX-^WD=pE%7<$HeKXcBTFU+vxh3*(ZUlZ)a3FSW)-Ur!OJxqXR z4_+F05FloFk~q2A!ovhe8tN4us6^0t_6u)-4;5dC;ds6qaE|xYU4zzLM3z0}v=px}$juA{c#E6P* z2-_nU#X~ZvDN^)|sH?K@`Uofvu)Xc;O#$ofHS+?aWZV!Z(NV|bM_4;l>o>tAAVprQ ziAaSnZD0`{Czuc3nJG|<1P&4LQ0%})g`&9H`8KOiRQ4j*-PY9 zrits%`ft&Rkr+Q@!R%_~8{z~znO!_u#op(la1RP?X)#84Ul@bSnxJ>!+!b)ah_ghFudcJAV2S?k5u)!-?)*)I1N1sq>JIZ#O4}w=l&0mb{ zrtd?YcW<1_TpLeKo;fAnP!p*(UQL#u90Q3-zx7+MWm(JRs@w+0v1)oWZM~UW!BAhx zq6Q~Vf63}Fdk+n%Q!-gUCX0URd6j_ffU=)o)jxUP^y6rz}fXBbeM0Yq5y zv}9APDKcWmO&8`|@Q~>Vek>kyzBH5%YlOGvO_aSGtD*x1SA&ee8B3v|z`SP6lZ5LgL;l@M47ft3(g34xUmSP6muXCbiolG!a)eTx?N>0Vw`-mR!x zm!f0tJ+#6f9g(i6OU_FVZm3A7Dl1}*joF^gy#J`E#2J4nUjl$Xjx{DKn&Pqg^q|Jt z#?i0;vUBM@TOQv2TY7Za*>!v7fP6&jz)V?v_NeKJxIf~7uTHxfnUGjhtn~og>J>}i zh>1a|cq2|XZEVey_@k%K!j1K?2K~j>%;*(fb!+gST!mexBo(i2?U*v%Pc#tXKmZyq zzP~uL8Uj+&>zf*E z&qG=&f$`OsVEov{oBvwarJIr|MA4Vv{I2(>WO0sPkMl7HF`R$<{i)yl<+f$P`34N< z9lqI`8QTdfZw+QI8SWTGJqFTRxf7h6WyXu@kd)!!)CUVrt8n|Pi0h|_xbjZAJ@bhQ z@b`Q-3o)s1g@M}{!B*M?a1HXXZPYt8+W&+j8E7CYSRe|ec0;I*eIJ!oECVVx-CHo* z2!!NNsiHc_lXk@JaQk*Yv0FEhr;38+OlfoUP_Y9GL@P0^0GM&KT#efS9yXfUP=xIdR9^vZK|P4w*BeN+H=qAoeZcxt+*KBA-M5P+J& z0B6GKq~|!~!&yy8a1P~9q?tLXev!+(PKzU*mcahQdEa#f+}0DR6H}5k=`oAii@ib}6b--tqt5$~PHdB%)8dVFi)Ms}eZFbtOWpSn za#>*(`rbEk-o@=mED?zVs`9xg&~|MyoR&k9h*I!RLMUK%f#3zq1L75U318NTN;p(l z&ZvzX4vDD{esSaC^AnN&!<&#MQWHCIW;jV31gEO{3zTdKJ-M?`O6N;`y$P=_ezPRg z4_g`C+*Ir5=vKyH5=}@Y>%ABV;qWH`_Vr~o5~lfZUc=#|b_+)rlgu!`kkx|1BvHx3 z#X`CcHn|WZ;rRL&s2dm+E-B-$IiB{}pLA2KK9ovzNZ7JO+Dl4ay^0$w*&OUjxx)|Q zXXRhBK^NZh2_d@-j2u6tITp7155e(R(J2huDn!pgaanbAG~@BMY{YTGmTJXWQ_S*G zXPDIL`li=)xf~j9c$w7`_S(@xNhNDq=(f}By~6sC*~^(qC4Yz|LW-;24AdP9d5CEU zoZws3ji=R(CQ2yJ!t%$;#w4r4J$*AwPW%t(h?E;*)*~hAZ3=gQt*u!292gt&+>9@5 z$f6%em!^o)bFUPl3z6)`JhR_r5UNfCo~z!^ywfdA>JOp6w=YzM2Pu{l)}9~-NzjaP}rJrv=yP0uJ)6B%4B$aWRe{lJlFlzPx~ zOU=+16s>oaAD+oVqAGoW9bPkzvqe!?G}U$+%vh(%jwN?$!Q2{*n$bu zXDD)TqFSMP%8|F`r;>Ev8cnG zP)x^5)*5VLE?|YBZB2L|>k7e{@WrTEuSp1aob~N3bf$LBwh8z=`}QaH?Li)4Y}5nn zbuT0LoF0NV^cj_%pKJL%UC{N_OT&?qlIaj)gHMI#YT%;bE&=)f+9Zu>@HS#jheiS% zW}ve(1c?VQNV<(1a=Cy#V)fx6l%MA$6E8}iDI-zC08F2Ri6t7s!4~u|G57}uQk`)s z{bM&t01Kn0sK|OgXPlA^HW@b2jkbJ5;(`ftj7;J@I}W9VQA=0#A*X3TVLpY@^W1)T z0MG#HBk}bc1eA6Ml)Ou~XG53_;MLPNVUC6us8dtP`93>FYO{-d$8h#9h-&+{4d4e% z$Dx0ILLt{CCEEYp0I_A9Nvy20HO;9W7a;P)+3Iml7Ad}hU|$v+2o9ilK9^IL?;6Eg zi0lpCr2G(kVa4vzCeF=H%q~>GI@;DpZ`-%mlVLo>FnE)DPtYojf(L0zsz`q@3J!jt z0CGc3_X3Bm8MzOHt=XsClme-iGo+;c27Cf0QeOW9Z6bAQNWlMs>&$>_F*CUsKgqli zG|Z6j&|o-D)M`G~4D&g(?9!znY%AUD;0`mJvjcQaqG3)p-xC7FHt0UgjY<&K3ucyz z_#%d?`#V1E6xL*a;2iCI<1`}Wk-!^_e@@H4(L(4ype4A~mGeS7dMy_`8k~O zBX|{S2nTAng+tKT<`*l#g^PBN_&p|YHc&1hZX!W!VfKf2AK{DJ++eA_@d}j(MByMpS zGiep{qxKCuWR~DOAN(b=M=%bQ>M0EEr{(&HHaASia18dY*_m{ zNg8P1sW{DkrW80=%KH0-4KY)I_#XcE!9was%n^nN;9@6l4+aZx;SbnY((palJ~UnN zm946W$`AvLSe8`9_&+9}VE$8*4nEM~TuEL)?Xa>T6YI}i6e za%b3H-ANlAT{zSn(zWI%;p_6EEH_A)i|+Tr^1lNQP*3758)%pes?>U4We9HoYNUya zW2syar+WnaWNEi2LUN|{cbpJ>Zfyt{9)P({sNMTG-#cXl;fQ040%7-2!3fea9Nr0n zdIE0a2Uk-6C^*8VHO$_lYQa6DZhVLvV7KVmdf?*H+E_X~V;Y5hij>lYvni(nv>n+m zWb(t}>zX^>BXk2z({LA?A``DC3aA#SpPcA7%?{YPSQktDg;P;*!ZO&J!2{kvhW3rj zSm>`-a+SJ)dJal{--Dxo$g#<0)b%eSrrSD7|Js44;A}FvHn@fhB0n2~2@Tg<+J(d9 z9cWsMSY8B#Xixt2LJk}c$w9+m?uDGjni)$aVsoQGj8raf!(5-KTCzTCgdb4t)IWhS zTJcyq-X3mIp7@VK8JuNn!Wm!<7Gc?)LkF`gI7^Ji=UFM#lx1?VP?1cj^$u}8S(aH9 zRBTpn))q+T_&K(WFnqu`YGMbEDXPFkDGYI-dGeEOOYRaIHGYUP5v{0xh{6i~|Gu@| z+*ve(zLpAB{mXVjhL>gf`*GXLLVo8+*9hS$p^4$-kfI)!R5A?}B!B@dSo?rG{AeN%^GbLq_hg)`2w*AOn)^DFwYW( zUjde&81P2|;<0dwJUCN0d5DF}`mtLeN|{JT*O;}mBTd5+3uow=rR@5;;$>Gos6*x& zGq_5K*k^zOc^G&G0<{{|)&7{25X<=Bje#BX>)1~BbVw=cbR+bxG9Eruk#0;S8k(v@ ztGSCwVleP3rkrvoLc~z_3@|4+LOP%N+YW|`1&lW|82@I2aTT$zb)ZM+!cXIx>PK9T zX6fDPpgH;)^b>HqeuAy1U?nhtbpQ|W1fPk|f1ylF%*ZDD2<8jCAo-|#AA|#`_&5-d zrJe@j$mn~^)mKf5x>-1B$e6;4&@{1R{PsdgIdI27Nj5`1(Y+Gn&C zIMi^yvPK^Cr4%@nv6G<28UMt-i4N3pJ;fCOtr= z@L$Mj0EL+XY<(rFr5Yo}RSxHUSz_cd`!>QE*{4&f7`(~Ga2^DPJ!4J8&nOCT<{7og zT~A>r_-vgKDX0Vo5EHswa6mU@{9P?b3|U#J#!)C`!S&m$mXF3N)-%;Orfd^Y zJa^=94vr!P2*ICiz7GB=w7fjVq8{L+$0{Hq%x@%Zn4KssZ5$FRip71cvOyufCepAd zP|8RFI~R4hS*LHW=6EU*sb{!Ng>3&MZUl$&@8CqvlE&t6x#13W$YYF5EgYys-1WJ> z&fGAA%H~wq@bXmxfZ~$A&yXe5U9jg&n?0-W7^|w;Q$YQ~Heu6*zJR&Sk>khFY;0Ke z2-;Cp;w*Z$2;_Sxjrx=NSVw*EItze(FZB8*G;2It$R$*A(4~KklG086n2kF4|3zfb z@H%{NZW|%!&}PFv6lCaS*PNpY6_Uc_4BH$>XuU^$91Sm?i^8hoaa$H_CA=gQAV`t? zDEtGn^!mwM^}n*-k2#e{40e1VY`<-w1X&0Tl3=U3E?HI#S_ z&ZnP%qriX{%uwZU!8GonpdOPLQ^CjFoUbj*6i2G1)|R&AC|jp&Y?>w8z7-N7h$*5-FI*qsdRT!RV>4$ur3ysK|3RFkM9F6W4&nD zh(V`*h!6AH{)-h;7jZXq#Hf=+5S2HDkWZ5vjQBwtr-fU4wzs>G&gGgG=gblR1EEp zP(@5PicSWLK~YG|bKyVX^cpp4<^ZoLWyo`i0Qn+-h~=nUm00>Q0zR%ECoG4v6bzdg z0}goZCOF=L=%+IN#c12e=@H7+Cq5nd;TsQ_H6C^5$TtIhC5h0 z>1INjhB6;?jx9|-6A!Mbc;yP%=aFd~K_z5NQ`Oiy1Xn|rJCG5cK;M3>+9)qj`BOLP zrx3PNFZ`>%g=n~X%9lK^oRRN+-j)BBKw$rD`~PK2xT<%D;g)D#YYQ88yy}iz8gIzE z4&O9f-ko=Ui;kvv-kn|l4}0GMA61q8ABF@HAb_Ii+6yWch$z?)m8$r-ihx}ghh&lr zBr|c65U@uXYb>kLwf9}!wXD7OUa~%AISB)F ze{X}k|?cRTOLZ_2Bu6@2(SH>BhuU{Ee%C#Ov0ew z8Ak=2We)HPo`syRMhsyCJ(LT<@xV$@^y_ci5g0>giNR)29!H;lRxZ-%$G%8VV2%cv zwliQL#tyre2jVJ$&-w1e3_QObRW@Fq#=zrQe7jI|k_(6gemzVe=t;tJd%%Th546Ie zOnWDSxw#laVBP}-?QpEmunxRnYyJx1wZO;$*axKY8xpAyfgCQYaa^cJ!EGuRloPJ$ zBHdyFa3lanJ_G3=KsV^FN^AdsEzVI*pQk|Kl#>zX>?(o^d=kAc_$w<3l()8|fU+)% zqUspewDB3{3QFTYf~~VX43S*OGO&ajF)<^tqXeCIg#^%lI477n2%+Um`U5lnDrnCa z`!H!-C#-i7XefV)xc~FczXinM*fU-5g~IbI@ti406wPx1`zPY&`XMt*Tzbk?fd)o4 z5{$22ka1n7_5-gRE?{xAfUmvqoXNziq2_jNUL)XhQ$ zG(_u&0_>l=-F$U{*J1XvJqE+kEkM306!HszRxPmMK7B>wY!qaKTgwvoP(^tWzx*k| z_jn%=Fp;~bu#^7KcmM*N#ARmK_xwA~oZNYT|2Gg0C%APk5NLHv$-3Ty&uP$sS=)@e z1a*E&U)hBHyCllL5Ol&tl7Rie-H3=);+)5DV%EbFnJIx|nOt2;VO?;0iC9&RH;USUsQ?%iY`$kq~5 zupW?f?m@WCUDdg#K|OetqX8g3?Q7@$#q5#JVuF#vOZH}7`w_AbdqEm{7c=; zd7KGMhoDzK5%$vDCRsKkAOo19ds+_yUkoZ^ZvK;kKK)vn|6&YKqi#=E&M_AS$Hf_i zJ2e#ZYjOpQGFE0YzRe#a5nQMz3J?qGJ2|0_h3U`37uTs8;Q|miW8ZxRY4H!xTdmvP zKLA&$Ksb^Q{#xHiPo2Q`aQKOsS5Jm3^aAgk3za~1#n1|s!_KdeP`47yIW@$8zjtZ4 zt+C17pc8-yij9d}Cz~&d3jF#*PG{y>L6)Igf#6qcC)xS`kkm#ejC1BA?=O(Sk01l$ z0yTq+gW3JS3ZK%M{7%90yIivF-o^lngcuA2+64xnm@Q1RvYHWT5mON73I5|}qUE#_ z;HE;T2DS-7>-o@H(Z}e9#_1i0gegzs%nX&iZB{~vYU>Fh@@hNef@Jbn;sj8f60MMv zY~NSkxv0QvuS(WlwN6(tLHaxi_EgC6GQ7rg(RTuYluIVf_gHSByMJIsJ0c}wk(91( zZFGBl2S&$<6mpTURp=qfjMuqdBaBIj=ITtc$?G)kpUF8*5EZyyLNPv|;&^;w9f88W z5vN~K<8(1aW z1C57JAV3wzH8iCCmK;zy1iCg{=N|y%Y00hps#x^-bJ@TA0N^tbfZH4B-oA+E#9YD| zG~G~Ww`G=A#D*(5){!(a>Tor@pDcRvIKC7)(i%V{(uZ`*vI2$NNV?<(K8Ro(7ZW=Q z5rQEVMfMszEoJYoQML4^ocGL$LeA#`iKuQbr+in$P5D?dLHEHtbpO8>bPdj3Q{`@J zPODpSr7W)R@^1oycD%agJA8=R8l&_u9CA98O70S#Z{|OY5rAw5MdPoDePJ~@{oLo# zVDU+^0C^c(&rH~zp|$bc?e^t|%iuo7KzGc*AP!G4MmHnHEKo`!rInyr7+^RbEVyh( z2vX)KUCQ84D-&kU4|*1OB`GF}-Zc~l=(eI5HQUnA$hrbPw~$OeTSZPJtvQH$9w>a! z#3fV!-Gkk^k?@lqlYz#eUt1p}K=V0h4kVLWr;5%EMK2E>beS!9bCIO~H{g4yJm2lZ z0m5H|wK0u&8&IOy()NxYM&vV#MHioeFGO*+id>FN>To8oK^^K31pXPyx$y!i zI)5Dos2)6BQXghZVNVkv0{W@S3QasAJ4^}nV(z+_;jpwBVULj_aqkLJ^IJiqo556I zo+=u6Xq!My1B0r4K7i)nikD~5puOv0Oh6bk2)IW{g`Q-&QsU4%U@PW(NC&3+w;mh1 zTKeGXvZ;8Sm{xgT*dsJj;}|?b7;vtT9P8(~T)`D9RJ@{Q2r(Gn^}_+=oG%6R&gQxH z!+H^zFZhrqQ7S_&9l@+3JHN>+B7YBKitaX)ioyUfM-!$hKY(jxz;OajHNkwqZ2Q z_&q6n2%UfU3uSt=4VN4#9`7}fOjO&VcfICnJ@54uN6xtwEs6rXR2lA25g0{dbwPX` z4D*U|NPi)q@;u@hU}#bibd+pZb@DXTa0mc8Ig}oy>_b64Eav`(#LnAuoq^t5j0&B* z_~UBk!I|A8+IR<4MwfK~-k<}UOP5szc5xRWvE~TYO+THhf0DNTB*EE(aYJ_n#i#T+ zia_`kLxEL|l9FWS3+lm42Ne(x%b7%p!?~Mos<~R)J`{Jd3Yi8So9F7oFA0*j5~7t# zq_L_%tQ7@{X#P#h(Yj@e2Yn8ypEo)Q%LZDQHewW`W~8Rr`x<-@rcZC;Yq;%$RQ~7kJ@(i5UmMZ|5hCwhT1S@_!9oaunf?OY|5joo@yC zHdK=9e*zOTM=>cfaecJin;&j-wXmD$Gr{b=o1nx%V^XQ+-NGhpql@Muk@azs&0C}r za+qMUucvF`k#GU1+W80)gq(S}r%3G&nvqj$7G3-yU;T~T{X2t_d>#|sB-%yP|DHLQ z#_G^pS`P1RCJ;dzo-=a8mDqwb`2mq4c}>Q^Pv)$3fLIZ*0%*!QHt6jcSZ6=Ubib-t zaQJ1xbVvEFB&41bWjBhkn24X_{%bx1=ov56w%zX)oKh|E zwot~tosP~)WkkbL!TMD~m$g`<|@qq#ZXpo_%p=5V=~=wtY4 zg;sBYwH*YEGvi`SY!P+Ro|SaKW906Mz*O(ykOYA6UrZbr&!Bk4yD2H~`0aAlfZYbx z162|`^6f{#1I^f?jVBAakyyG; zjn$kjSba-4OF!;qOlX-rYUw1g{fZOV`!Y^4&O{*->%7T1 zYl$EoCW5P}*qFklzP)gW?*0p+G4Q77smsOcS4%$p7(vRu#HDO+jy{9TD_zA|!tbX_ zbauS3Z;#?bkbjXzDJ7ED$9aAV(XMz-c-EZA1ENm|OnZa4J+B~lMnayW^>Ek9qD8hj z!~+BP97&ua=%}CYcwX>s`k}N1t*B=vs?({O@BxZ;(J^ZkvWw_#*o{2a3D`i&Fnc1t zK=6pL1Krnjw_3TR)EeOPnC3OBiREp#h$HU_+`g%v|3)_^F+hg|j9v?fl0S->fl?R? z`z;lzH3%B?8-82^MK(IgAtb0N(t{;&aHQx}Z!0mrsnD%?q(OOv!FiH1+PYHN0gh}@ zg#QFt#W?mn0jcnh=y$FWog;*#=^MXFcm#LQ7gni|o4stU+8=}EcDaOs>P8BupoBg!-)S`MYoGMe^Sp6u_KcyI5X zngEt@l_5(XqBT3%G16+t;G$(3yTpabG#YDgK#!sX)&Jd4blJWgE87*dw$$TAxiA%Ds9R~ul9V$f@m;687&oZmZ-AbFw8b#Q1stzNJlb?lJyu}wC-IuX zDyxWw+b#kFz`0_3VpawHvta+WMbaCmNDOrd0&B#?Lm4@pf4*1;fb%qR7^Jaj^rq9&t-R}hmM$&{$zmw_mFY`C87BPdHJaC)^-Qryk;E-nD$u^RQs4T!YYVgW5-4~gLVL8*2Q5}8+xHge3-?uP_L^CXtAuepTCe~N&Kkd%VjU>*PAbbNr-I#0_{Xy8$0n-04?@?faKN<_iV!I$m|68YB^P5YH|> zCuq1*SCJ8-LPv5UTame@tcQD^IWb=&8P+(-r(w|uL;_Nv09*)eqGe&LV2_oE>?s24 zY$NOzdTmRt*Ga;s?m_hs=w)iE#a;m15V^|h7^o}8rA`Z`DqIU0FtX63z;{(+V94fd zx^8g{4Bdt@D`ChgmC#V4bz~*{|5(XsC9y32=l_gR6Dq&y?;gDlD_37<-JPU zm#kK0Ik>s1Aw92o(^OS+rn)NL)YO(qwj=`oQH8W+OD5gWV1FEMN>)9ojYQD%lp3n^jQRv<1O*d{V`M-Pr?rw znMpLI8{pD-vz^Z^iny<5C``-w0r*lz=dpde&61AQFW{n$wCG&21KmWk? zNO2;IJ1NnUs78o6bWiEMz1-`DcS^*uu+Z2U_+(!71wQ$*^`3IAy#fP2qu-K0V;mTK z5j>tdbsBg+1@@qKU6V`^;kpqnUjKAIa=C+O$4P)uASQjDmWXSCe03@tV&Z^|Kw^Ob}Cc<=y2}cwp)WD#RzWS7sT5f zJ+WSbd=;ha8w6i}B({PupxK+teRRz2Mt#UHLge-mF;4cQfN^uVB>&&yto@AS#s7)} z-m(QIxMBk+KO(cdZ9$GlJIhru~60ykWteer)aadg`ccxTU`2ZMLm z$^RIoUEv@{VED6+<$(Vg@ROU9a5@+65{E|}{ID&6&jIa!)g0d|h`hj{|K{AlKsl5P zW^}tv2L}4V@?c))d^~5<+jBm7oCQ9FlR-XW3=G-QYx>T^V7$B}3A};3jfNys$(Cfi zA$d?@k9Z~-pMxlW2t{l7_%QJLju@zM9s1B4C=Tb49E*W`8ZPiDlr`lAYvB2@=ndfI zr);DnxOF&d!f4{ydq%4^HFqQ0J%QfDQu^7 zb4w~pYdAq$u+{>v;l5RhFZ9l{h6TKdAl&Bkg1Z^`&Y8k@jPG9Zzzcgt;-P`z(ZW7D zCopW9^?d?9@SWk(!gKhVo=LZ)tJC3Ce$>m|g$FJMcf63!q^8S-=jUqqvNPEt4m z&p|v3dqKl#+o}<|sa{d+bgvG|4})`*wq|E1ZPd)lpKb7e(JbiJ&b|~e0|Fm;3uYG+ zx#QiM%-nhAz#A1{YbGb1$pu9f_&qLIw|8xfudcS4(eylfMSS1~Xok->;R;JxOi$qU zT(28$;5&aoD#{a^U0rJeKNtg4cw!P<)Y=$^1KrUiDeBy+@)!<_%VArmiIOb3{BSfL z!KIn=Xzm)?z>>~{Q5coj1_r$hkh!%GF$#PO;etRDiNIimv=@_g;n*x~ZktG8&sfvb zy8<-;!gkuCoJm~;ZT`2M45x2OEcna)8h*p(s6{F{GT(M3Z{s4yuFY_ z;ODyt!rnPMUp?#pxig-Tit`BD`Gu0`y2gdjtqk*j+u;5yE(A~4@M=zsb*$8oZ1&lQ z)8eVR)_7gS0=lEig9}XjkuHG_>)jm%^$QwX_zKGc6I4(W$KKn{?SfhU5JKQfDA5hY zH2uS912m{E0W}+MNlZ*PdY6^?e_%GUT#}2k1O|{;FKT4}G2hxH@MdfHJa=GpltcyF zf(n>i$ARU-l?s6`Z3v@mZgV;{J0JN7jP8%ooQ0Xl)J5Eb;L*3ho0GbN0fFam9aadc zg~Gk zVL#wR5UOO0`LyqK6zX#Cx4`|o$RnCDQB*2wyJ-D)vYhC08HCt+H z0Y9i>roIXKQ8U4KLabwGP^?Tu1~`gOxW9biHjlvw9M=|b6s{&Mc(N-0#;K#1BXZUj z&!pTt`vQ31O2E^NFn-~!%(e;dcrq0xpZCF^lmcE2Y7+SWiLUm4Z4%wwF34mQNot#X zk=I6un&5CK^MRDWg8v<}(h+*1Hj`+sXNKM(!j>U-&5RiIRArRwJj~SLIg*`$6J(su zPr(M|j&B6kfi3`ykm1d7VRN3Sn4H~Is}XfV<(WiHGJ{-y$jUeyn@!!1k9A$TQ@3;} zlKWaf$e{9>qwD}E&O)3xfHbkn0NFmq{(s<730G|fdx-ldady_6B$(M64By+sUh0njL6XRZi+Tj3N{sA_VmgipWDcOd0)9msrE82ey1^oT5Qk^{Cy<|Kvi!EJd zU?0cT%{bX|Yty6gxIlvo3A3_57awSJVOEjQvm>xz7n_!@y`!V_I|6@LUyAd$qlP`Vs>f(fn3hESBw`Nd7nb~)*xH69Jw zLXl(70@38)z}_8$Jv!~mlZHOpQ9vAxF0TO7Ms?K3s(K3E2XzPrQJshLF?<~*rQM5S zAbg~{2v=a2k^UA8!=Dx1gt!ktYl&p*azPs*DL7F>j@eTXSJ0j6Dvt0%K~mNW;Tr1c zwu9+t!qMto&yvcY6ATdl)A$}y<*4(q+FF8QTWU$c|F0eHUW~Alz*5sBT1Lo-F6$f> z$G2h8%&asx2HkZQEU;b_JO>MY0;8Xo7WY5UcZ4#kbE(AoW~#JoG#?S*?5jrvao(>R z8B}z9q$&h88HzzNrdP+{`j(ca*>kKEn|)wwA{+rVe+PcSYO@wLg32gM2FdFb#IRUsa_=0KQgW$ifiXa!(kNrSbVA!^7J(w|MMGtje>%T`3o zig5}|mr76kW)kypm?X4N^PYe-8`I&jy-O7D@UI<}U0z+pq{QVe8diUH)#r>vbGkKC z9ftEY-Ag$h;>w23CuHKO>iS3;4ry>I-d_;q^cA}CwXM369n{hB8U;KFZlu=MPe4Gh za6LeDxL!suqH!ic7&%a~h|ZPk7K7N>DJh5^Ba$Tg9_eUIUZS-98^*qXlxEkPsxM`V$wU?^!WQ zM4~xZ)xb8hMlI`GMJLb3jM*#BH7YM`p^cjLB=q3M4~{pSeCdW=f@33!ATs43CFE-o z;S9u;s!T8sK_ilKhZh7}^m9mN9D*z)hQd+C_9E`aqu5(YJD=#L&QwYp26O2OLGE2B*2kH#0+~DKa;Is#j>=(x0u#+e{%q2O5FF^xPf_=} z&JGB0(KVx=s=Vg8Tzoon#3JN+OP692*qK?>GeQ!Snc6!`LgXyfzP*Jfulnom@c~wy zuws`%I#Yh?4NLy+)hf>#oUf-Fd!?k@5V4|L`faz|I$K*rIM%qvRIWEefID`B(GI%A zP}tBm&lZt#$gHa&B6P1Sgfrm(m*hGY_@{Rck{n}HNo)41*?|U<&=*K>n#ZdY)v1m? zCJ3sXwM-QHba5R3w6d^@5u<$lxI8qte}yTv?Lb-74gI@PC2_U@EjkucU~PVd=_0cs zb(4%eheLrn9s`ss&k~HeJz##(7akQv=q-womy|5SDH3}g*^SD$4$-W?t6NNbA4C8N zycxt~xo7|*THVsx&@cnC0Ramo>{<|Cm;F7fpXll8r3>1_7@nm+s{v3ROV_qqZ`TNlaXv#F*W= zBv;x?+01MbD^3pwN{BZvS)+uMtbYZ*u|>5Z;yYKM1@n+JaHxlI!Dd1ggIBgp*XF#h zk%egy1e3X0k@J&O{eG|>hxl0#$F=lW2ig&Ez5gx@MMzYku*)n&4>Sz>dpr3pCDVy@ zvv{a^QeWZz!*)vABP)ne}H4`=$xz9SzX5NXGM_l0kTB?~WCa z9ZsT=S7Oh^oceTn9xK^^Dp7;|_i$ZezUtMz!gF&l!~oa+Kk+Tz*HW+bhbJr~$+`}lmGMY|1J#F+nj1kGGbla3|gWN-4w6{(E-k8 z{=SKR60=7-nOTGT)@(b_iO~dW?(8n^AI>Dv|J(mDgHw{42>hEa=G z2_bCwR>@2{6?LM_`d;bR4D>_}oASHqRz#Jnyq#3KEo{U+Wc_AT(9M_{TBkiBlgMNu z?fb^Vi{*)YG^UoLix1#6%rhm~5C(m*r!?%L@8+g>B#nrG3Ct=bt-j8#0XUF06LA76lDdH47%$)H29!r8o2R$VL596PiV$0BCSU|f8KrvWQs7HT zX}>RR(LJ7&iG+>J&5#-R;2x-Rh^l}%^`sJ*1YFe+Ie~v9ut5j@i~*`jZo-bVp<<~z zo(ZLgaID12GVkbEm=eJ*(ncPsBWN|51V%}F`JKeIZVLkvi!&(olK9fPHk@S8=R%0H zArWG80n>=zHB?^Dwa7JLXZiW_9|S^iHWx8_r{~90&1vhN>~8T^Ebw=w?YhtF2!fB+ zr$ZEAwh$B`8n0MQHWOWRf?~$}Lw6gY=&UR6O-6d0Am+UsD!~%7@gw(OW%L}WxkRTg z97qfIa|+0rdEk2*OvNE&P156Bhe%O4GHb`^#ykXz1!I#Jv}AD4a{!c;MbdGWhyrg3 zYO&=S(S*yIAHt^mHZ^ zxpww-4ce%xIa?xuze@w?+~U#(`k@9$_ZDxF#61SR4+d1TGO%OEH_rsCrNW0&5M(V) zrfSonZ%&oO|AV@T(uQOs#O$O*ZM?N1jEV^?h~v!T6o0*9?0hfL;!1izXdA0}nTkRj zfk*fdBDNObuE_W#!@dfd&8V?Zv}zNj)EbiB!{v-J1)|oy59F8axgH<^=UKsiLeZNQ z8`Gn$lMH+?((VTVAcZv#QLq75QqV&Sy^7W8@#f|>B=Ulw8L_PABc1zhYe1s~J=0y+5xVI<->1cr`(4$;d_fCVV z$&mDsfH63wB`#t^L4?l|U^F-@hM4SvFiSq5L5I3$O$(zBGv_8-Ahs|0nmKwWbKo!CRq4_>oJq4Ss|t-6VeWB zqtnfqh!s-9*_`VMMk#;yu=wI15xoNbB9`atip)m^DkuAIqyc2uB|6xtZ!)y^EM1(D`jRTGB~dg+Mjb&^wS~60nvXLMi#n!V2!6?S3(8MQ^iBRMb zI;J}G;iADt^D)$By2;u|;keP|SRs!?4nW)!b|%%+BPEg5EO4nUkz)yxhqR4zaCIF)pqw6 z@jbpk3f{I?4)GA$Dq(gOUvmDUq0jjbvs0c`4Ae?R+-!z10Sq$^m}3ZX&TtKWAuZ!v zq$&UDI%zznZnJH8NF~VTg5}UpVV+fF^|!IaS8aGl$T)50AuF0K+e2S5!W>%M9AOsO z2i?TW`nfTMAa$9O@(ICcBkxN*A5b`(hise_mpc_hFyY-3h@t7A{&~vdXs9MPa+z3w z6iis`A!90t5L7Ynt^P?GI6+4wn&3svdq)?1J1~pb*^hID8KAJ4Eu594_+*_xrU+rk zr2g8Mz!S}Eyr4)57?`qltP+?E%;(12qFLCZwE)T)9=d37czS6E{QtR}0xpCSgIEe% z$7nJ|AAd|An@t%#7>b+byMd zG%7`@05=&g9L{V>XfsWB&k%HiL0K5b+#h5)yA_biOiv|6JkzEzlwedZN!#zPuM1s( z6_*uAvFuA}brfV6?~sWC3gw&6D}1<)Km*QaTC=kG9?8wbndxx)+(~I#2BY33!2u(G zF_V7w3<+a1^MH6d(cPhS-wC+W5sw8=xI=aFSg%uv; z$vKk1z`0||HN)XnIgc|_5-Mma$r%IZ1T6J8x5P6oG#I<0$ZgISzNX zgcQWq`j+mh4dBhG8Bwk)Snxw&k%zT`V3(q0?T z^ZwYINL&9lwx#RZya3DZEWHEXRkQi0gF2B_Ac@H&s1qZTa3gx8MgaL;L9>_-Kx|CF zp(D4jTkCrDIc_E`oXItpsP^h45EO?VZE8@PDM}7!2UkQ2JqhD_Mee<-5=3KIL5^g^ z5qNxxd-EUfJ+eplDV4mo#>2~+*rN*3%n2$b`XrlYMGq_^drN9(kkhmva*R12b=`s* zpvz&F{Mo?+RQ=eUBg)`9y}s{Gd=YR&gM%AtHt87HA2rG5Xpye7SmpfJwNbN+&igoz zqs1ey2WtWaGh5;#&V3qg zPzpBG{Tq&$@_O7VF9~ z8eS&V-p&o0b#a@jOBO4yn!|M+jJUGo^}g%v4s{~RyznrMu&xHmp_$c{!6Ll63H7}K zw>x)rEI%ySoKG-LXh>JjON6vfk+!R7Ku=}2fe|4%rfW+}fHxyj>`oGiO%bC)U^2;# zK+`Oa#qT63JCiY{Sx1nT=nKlR64!JPS_pBefLO6&?ih5d;HyE#BPvbIY-DDjZpC&K z+j$O%V2jr)`~X+Byf&R_jJM1>C?xU+74a0e5(IKmL720vo?=3ArzJsBjdZDwP}J+I z7(xm~v~w2eBH=1odYQLGg^gleal*^77ASM6c<~)x)UrJ%Q0Hh-W%dJW(2Ad<^c8!Vz!;*!%7K0OQns;ts$x}Xa#vt!u4`ydNJ9^h7YCBsx z3m5-b(w>Aq5VQD!*U1a26K=g&i0qHTD#By`k2N`{g#X{CWc8AP0|%_$Zy$o0{4($(BUmKdP!x z)SgKHQzBm;YOOMA_*xdwCNc+Bv+VtkFG`yyN&+ z?p|^Aey6Ps7cAZq@7y0lmGLCb`i{)t#u0lxeMfJ5DC9H@tOgLo2|GJ>_^mK^I(cT22U6m0DjX5jx z8I~uuhqH$8?KK5L-B2>1Ey*)G*ja%?vm$@ID(AD+_~W$%3=AvQB+Kb5>?IhQg~gnK zGFc4eD_O_2on4ncPZ{9ee`y7s&Y%JfMR|FBVP`gCWIYO6Cmy-z z9QLW;fZ%|uG%{5jS&`%wouP8_2#hIMv!6og>6~s~d z0}a28n+u}o-mg}2MG^j5QMBGDCW@Af+4$NSW!(`)YsjL=PTAQp;kU!x3G~@Qr(EZF z*rQ?Nut{|LoOahmooEeYk^w{IzvM7Fe^WW;L1{gOL~{H1o_DJR$jx#4ad0 zfNYN1Lf;6@o)4oS9%WfKY8k?3VvvvIjDEEQ<1_p-pLF9o9_L%W4l`6tTiHBRw9~Is z#es%vg%nP_F|-di@+cy%5gF3dnyE`njH4>PMhHGX$)x5hg4Fy@kZY(czBiY} z7Pdr+ACR&li!^#qq6FI`t(0S>;71=JEK=qt7U*q z593I93(dkDM0J>;SV>sz?!xoA{4==AmxdqyDs0%T91&n%>Ii*9u?fNBT~`>A4BvBs zjmn0~ljF@Twu^L!cngL-At$V-{zVB zNj(JTs8od~%E;tQEj8q{QrzK6IT~2IQdy2!1ttdoriY|2;;^kFhW17Y5bPuDN>bPr zT&hMj__G|K=Q(Qc>*zZtncA#Au^>bw&@c4XhhzBXXEH+Dga7u-A~jnt3mEz$WOW8j z9f&asFc^>COahG{-@@v;2zrNZ)_<3ER(iC*>#`-T{!23gGV=K9u_ znrIv4N^V*dTlR5#H|1}@61!J(Wuw<3^Mu-n^KsDNtY+jJhgy3^T|FJ^Dy+l>OcF647Q zSmX@lK!Mb(;1}iS3j%B(3u0~ohpmOlp$++O5%*9!`|ZCuF;V{z86x!pRjYX z&Nn1YVlJ~{pI5xT6^>i_7qcOx5Z<$)@8IMHEr_TXGV3951xDZ?DFW5gR=A;t>Ud;w8R~e}#4e+BoUiUR;D+%{KPh$eNm&36vew7jE#8}=0_kKQ;`!mgK%>{hEm1X(i| z&^!eEGMYATG!s`QaGJ13v*hhS1+LyX zVQa4*G1_$;JwvTroRO$$4d0#N{OB44Ok|o%IjYd;m!ry5LDY%ld8rq0wk$s$!SIkv zY;Yq*Fumg!lUsQ*hGYoMxn8Fl-a{T$pJJpMM|GrhsX@^%i(;c;rLgjCd80{R!Z``jzziD=tSQ)4L1yaEkX2Ma@ z+(~uDiwKQtcy?ZtgcOeT$ZUm!Uwm1M0VB3Gs-Dd&YEdmtF_t#R=Z9^XaoRDS!CE=E z0d=smDTj#y&GxCKi*oK2@Q$18scOMFavF^@IQb%A=O=O3@AqkN+elU4v=aZ#|<32SoxEDB0MLD7@)T*)0tywV&Cc`Zai{v>VBWPUaaeNZG3?)+?b zlpR1jOyXDA>5~6z?m%XS+&45rQ1fV}XzgBRIH8JsqT z!gpMle-u}1w}Bfn3ELqddItqMkLiov3M3>Ndnc<#inE=r&8q#wh*qQ{_dX%MC`yH+ z<)O>9jlgL&%9iG6iSd5L4V%MSo8xr}9Nmb|i8m*v+3UqnSQ2uduaQNvgM>8=H~yl* zY6c1X(IL>dxj?g%Z}a-#c-6fSs4$a4E08S$#iCpZf`m6SM)MfCAA`M+l;h-j{@iS- zlAF0T?>5EDuRH$!ph;>l7Hq=JMQKFgTuT$(mUSre4}v zT(Kts11Tznr9SBfoJftTR_CJ~Wv%wGO^8+yeHONTl&uazn}N^^=-BG1mB{`WI99qC zLQ^_TxOPfd`_(hzqE?q#Q=(d@My7~Ob*Jq(P&8BdW-P#0oV|$(LDb4d*4-Y#Gus3Q zd~J{Qoc18gU(a1Wv8rsdcf1)XN4{BLN{|8jy_v2v>+#Z#oh%LDz^{hG8$n${w_?zv zPF=TS4eVanDph`=#z+4wI!g-9KO!B)oKeIFh}C}~hVhX`Wd94ig9Ndsw3+l>@Dt$Zhm1hhh+`p7_yF?j}|rOBkT zLC8!PIM>jM`|E_s5m1wa`{@#^;Fb#O|9FZ%B!zM7inwXGb3$1W8excUf)}V1Ks1w~ zZUc`qNVpaDrf}TEUYn(ckPtSPUd43+d~5##VxR$G11G2$iy{&$BIE*3@%qj8$&r>k zuq#iN$dhHOWbl!CX4CFdVBq4<4IpQvgfd;KbL=bweaa=y8E4k%#g@7g){Ij#9 z`L0u`)l9VVj(Ap3a1uiyMkqMGrWH0#^i~JcA0{3-vt^EvR)d1huNEjS%w`Z^xMlwIZZ`LpmNhmSv8Fsp{1^31Nb4tUDRQQzfeIXR8(J%TWRE3zLrX$vD<*@MDyOJ%1b`qijvi7iR zDMpIt?VaB|On0ILAFjny^aSo{kz+(J${dE6LNOI<_ZF)V^5?z5qNLp8YXuw_ZOkA+ z7b$`8wi7!dp@lsSY7X~S%#v@oEw@{tB%GR}^3*mc<>m@9Hq-#ywwRN$uP!!+_GV%e z8CPpjkR0@00)WofqVo7a7iw4mUD?X2`bPmmH|jP{lL#Iy=>&Q}J6CSj|5>%2&r(M( zllgeIzCV`<`);#WJSc~*Qi_ppaJ`G9vBBqp0pMKAr6sOhkOUM8Rylyqr*f?VJb6Y7 z&PDDt)M|n8E6Ksd_!^E0g}Y!HRK!STpbe06wDwbrY`|q=3pe*16?)MK#x#+uLmzh~{O_k0ZuwS|{5>1*^hjrGeKyDPgB#g(Wtg zjFkcLX#gZ^yxHi!l0W?s%H=Nu)z5fTO(R3u$NSYykrmSM;D8 zSVKHqc4w0eimr8V5RN7VkCmY}9{#1Kb$b?vVL> z7jhkU>?V3!4L+#Db=V zs1&`@s{`UUs=u$r;S4HqBF2eX6@ndE5;`M;4E0Fr_PJWJhnTAvnKnVL?}XxDqHk2?SK#kcg*PPy-wq z?UZ580xe+uLP*O}Bt|(!{!Q3Sg8}=^dU|P;ErsIZU>%UFdxc&Q6PAo+AW)EOoj`Kg zu7jp-7>Tg4v$Y^ZP*%;Qi!}he%lLwjp#_R9hHeeXLgxXUm=P)I-INZ!Wcsu1!KVam z3ZbTQOkbGSq_|@ZK_uLx+bbgx0`xE-7MI5aYH+TWcMo@W2+P|MUt=gYb09sb#4*iG z1fH&v_s#eiNQCr^20ko$J?CE_A+d?>~*#3mQ%(SLLPoINX&BXEb z5<}qJQCZ@^)_6ncL(m|cvOi&`J=X>%(+#bSA#hNy+lSu%4A+6PfoZ{_LGOaBfFxzd zG$3}Y2S{?r$Q4xN>L4QK#3h0Yf*q6Y!Tws^>KIBn>Tqxzn>DLGo|;V1dabk%aLxoW zsl+Q@mMOSJ&bCB}?(6EJJ=2+ai3~m0SI6}Ra*?Gi@#fGaFy=IY3d|D%oxP$7^M|Cb zeGghrrQ3q*GtVmDLixIIWg?E*5ETUBVtGw!QSba($@Nt_wds1pO7>8^ltBn6y@fkYl>va{$JZ_K4CirrX7Lmc6Dd94(kAZC9;DKJ~8}@k(>DE)~&5aNZUB5#dzLJV)t-Y}qaEeOXA~ zk7YZD<0%R-<5W=>z>-4?P@K5bVALk-d_a^umFu@alHOJ`alMWvmP`l;ZxZufYvZ)s^N zP{9NDbh;uOe=QX}J=9YqK|S)_4<~;8PFuIBAV0xUP(k4pU+N@E1zVA*#5lp^ciNb9 zxvJpzIA6G7SobJHkSGkyXEjo}3+x1JT{wzr5WBZD8;#5#0doZW6n58r%oM8o#eO|Vwl$F5Zsg<;B#Pclk#SE01Dd_kAPvUg_LZzp1?E| zHb<(8;GRleheZuJHGjJoxKjBQnJMYreOd6<8B z#3wLgkV>3&c)Ztnr=$O{#DbPgd}fqH(04tWs#?PL(Ds7l5#=eO#Ccl=DISc$K)M5+HKZ|8g5R7+)2p1EOgnADvu)SD*gRp!)1)4kM6b=U+ zlmC1ntsUe|v$y?xCIijZWVKs;Uz`9K)iDUo3exivLT4mrp6E|H=j!p^cOo93JL5a* zTV_SU-5jdAoA&%G^HQCQMer@TGr!ubq|b!#lj8T9nffr2hGMb=F~_ja>|(4!T!Za$ zn{0+i4eqqFk^II4dB~yoaAs&lW=<`A$v|OJ-km8rGeu9CNdZ zQFn$~70vu>%_`-B9q8_zLJ@(CFv;tpOFpx5oQ@SC6{jT|lPyz_scb>X*&O6KLIMC= zVVfl6e>OE$lUNY>O$&$SRhcT@<;(g-P$E?@U807XRUt}S>V@+3>#Ed;?zN2mM;6=n zofwc#f-m(7j1m@!QmmTg(psFj)0UP{M^ENd z_5#Pp%Bom2NV*b~SPEmp$n2(ntxX+v+UZ9f^x$XZ4O__AHIuBZf}SOAM~rw&)Of7M z0wB!7eKAZzh0ra}_N+w4A1Ib5vdLLVq!8P2oXMAJ`kfk%2l(0wv6xYUrmRt4Loq79 z;lOl=!UH3U@IVna)!4n2ZQPCvd+aX3v)P^#C8P+WAM}SHlnw8Od>SSF?CC@N!(I;} zCJ~&6ba{7|OexP&Xjd(!i1w4ec#S-?SRQ(gV&b!o<-F^YrZ*>AYtj>K2?e-~{I^LC^n0b!K5x$O^SZo%F=!!8&E*8dCU_1uG{6#>x5) z-J%aauMfXRSpab(8g;bza)y;|Li$Nta%{&z57^Z%v2%1Q=qHQ<)mcleM0AOGDuc2O&Cz3fUx zx3^DQnsiN7zMiKm6a3hwUNQ-PZ5mH1~ z|MQVjcagGxr;_>i@3(KNrQdJ=%g#jw^%dD|v$+@Ajbs$f8qxrEnZ*55g*gJd?i?jN zM?t&|^dcn~((gaGRKgQ2=oQ$vHPsZ)G>0evoxG`rcJ6nlv9*T5Y0MwkD$MHAqTx4@ zMQ4+t1VNt4W2?Md#|Is z3DP5lYqvuqYq_sP&%z>;h2$M>`Ns7QQUBCw5%v)~6IjlA9cA%`hHyQ%Ge$vAZbzfc0E5ti5FIdmW!gmJE6$6?=9U?yI~xkm z$4W)DW0k_lkKC-;u1(Rsv5jjv0K(>=z)s|XujQd%WGWpaAQb5c3Yqm3hgSQpH{7Zp{I%xWDnjko zR^!ed-W~I;t8mjd(b5)f`d@YWs;2si9YetG)6lHG746ck+S_^NuDgWxW3W~NHc%TJ zgtG#zb5Na?`y%jv)TBk3K*4r)#!_v7HGyqQ_o~`-28|rMcH-fmKXrEkf9+1}CGN!O zGrF@AtYEuq#$_+q_I<w-C-c+s^lHP&<=}FPxZe3SUJx#dZT_)-DoQMNYM>p*FvpEdjJY;!t1)=>+-7 zMdy85^-qVQjR_Vs6Ai2)R=Oj>v{`Spw#s?W@1Xj&!`VY~m2IIDK#6J?drV6?H*+o2 z2{1%^E8MGNZ#8u9Xp3jajTYz_!#CRP=*TEwFX@fr)n<-^K^A~sIJCO0IyzOF@(pj< zvl0#1)s{?{iucrm63*TVNX|lDz-Hsdd!iSZJ~<$6Gf>8B9w{(hv>}}Uqi{|oYrJRI8K0?S4B>4qRA4+QC`I$p`SCf zjfQ`t5YVd%5jbDD@`9D2;xwutV-Dxi8aX_L+Ddsk*LYa0=j}mos!Z^Z?(>R9XQ7b` zPHTr46sMjoBtn2Esglqq>L>u>n(8N&UA7a**=f->?#iM!G{S+?gtkSl%;EbMwPr42 zqRf1Pos9aRwo#!>gtiTmu#@8i+!&aD$_I~D*JitAfC3_wAGqUgfE)U?Vk;RgY%^!k z0|NG{8@}tS07Oh9)cY^QnyHpHHv_TJt}kPSY0yJ~A4T|=t z5y~!YBiK|(|nlEzluvG z*@Y6$1Vw(KBwiM7xOvX9D6`_73so8%tOAPssOH|@f|oI^;2nJgG7hFcY?`t&AC_Ci z>%hxSUF;w+Df+~6xoYnZ0VL6c;;EhoJz*i~339lqfc6nSiQCX6afk~ols(#onQ61N zH&WVQn>P4_4CA$Kj~S0tNN=k3b(u9wWHYN@u?2!yen?bpdkc6rh^?q5|G!nzMb~#L zDP2b+C<@K_pb4pU)R!tvJgg{*{gkmfl~K+Xak@(p@q_;As?gtBqmga2!RgxI>+Vi- zBgT148MHcsO8;7F-{9zyrazDChEMq-wMa_@Ywt&O_urRn`S;Yr*Cq&0)|XJMr~NwVueQMqAHWSxn|JBk81P#Zi&HR5ooJasIb zv*{K(ukgqB=;G!{ zf#If-ARIC-1I&(8`A+YKc5Tr81B8QwoY6~kN+jXf4*ymB%soZj!gcv4SNHsA=6sw$ zgZ@W|0^QiFv7xM^HEU*oCcGdr6ypXR)NCtA(M(6Eh%(7B!t?vPv77Hn()15v8-1kc z#4d6MzJesy_m!9oH()FB9@iSN69?vJ& HjcYlgJ_MrtWgdCAv_x*Ik8U7V)=f&x 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 z%0A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

    2`g+n`gCP7R3%ZHbh;0kk2~AS-B1qycL| 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%0D?#>vJJ#zDsJ#@5Dq##m!nV__pO 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

    as7>%YU}Ph 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�`Bz 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

    wjw7LBzroH_p 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%0D%5uZv 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%0ALX#NLT)lhc@yvlf8CT^4%yIVQ*Cy*9J^c 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 dvDXz2sWzdcyUPYm(~$*AUm8u0&To*KIDH^B3pW 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%0DQkBKcY~HmEh|njL%30zJ}zFT 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

    7n%g%7tatsT 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

  • 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 Q%?A~a-f_NJtn!%u2j4utrT_o{ diff --git a/.aider.tags.cache.v4/d7/41/5f8dde2b6955c58d88f39cdb650d.val b/.aider.tags.cache.v4/d7/41/5f8dde2b6955c58d88f39cdb650d.val deleted file mode 100644 index d45c92e4edd2e69db33cc1f232496ba9eede1f62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45747 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 Date: Mon, 14 Apr 2025 13:50:48 +0100 Subject: [PATCH 015/343] fix: tests --- app/controllers/general.php | 3 +- src/Appwrite/Network/Validator/Origin.php | 62 ++++++++++---------- src/Appwrite/Network/Validator/Redirect.php | 2 +- tests/unit/Network/Validators/OriginTest.php | 3 + 4 files changed, 38 insertions(+), 32 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 2e7833d9aa..be9b165ac9 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -734,7 +734,8 @@ App::init() $originValidator = new Origin($platforms); if ( - !$originValidator->isValid($origin) + !empty($origin) + && !$originValidator->isValid($origin) && \in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE]) && $route->getLabel('origin', false) !== '*' && empty($request->getHeader('x-appwrite-key', '')) diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 9a3d2d6e23..78d0db221b 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -3,6 +3,7 @@ namespace Appwrite\Network\Validator; use Appwrite\Network\Platform; +use Utopia\CLI\Console; use Utopia\Validator; use Utopia\Validator\Hostname; @@ -26,37 +27,32 @@ class Origin extends Validator /** - * Check if Redirect URI is valid. - * @param mixed $redirect The redirect URI. + * Check if Origin is valid. + * @param mixed $origin The Origin URI. * @return bool */ - public function isValid($redirect): bool + public function isValid($origin): bool { $this->scheme = null; $this->host = null; - if (!is_string($redirect) || empty($redirect)) { + if (!is_string($origin) || empty($origin)) { return false; } - $parts = $this->parseUrl($redirect); - $scheme = $parts['scheme']; - $host = $parts['host']; + $this->scheme = $this->parseScheme($origin); + $this->host = parse_url($origin, PHP_URL_HOST); - if (!empty($scheme) && in_array($scheme, $this->schemes, true)) { + if (!empty($this->scheme) && in_array($this->scheme, $this->schemes, true)) { return true; } - if (empty($host)) { - return true; - } else { - $validator = new Hostname($this->hostnames); - if ($validator->isValid($host)) { - return true; - } + if (!in_array($this->scheme, ['http', 'https'])) { + return false; } - return false; + $validator = new Hostname($this->hostnames); + return $validator->isValid($this->host); } /** @@ -66,7 +62,7 @@ class Origin extends Validator public function getDescription(): string { $platform = $this->scheme ? Platform::getNameByScheme($this->scheme) : null; - $host = $this->host ? '(' . htmlspecialchars($this->host) . ')' : ''; + $host = $this->host ? '(' . $this->host . ')' : ''; if (empty($this->host) && empty($this->scheme)) { return 'Invalid Origin.'; @@ -95,20 +91,26 @@ class Origin extends Validator } /** - * Parses a URI string to extract scheme and host. - * Stores extracted parts in $this->scheme and $this->host. - * @param string $uri - * @return array{scheme: string|null, host: string|null} + * Parses the scheme from a URI string. + * + * @param string $uri The URI string to parse. + * @return string|null The extracted scheme string (e.g., "http", "exp", "mailto") */ - protected function parseUrl(string $uri): array - { - if (str_ends_with($uri, '://')) { - $uri .= 'placeholder'; + function parseScheme(string $uri): ?string { + $uri = trim($uri); + if ($uri === '') { + return null; // No scheme in empty string + } + + $scheme = parse_url($uri, PHP_URL_SCHEME); + if ($scheme === false) { + if (preg_match('/^([a-z][a-z0-9+.-]*):/i', $uri, $matches)) { + return $matches[1]; + } else { + return null; + } + } else { + return $scheme; } - $scheme = \parse_url($uri, PHP_URL_SCHEME); - $host = \parse_url($uri, PHP_URL_HOST); - $this->scheme = $scheme ?: null; - $this->host = $host ?: null; - return ['scheme' => $this->scheme,'host' => $this->host]; } } diff --git a/src/Appwrite/Network/Validator/Redirect.php b/src/Appwrite/Network/Validator/Redirect.php index 58bb955ad2..43750f4cbd 100644 --- a/src/Appwrite/Network/Validator/Redirect.php +++ b/src/Appwrite/Network/Validator/Redirect.php @@ -13,7 +13,7 @@ class Redirect extends Origin public function getDescription(): string { $platform = $this->scheme ? Platform::getNameByScheme($this->scheme) : null; - $host = $this->host ? '(' . htmlspecialchars($this->host) . ')' : ''; + $host = $this->host ? '(' . $this->host . ')' : ''; if (empty($this->host) && empty($this->scheme)) { return 'Invalid URI.'; diff --git a/tests/unit/Network/Validators/OriginTest.php b/tests/unit/Network/Validators/OriginTest.php index 839960b671..989c06da71 100644 --- a/tests/unit/Network/Validators/OriginTest.php +++ b/tests/unit/Network/Validators/OriginTest.php @@ -50,6 +50,9 @@ class OriginTest extends TestCase ], ]); + $this->assertEquals(false, $validator->isValid('')); + $this->assertEquals(false, $validator->isValid('/')); + $this->assertEquals(true, $validator->isValid('https://localhost')); $this->assertEquals(true, $validator->isValid('http://localhost')); $this->assertEquals(true, $validator->isValid('http://localhost:80')); From e551e4ad5bebd29549b8d45612a912b3cd6cadb4 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 14 Apr 2025 14:23:01 +0100 Subject: [PATCH 016/343] chore: fmt --- src/Appwrite/Network/Validator/Origin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 78d0db221b..53598da324 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -3,7 +3,6 @@ namespace Appwrite\Network\Validator; use Appwrite\Network\Platform; -use Utopia\CLI\Console; use Utopia\Validator; use Utopia\Validator\Hostname; @@ -96,7 +95,8 @@ class Origin extends Validator * @param string $uri The URI string to parse. * @return string|null The extracted scheme string (e.g., "http", "exp", "mailto") */ - function parseScheme(string $uri): ?string { + public function parseScheme(string $uri): ?string + { $uri = trim($uri); if ($uri === '') { return null; // No scheme in empty string From 2427f950b51079783e418065cde8ad6483b0159c Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 14 Apr 2025 14:34:22 +0100 Subject: [PATCH 017/343] fix: realtime --- app/realtime.php | 6 +++--- tests/e2e/Services/Realtime/RealtimeBase.php | 18 ++---------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/app/realtime.php b/app/realtime.php index 86f9c85fdd..99b10384fd 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -508,7 +508,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, } $timelimit = $app->getResource('timelimit'); - $console = $app->getResource('console'); /** @var Document $console */ + $platforms = $app->getResource('platforms'); $user = $app->getResource('user'); /** @var Document $user */ /* @@ -533,9 +533,9 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, * Skip this check for non-web platforms which are not required to send an origin header. */ $origin = $request->getOrigin(); - $originValidator = new Origin(array_merge($project->getAttribute('platforms', []), $console->getAttribute('platforms', []))); + $originValidator = new Origin($platforms); - if (!$originValidator->isValid($origin) && $project->getId() !== 'console') { + if (!empty($origin) && !$originValidator->isValid($origin) && $project->getId() !== 'console') { throw new Exception(Exception::REALTIME_POLICY_VIOLATION, $originValidator->getDescription()); } diff --git a/tests/e2e/Services/Realtime/RealtimeBase.php b/tests/e2e/Services/Realtime/RealtimeBase.php index 99f31134c0..1350b305fc 100644 --- a/tests/e2e/Services/Realtime/RealtimeBase.php +++ b/tests/e2e/Services/Realtime/RealtimeBase.php @@ -16,13 +16,6 @@ trait RealtimeBase $projectId = $this->getProject()['$id']; } - $headers = array_merge( - [ - "Origin" => "appwrite.test", - ], - $headers - ); - $query = [ "project" => $projectId, "channels" => $channels, @@ -49,7 +42,7 @@ trait RealtimeBase public function testConnectionFailureMissingChannels(): void { - $client = $this->getWebsocket(); + $client = $this->getWebsocket([]); $payload = json_decode($client->receive(), true); $this->assertArrayHasKey("type", $payload); @@ -64,14 +57,7 @@ trait RealtimeBase public function testConnectionFailureUnknownProject(): void { - $client = new WebSocketClient( - "ws://appwrite-traefik/v1/realtime?project=123", - [ - "headers" => [ - "Origin" => "appwrite.test", - ], - ] - ); + $client = $this->getWebsocket(projectId: '123'); $payload = json_decode($client->receive(), true); $this->assertArrayHasKey("type", $payload); From 814be66b98f9bd09a31cc8298633cc230c74d86b Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 26 Apr 2025 16:05:07 +0530 Subject: [PATCH 018/343] update: use new terminologies on path params and local variables. --- app/controllers/api/databases.php | 1806 +++++++++++++++-------------- 1 file changed, 909 insertions(+), 897 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index c5d0e9e754..d3a34f56e8 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -66,11 +66,11 @@ use Utopia\Validator\URL; use Utopia\Validator\WhiteList; /** - * * Create attribute of varying type + * * Create column of varying type * * @param string $databaseId - * @param string $collectionId - * @param Document $attribute + * @param string $tableId + * @param Document $column * @param Response $response * @param Database $dbForProject * @param EventDatabase $queueForDatabase @@ -85,19 +85,19 @@ use Utopia\Validator\WhiteList; * @throws ConflictException * @throws Exception */ -function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): Document +function createColumn(string $databaseId, string $tableId, Document $column, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): Document { - $key = $attribute->getAttribute('key'); - $type = $attribute->getAttribute('type', ''); - $size = $attribute->getAttribute('size', 0); - $required = $attribute->getAttribute('required', true); - $signed = $attribute->getAttribute('signed', true); // integers are signed by default - $array = $attribute->getAttribute('array', false); - $format = $attribute->getAttribute('format', ''); - $formatOptions = $attribute->getAttribute('formatOptions', []); - $filters = $attribute->getAttribute('filters', []); // filters are hidden from the endpoint - $default = $attribute->getAttribute('default'); - $options = $attribute->getAttribute('options', []); + $key = $column->getAttribute('key'); + $type = $column->getAttribute('type', ''); + $size = $column->getAttribute('size', 0); + $required = $column->getAttribute('required', true); + $signed = $column->getAttribute('signed', true); // integers are signed by default + $array = $column->getAttribute('array', false); + $format = $column->getAttribute('format', ''); + $formatOptions = $column->getAttribute('formatOptions', []); + $filters = $column->getAttribute('filters', []); // filters are hidden from the endpoint + $default = $column->getAttribute('default'); + $options = $column->getAttribute('options', []); $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -105,43 +105,43 @@ function createAttribute(string $databaseId, string $collectionId, Document $att throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } if (!empty($format)) { if (!Structure::hasFormat($format, $type)) { - throw new Exception(Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, "Format {$format} not available for {$type} attributes."); + throw new Exception(Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, "Format {$format} not available for {$type} columns."); } } // Must throw here since dbForProject->createAttribute is performed by db worker if ($required && isset($default)) { - throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for required attribute'); + throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for required column'); } if ($array && isset($default)) { - throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array attributes'); + throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array columns'); } if ($type === Database::VAR_RELATIONSHIP) { $options['side'] = Database::RELATION_SIDE_PARENT; - $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection'] ?? ''); - if ($relatedCollection->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND, 'The related collection was not found.'); + $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection'] ?? ''); + if ($relatedTable->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND, 'The related table was not found.'); } } try { - $attribute = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), + $column = new Document([ + '$id' => ID::custom($db->getInternalId() . '_' . $table->getInternalId() . '_' . $key), 'key' => $key, 'databaseInternalId' => $db->getInternalId(), 'databaseId' => $db->getId(), - 'collectionInternalId' => $collection->getInternalId(), - 'collectionId' => $collectionId, + 'collectionInternalId' => $table->getInternalId(), + 'collectionId' => $tableId, 'type' => $type, 'status' => 'processing', // processing, available, failed, deleting, stuck 'size' => $size, @@ -155,35 +155,35 @@ function createAttribute(string $databaseId, string $collectionId, Document $att 'options' => $options, ]); - $dbForProject->checkAttribute($collection, $attribute); - $attribute = $dbForProject->createDocument('attributes', $attribute); + $dbForProject->checkAttribute($table, $column); + $column = $dbForProject->createDocument('attributes', $column); } catch (DuplicateException) { throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); } catch (LimitException) { throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); } catch (\Throwable $e) { - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $table->getInternalId()); throw $e; } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $table->getInternalId()); if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { $twoWayKey = $options['twoWayKey']; - $options['relatedCollection'] = $collection->getId(); + $options['relatedCollection'] = $table->getId(); $options['twoWayKey'] = $key; $options['side'] = Database::RELATION_SIDE_CHILD; try { $twoWayAttribute = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $twoWayKey), + '$id' => ID::custom($db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $twoWayKey), 'key' => $twoWayKey, 'databaseInternalId' => $db->getInternalId(), 'databaseId' => $db->getId(), - 'collectionInternalId' => $relatedCollection->getInternalId(), - 'collectionId' => $relatedCollection->getId(), + 'collectionInternalId' => $relatedTable->getInternalId(), + 'collectionId' => $relatedTable->getId(), 'type' => $type, 'status' => 'processing', // processing, available, failed, deleting, stuck 'size' => $size, @@ -197,45 +197,45 @@ function createAttribute(string $databaseId, string $collectionId, Document $att 'options' => $options, ]); - $dbForProject->checkAttribute($relatedCollection, $twoWayAttribute); + $dbForProject->checkAttribute($relatedTable, $twoWayAttribute); $dbForProject->createDocument('attributes', $twoWayAttribute); } catch (DuplicateException) { - $dbForProject->deleteDocument('attributes', $attribute->getId()); + $dbForProject->deleteDocument('attributes', $column->getId()); throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); } catch (LimitException) { - $dbForProject->deleteDocument('attributes', $attribute->getId()); + $dbForProject->deleteDocument('attributes', $column->getId()); throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); } catch (\Throwable $e) { - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); throw $e; } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); } $queueForDatabase ->setType(DATABASE_TYPE_CREATE_ATTRIBUTE) ->setDatabase($db) - ->setCollection($collection) - ->setDocument($attribute); + ->setCollection($table) + ->setDocument($column); $queueForEvents - ->setContext('collection', $collection) + ->setContext('table', $table) ->setContext('database', $db) ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collection->getId()) - ->setParam('attributeId', $attribute->getId()); + ->setParam('tableId', $table->getId()) + ->setParam('columnId', $column->getId()); $response->setStatusCode(Response::STATUS_CODE_CREATED); - return $attribute; + return $column; } -function updateAttribute( +function updateColumn( string $databaseId, - string $collectionId, + string $tableId, string $key, Database $dbForProject, Event $queueForEvents, @@ -256,59 +256,59 @@ function updateAttribute( throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $column = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); - if ($attribute->isEmpty()) { + if ($column->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } - if ($attribute->getAttribute('status') !== 'available') { + if ($column->getAttribute('status') !== 'available') { throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE); } - if ($attribute->getAttribute(('type') !== $type)) { + if ($column->getAttribute(('type') !== $type)) { throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID); } - if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute(('filter') !== $filter)) { + if ($column->getAttribute('type') === Database::VAR_STRING && $column->getAttribute(('filter') !== $filter)) { throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID); } if ($required && isset($default)) { - throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for required attribute'); + throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for required column'); } - if ($attribute->getAttribute('array', false) && isset($default)) { - throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array attributes'); + if ($column->getAttribute('array', false) && isset($default)) { + throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array columns'); } - $collectionId = 'database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId(); + $tableId = 'database_' . $db->getInternalId() . '_collection_' . $table->getInternalId(); - $attribute + $column ->setAttribute('default', $default) ->setAttribute('required', $required); if (!empty($size)) { - $attribute->setAttribute('size', $size); + $column->setAttribute('size', $size); } - switch ($attribute->getAttribute('format')) { + switch ($column->getAttribute('format')) { case APP_DATABASE_ATTRIBUTE_INT_RANGE: case APP_DATABASE_ATTRIBUTE_FLOAT_RANGE: - $min ??= $attribute->getAttribute('formatOptions')['min']; - $max ??= $attribute->getAttribute('formatOptions')['max']; + $min ??= $column->getAttribute('formatOptions')['min']; + $max ??= $column->getAttribute('formatOptions')['max']; if ($min > $max) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); } - if ($attribute->getAttribute('format') === APP_DATABASE_ATTRIBUTE_INT_RANGE) { + if ($column->getAttribute('format') === APP_DATABASE_ATTRIBUTE_INT_RANGE) { $validator = new Range($min, $max, Database::VAR_INTEGER); } else { $validator = new Range($min, $max, Database::VAR_FLOAT); @@ -326,7 +326,7 @@ function updateAttribute( 'min' => $min, 'max' => $max ]; - $attribute->setAttribute('formatOptions', $options); + $column->setAttribute('formatOptions', $options); break; case APP_DATABASE_ATTRIBUTE_ENUM: @@ -348,44 +348,44 @@ function updateAttribute( 'elements' => $elements ]; - $attribute->setAttribute('formatOptions', $options); + $column->setAttribute('formatOptions', $options); break; } if ($type === Database::VAR_RELATIONSHIP) { - $primaryDocumentOptions = \array_merge($attribute->getAttribute('options', []), $options); - $attribute->setAttribute('options', $primaryDocumentOptions); + $primaryRowOptions = \array_merge($column->getAttribute('options', []), $options); + $column->setAttribute('options', $primaryRowOptions); try { $dbForProject->updateRelationship( - collection: $collectionId, + collection: $tableId, id: $key, newKey: $newKey, - onDelete: $primaryDocumentOptions['onDelete'], + onDelete: $primaryRowOptions['onDelete'], ); } catch (NotFoundException) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } - if ($primaryDocumentOptions['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $primaryDocumentOptions['relatedCollection']); + if ($primaryRowOptions['twoWay']) { + $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $primaryRowOptions['relatedCollection']); - $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey']); + $relatedColumn = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $primaryRowOptions['twoWayKey']); if (!empty($newKey) && $newKey !== $key) { $options['twoWayKey'] = $newKey; } - $relatedOptions = \array_merge($relatedAttribute->getAttribute('options'), $options); - $relatedAttribute->setAttribute('options', $relatedOptions); - $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); + $relatedOptions = \array_merge($relatedColumn->getAttribute('options'), $options); + $relatedColumn->setAttribute('options', $relatedOptions); + $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $primaryRowOptions['twoWayKey'], $relatedColumn); - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); } } else { try { $dbForProject->updateAttribute( - collection: $collectionId, + collection: $tableId, id: $key, size: $size, required: $required, @@ -405,44 +405,44 @@ function updateAttribute( } if (!empty($newKey) && $key !== $newKey) { - $originalUid = $attribute->getId(); + $originalUid = $column->getId(); - $attribute - ->setAttribute('$id', ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $newKey)) + $column + ->setAttribute('$id', ID::custom($db->getInternalId() . '_' . $table->getInternalId() . '_' . $newKey)) ->setAttribute('key', $newKey); - $dbForProject->updateDocument('attributes', $originalUid, $attribute); + $dbForProject->updateDocument('attributes', $originalUid, $column); /** * @var Document $index */ - foreach ($collection->getAttribute('indexes') as $index) { + foreach ($table->getAttribute('indexes') as $index) { /** - * @var string[] $attributes + * @var string[] $columns */ - $attributes = $index->getAttribute('attributes', []); - $found = \array_search($key, $attributes); + $columns = $index->getAttribute('attributes', []); + $found = \array_search($key, $columns); if ($found !== false) { - $attributes[$found] = $newKey; - $index->setAttribute('attributes', $attributes); + $columns[$found] = $newKey; + $index->setAttribute('attributes', $columns); $dbForProject->updateDocument('indexes', $index->getId(), $index); } } } else { - $attribute = $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute); + $column = $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key, $column); } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collection->getId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $table->getId()); $queueForEvents - ->setContext('collection', $collection) + ->setContext('table', $table) ->setContext('database', $db) ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collection->getId()) - ->setParam('attributeId', $attribute->getId()); + ->setParam('tableId', $table->getId()) + ->setParam('columnId', $column->getId()); - return $attribute; + return $column; } App::init() @@ -845,18 +845,19 @@ App::delete('/v1/databases/:databaseId') $response->noContent(); }); -App::post('/v1/databases/:databaseId/collections') - ->desc('Create collection') +App::post('/v1/databases/:databaseId/tables') + ->alias('/v1/databases/:databaseId/collections') + ->desc('Create table') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].collections.[collectionId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'collection.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{response.$id}') + ->label('audits.event', 'table.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{response.$id}') ->label('sdk', new Method( namespace: 'databases', - group: 'collections', - name: 'createCollection', + group: 'tables', + name: 'createTable', description: '/docs/references/databases/create-collection.md', auth: [AuthType::KEY], responses: [ @@ -868,8 +869,8 @@ App::post('/v1/databases/:databaseId/collections') contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.') + ->param('tableId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('name', '', new Text(128), 'Table name. Max length: 128 chars.') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true) @@ -877,7 +878,7 @@ App::post('/v1/databases/:databaseId/collections') ->inject('dbForProject') ->inject('mode') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $queueForEvents) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -885,24 +886,24 @@ App::post('/v1/databases/:databaseId/collections') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collectionId = $collectionId == 'unique()' ? ID::unique() : $collectionId; + $tableId = $tableId == 'unique()' ? ID::unique() : $tableId; // Map aggregate permissions into the multiple permissions they represent. $permissions = Permission::aggregate($permissions) ?? []; try { - $collection = $dbForProject->createDocument('database_' . $database->getInternalId(), new Document([ - '$id' => $collectionId, + $table = $dbForProject->createDocument('database_' . $database->getInternalId(), new Document([ + '$id' => $tableId, 'databaseInternalId' => $database->getInternalId(), 'databaseId' => $databaseId, '$permissions' => $permissions, 'documentSecurity' => $documentSecurity, 'enabled' => $enabled, 'name' => $name, - 'search' => implode(' ', [$collectionId, $name]), + 'search' => implode(' ', [$tableId, $name]), ])); - $dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), permissions: $permissions, documentSecurity: $documentSecurity); + $dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), permissions: $permissions, documentSecurity: $documentSecurity); } catch (DuplicateException) { throw new Exception(Exception::COLLECTION_ALREADY_EXISTS); } catch (LimitException) { @@ -912,23 +913,23 @@ App::post('/v1/databases/:databaseId/collections') $queueForEvents ->setContext('database', $database) ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collection->getId()); + ->setParam('tableId', $table->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($collection, Response::MODEL_COLLECTION); + ->dynamic($table, Response::MODEL_COLLECTION); }); -App::get('/v1/databases/:databaseId/collections') - ->alias('/v1/database/collections') - ->desc('List collections') +App::get('/v1/databases/:databaseId/tables') + ->alias('/v1/databases/:databaseId/collections') + ->desc('List tables') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'collections', - name: 'listCollections', + group: 'tables', + name: 'listTables', description: '/docs/references/databases/list-collections.md', auth: [AuthType::KEY], responses: [ @@ -974,11 +975,11 @@ App::get('/v1/databases/:databaseId/collections') throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); } - $collectionId = $cursor->getValue(); - $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $tableId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Collection '{$collectionId}' for the 'cursor' value not found."); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Table '{$tableId}' for the 'cursor' value not found."); } $cursor->setValue($cursorDocument); @@ -987,27 +988,29 @@ App::get('/v1/databases/:databaseId/collections') $filterQueries = Query::groupByType($queries)['filters']; try { - $collections = $dbForProject->find('database_' . $database->getInternalId(), $queries); + $tables = $dbForProject->find('database_' . $database->getInternalId(), $queries); $total = $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT); } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } + + // TODO: collections > tables $response->dynamic(new Document([ - 'collections' => $collections, + 'collections' => $tables, 'total' => $total, ]), Response::MODEL_COLLECTION_LIST); }); -App::get('/v1/databases/:databaseId/collections/:collectionId') - ->alias('/v1/database/collections/:collectionId') - ->desc('Get collection') +App::get('/v1/databases/:databaseId/tables/:tableId') + ->alias('/v1/databases/:databaseId/collections/:tableId') + ->desc('Get table') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'collections', - name: 'getCollection', + group: 'tables', + name: 'getTable', description: '/docs/references/databases/get-collection.md', auth: [AuthType::KEY], responses: [ @@ -1019,11 +1022,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') - ->inject('mode') - ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, string $mode) { + ->action(function (string $databaseId, string $tableId, Response $response, Database $dbForProject) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1031,25 +1033,25 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $response->dynamic($collection, Response::MODEL_COLLECTION); + $response->dynamic($table, Response::MODEL_COLLECTION); }); -App::get('/v1/databases/:databaseId/collections/:collectionId/logs') - ->alias('/v1/database/collections/:collectionId/logs') - ->desc('List collection logs') +App::get('/v1/databases/:databaseId/tables/:tableId/logs') + ->alias('/v1/databases/:databaseId/collections/:tableId/logs') + ->desc('List table logs') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'collections', - name: 'listCollectionLogs', + group: 'tables', + name: 'listTableLogs', description: '/docs/references/databases/get-collection-logs.md', auth: [AuthType::ADMIN], responses: [ @@ -1061,13 +1063,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('tableId', '', new UID(), 'Table ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) ->inject('response') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + ->action(function (string $databaseId, string $tableId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1075,10 +1077,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + $tableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $tableDocument->getInternalId()); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -1095,7 +1097,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') ]); $audit = new Audit($dbForProject); - $resource = 'database/' . $databaseId . '/collection/' . $collectionId; + $resource = 'database/' . $databaseId . '/table/' . $tableId; $logs = $audit->getLogsByResource($resource, $queries); $output = []; @@ -1150,19 +1152,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') }); -App::put('/v1/databases/:databaseId/collections/:collectionId') - ->alias('/v1/database/collections/:collectionId') - ->desc('Update collection') +App::put('/v1/databases/:databaseId/tables/:tableId') + ->alias('/v1/databases/:databaseId/collections/:tableId') + ->desc('Update table') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].update') - ->label('audits.event', 'collection.update') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('event', 'databases.[databaseId].tables.[tableId].update') + ->label('audits.event', 'table.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'collections', - name: 'updateCollection', + group: 'tables', + name: 'updateTable', description: '/docs/references/databases/update-collection.md', auth: [AuthType::KEY], responses: [ @@ -1174,7 +1176,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('tableId', '', new UID(), 'Table ID.') ->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.') ->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('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) @@ -1183,7 +1185,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') ->inject('dbForProject') ->inject('mode') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $queueForEvents) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1191,53 +1193,53 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $permissions ??= $collection->getPermissions() ?? []; + $permissions ??= $table->getPermissions() ?? []; // Map aggregate permissions into the multiple permissions they represent. $permissions = Permission::aggregate($permissions); - $enabled ??= $collection->getAttribute('enabled', true); + $enabled ??= $table->getAttribute('enabled', true); - $collection = $dbForProject->updateDocument( + $table = $dbForProject->updateDocument( 'database_' . $database->getInternalId(), - $collectionId, - $collection + $tableId, + $table ->setAttribute('name', $name) ->setAttribute('$permissions', $permissions) ->setAttribute('documentSecurity', $documentSecurity) ->setAttribute('enabled', $enabled) - ->setAttribute('search', \implode(' ', [$collectionId, $name])) + ->setAttribute('search', \implode(' ', [$tableId, $name])) ); - $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity); + $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $permissions, $documentSecurity); $queueForEvents ->setContext('database', $database) ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collection->getId()); + ->setParam('tableId', $table->getId()); - $response->dynamic($collection, Response::MODEL_COLLECTION); + $response->dynamic($table, Response::MODEL_COLLECTION); }); -App::delete('/v1/databases/:databaseId/collections/:collectionId') - ->alias('/v1/database/collections/:collectionId') - ->desc('Delete collection') +App::delete('/v1/databases/:databaseId/tables/:tableId') + ->alias('/v1/databases/:databaseId/collections/:tableId') + ->desc('Delete table') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].delete') - ->label('audits.event', 'collection.delete') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('event', 'databases.[databaseId].tables.[tableId].delete') + ->label('audits.event', 'table.delete') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'collections', - name: 'deleteCollection', + group: 'tables', + name: 'deleteTable', description: '/docs/references/databases/delete-collection.md', auth: [AuthType::KEY], responses: [ @@ -1249,13 +1251,13 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') contentType: ContentType::NONE )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('mode') - ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, string $mode) { + ->action(function (string $databaseId, string $tableId, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, string $mode) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1263,45 +1265,45 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $collectionId)) { + if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $tableId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); } - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId()); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_COLLECTION) ->setDatabase($database) - ->setCollection($collection); + ->setCollection($table); $queueForEvents ->setContext('database', $database) ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collection->getId()) - ->setPayload($response->output($collection, Response::MODEL_COLLECTION)); + ->setParam('tableId', $table->getId()) + ->setPayload($response->output($table, Response::MODEL_COLLECTION)); $response->noContent(); }); -App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string') - ->alias('/v1/database/collections/:collectionId/attributes/string') - ->desc('Create string attribute') +App::post('/v1/databases/:databaseId/tables/:tableId/columns/string') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/string') + ->desc('Create string column') ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'attribute.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'createStringAttribute', + group: 'columns', + name: 'createStringColumn', description: '/docs/references/databases/create-string-attribute.md', auth: [AuthType::KEY], responses: [ @@ -1312,18 +1314,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') ->param('size', null, new Range(1, APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH, Range::TYPE_INTEGER), 'Attribute size for text attributes, in number of characters.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, new Text(0, 0), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) - ->param('array', false, new Boolean(), 'Is attribute an array?', true) - ->param('encrypt', false, new Boolean(), 'Toggle encryption for the attribute. Encryption enhances security by not storing any plain text values in the database. However, encrypted attributes cannot be queried.', true) + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Text(0, 0), 'Default value for column when not provided. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) + ->param('encrypt', false, new Boolean(), 'Toggle encryption for the column. Encryption enhances security by not storing any plain text values in the database. However, encrypted columns cannot be queried.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { // Ensure attribute default is within required size $validator = new Text($size, 0); @@ -1337,7 +1339,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string $filters[] = 'encrypt'; } - $attribute = createAttribute($databaseId, $collectionId, new Document([ + $column = createColumn($databaseId, $tableId, new Document([ 'key' => $key, 'type' => Database::VAR_STRING, 'size' => $size, @@ -1349,22 +1351,22 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_STRING); + ->dynamic($column, Response::MODEL_ATTRIBUTE_STRING); }); -App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email') - ->alias('/v1/database/collections/:collectionId/attributes/email') - ->desc('Create email attribute') +App::post('/v1/databases/:databaseId/tables/:tableId/columns/email') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/email') + ->desc('Create email column') ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'attribute.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'createEmailAttribute', + group: 'columns', + name: 'createEmailColumn', description: '/docs/references/databases/create-email-attribute.md', auth: [AuthType::KEY], responses: [ @@ -1375,18 +1377,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email' ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, new Email(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) - ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Email(), 'Default value for column when not provided. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - $attribute = createAttribute($databaseId, $collectionId, new Document([ + $column = createColumn($databaseId, $tableId, new Document([ 'key' => $key, 'type' => Database::VAR_STRING, 'size' => 254, @@ -1398,22 +1400,22 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email' $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_EMAIL); + ->dynamic($column, Response::MODEL_ATTRIBUTE_EMAIL); }); -App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') - ->alias('/v1/database/collections/:collectionId/attributes/enum') - ->desc('Create enum attribute') +App::post('/v1/databases/:databaseId/collections/:tableId/attributes/enum') + ->alias('/v1/database/collections/:tableId/attributes/enum') + ->desc('Create enum column') ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'attribute.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'createEnumAttribute', + group: 'columns', + name: 'createEnumColumn', description: '/docs/references/databases/create-attribute-enum.md', auth: [AuthType::KEY], responses: [ @@ -1424,22 +1426,22 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') ->param('elements', [], new ArrayList(new Text(DATABASE::LENGTH_KEY), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' elements are allowed, each ' . DATABASE::LENGTH_KEY . ' characters long.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, new Text(0), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) - ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Text(0), 'Default value for column when not provided. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $key, array $elements, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { if (!is_null($default) && !in_array($default, $elements)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements'); } - $attribute = createAttribute($databaseId, $collectionId, new Document([ + $column = createColumn($databaseId, $tableId, new Document([ 'key' => $key, 'type' => Database::VAR_STRING, 'size' => Database::LENGTH_KEY, @@ -1452,22 +1454,22 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_ENUM); + ->dynamic($column, Response::MODEL_ATTRIBUTE_ENUM); }); -App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') - ->alias('/v1/database/collections/:collectionId/attributes/ip') - ->desc('Create IP address attribute') +App::post('/v1/databases/:databaseId/tables/:tableId/columns/ip') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/ip') + ->desc('Create IP address column') ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'attribute.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'createIpAttribute', + group: 'columns', + name: 'createIpColumn', description: '/docs/references/databases/create-ip-attribute.md', auth: [AuthType::KEY], responses: [ @@ -1478,18 +1480,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, new IP(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) - ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new IP(), 'Default value for column when not provided. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - $attribute = createAttribute($databaseId, $collectionId, new Document([ + $column = createColumn($databaseId, $tableId, new Document([ 'key' => $key, 'type' => Database::VAR_STRING, 'size' => 39, @@ -1501,22 +1503,22 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_IP); + ->dynamic($column, Response::MODEL_ATTRIBUTE_IP); }); -App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url') - ->alias('/v1/database/collections/:collectionId/attributes/url') - ->desc('Create URL attribute') +App::post('/v1/databases/:databaseId/tables/:tableId/columns/url') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/url') + ->desc('Create URL column') ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'attribute.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'createUrlAttribute', + group: 'columns', + name: 'createUrlColumn', description: '/docs/references/databases/create-url-attribute.md', auth: [AuthType::KEY], responses: [ @@ -1527,18 +1529,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url') ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, new URL(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) - ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new URL(), 'Default value for column when not provided. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - $attribute = createAttribute($databaseId, $collectionId, new Document([ + $column = createColumn($databaseId, $tableId, new Document([ 'key' => $key, 'type' => Database::VAR_STRING, 'size' => 2000, @@ -1550,22 +1552,22 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url') $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_URL); + ->dynamic($column, Response::MODEL_ATTRIBUTE_URL); }); -App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/integer') - ->alias('/v1/database/collections/:collectionId/attributes/integer') - ->desc('Create integer attribute') +App::post('/v1/databases/:databaseId/tables/:tableId/columns/integer') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/integer') + ->desc('Create integer column') ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'attribute.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'createIntegerAttribute', + group: 'columns', + name: 'createIntegerColumn', description: '/docs/references/databases/create-integer-attribute.md', auth: [AuthType::KEY], responses: [ @@ -1576,18 +1578,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') ->param('min', null, new Integer(), 'Minimum value to enforce on new documents', true) ->param('max', null, new Integer(), 'Maximum value to enforce on new documents', true) - ->param('default', null, new Integer(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) - ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->param('default', null, new Integer(), 'Default value for column when not provided. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { // Ensure attribute default is within range $min ??= PHP_INT_MIN; @@ -1605,7 +1607,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege $size = $max > 2147483647 ? 8 : 4; // Automatically create BigInt depending on max value - $attribute = createAttribute($databaseId, $collectionId, new Document([ + $column = createColumn($databaseId, $tableId, new Document([ 'key' => $key, 'type' => Database::VAR_INTEGER, 'size' => $size, @@ -1619,31 +1621,31 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege ], ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - $formatOptions = $attribute->getAttribute('formatOptions', []); + $formatOptions = $column->getAttribute('formatOptions', []); if (!empty($formatOptions)) { - $attribute->setAttribute('min', \intval($formatOptions['min'])); - $attribute->setAttribute('max', \intval($formatOptions['max'])); + $column->setAttribute('min', \intval($formatOptions['min'])); + $column->setAttribute('max', \intval($formatOptions['max'])); } $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_INTEGER); + ->dynamic($column, Response::MODEL_ATTRIBUTE_INTEGER); }); -App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float') - ->alias('/v1/database/collections/:collectionId/attributes/float') - ->desc('Create float attribute') +App::post('/v1/databases/:databaseId/tables/:tableId/columns/float') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/float') + ->desc('Create float column') ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'attribute.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'createFloatAttribute', + group: 'columns', + name: 'createFloatColumn', description: '/docs/references/databases/create-float-attribute.md', auth: [AuthType::KEY], responses: [ @@ -1654,18 +1656,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') ->param('min', null, new FloatValidator(), 'Minimum value to enforce on new documents', true) ->param('max', null, new FloatValidator(), 'Maximum value to enforce on new documents', true) - ->param('default', null, new FloatValidator(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) - ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->param('default', null, new FloatValidator(), 'Default value for column when not provided. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { // Ensure attribute default is within range $min ??= -PHP_FLOAT_MAX; @@ -1681,7 +1683,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); } - $attribute = createAttribute($databaseId, $collectionId, new Document([ + $column = createColumn($databaseId, $tableId, new Document([ 'key' => $key, 'type' => Database::VAR_FLOAT, 'required' => $required, @@ -1695,31 +1697,31 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' ], ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - $formatOptions = $attribute->getAttribute('formatOptions', []); + $formatOptions = $column->getAttribute('formatOptions', []); if (!empty($formatOptions)) { - $attribute->setAttribute('min', \floatval($formatOptions['min'])); - $attribute->setAttribute('max', \floatval($formatOptions['max'])); + $column->setAttribute('min', \floatval($formatOptions['min'])); + $column->setAttribute('max', \floatval($formatOptions['max'])); } $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_FLOAT); + ->dynamic($column, Response::MODEL_ATTRIBUTE_FLOAT); }); -App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolean') - ->alias('/v1/database/collections/:collectionId/attributes/boolean') - ->desc('Create boolean attribute') +App::post('/v1/databases/:databaseId/tables/:tableId/columns/boolean') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/boolean') + ->desc('Create boolean column') ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'attribute.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'createBooleanAttribute', + group: 'columns', + name: 'createBooleanColumn', description: '/docs/references/databases/create-boolean-attribute.md', auth: [AuthType::KEY], responses: [ @@ -1730,18 +1732,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, new Boolean(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) - ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Boolean(), 'Default value for column when not provided. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - $attribute = createAttribute($databaseId, $collectionId, new Document([ + $column = createColumn($databaseId, $tableId, new Document([ 'key' => $key, 'type' => Database::VAR_BOOLEAN, 'size' => 0, @@ -1752,22 +1754,22 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_BOOLEAN); + ->dynamic($column, Response::MODEL_ATTRIBUTE_BOOLEAN); }); -App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/datetime') - ->alias('/v1/database/collections/:collectionId/attributes/datetime') - ->desc('Create datetime attribute') +App::post('/v1/databases/:databaseId/tables/:tableId/columns/datetime') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/datetime') + ->desc('Create datetime column') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'attribute.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'createDatetimeAttribute', + group: 'columns', + name: 'createDatetimeColumn', description: '/docs/references/databases/create-datetime-attribute.md', auth: [AuthType::KEY], responses: [ @@ -1778,20 +1780,20 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/dateti ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, fn (Database $dbForProject) => new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime()), 'Default value for the attribute in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.', true, ['dbForProject']) - ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, fn (Database $dbForProject) => new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime()), 'Default value for the attribute in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Cannot be set when column is required.', true, ['dbForProject']) + ->param('array', false, new Boolean(), 'Is column an array?', true) ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { $filters[] = 'datetime'; - $attribute = createAttribute($databaseId, $collectionId, new Document([ + $column = createColumn($databaseId, $tableId, new Document([ 'key' => $key, 'type' => Database::VAR_DATETIME, 'size' => 0, @@ -1803,22 +1805,22 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/dateti $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_DATETIME); + ->dynamic($column, Response::MODEL_ATTRIBUTE_DATETIME); }); -App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relationship') - ->alias('/v1/database/collections/:collectionId/attributes/relationship') - ->desc('Create relationship attribute') +App::post('/v1/databases/:databaseId/tables/:tableId/columns/relationship') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/relationship') + ->desc('Create relationship column') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'attribute.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'createRelationshipAttribute', + group: 'columns', + name: 'createRelationshipColumn', description: '/docs/references/databases/create-relationship-attribute.md', auth: [AuthType::KEY], responses: [ @@ -1829,12 +1831,12 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('relatedCollectionId', '', new UID(), 'Related Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('relatedTableId', '', new UID(), 'Related Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('type', '', new WhiteList([Database::RELATION_ONE_TO_ONE, Database::RELATION_MANY_TO_ONE, Database::RELATION_MANY_TO_MANY, Database::RELATION_ONE_TO_MANY], true), 'Relation type') ->param('twoWay', false, new Boolean(), 'Is Two Way?', true) - ->param('key', null, new Key(), 'Attribute Key.', true) - ->param('twoWayKey', null, new Key(), 'Two Way Attribute Key.', true) + ->param('key', null, new Key(), 'Column Key.', true) + ->param('twoWayKey', null, new Key(), 'Two Way Column Key.', true) ->param('onDelete', Database::RELATION_MUTATE_RESTRICT, new WhiteList([Database::RELATION_MUTATE_CASCADE, Database::RELATION_MUTATE_RESTRICT, Database::RELATION_MUTATE_SET_NULL], true), 'Constraints option', true) ->inject('response') ->inject('dbForProject') @@ -1842,8 +1844,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati ->inject('queueForEvents') ->action(function ( string $databaseId, - string $collectionId, - string $relatedCollectionId, + string $tableId, + string $relatedTableId, string $type, bool $twoWay, ?string $key, @@ -1854,8 +1856,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati EventDatabase $queueForDatabase, Event $queueForEvents ) { - $key ??= $relatedCollectionId; - $twoWayKey ??= $collectionId; + $key ??= $relatedTableId; + $twoWayKey ??= $tableId; $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1863,34 +1865,34 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId()); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $relatedCollectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); - $relatedCollection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollectionDocument->getInternalId()); + $relatedTableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId); + $relatedTable = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $relatedTableDocument->getInternalId()); - if ($relatedCollection->isEmpty()) { + if ($relatedTable->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attributes = $collection->getAttribute('attributes', []); - /** @var Document[] $attributes */ - foreach ($attributes as $attribute) { - if ($attribute->getAttribute('type') !== Database::VAR_RELATIONSHIP) { + $columns = $table->getAttribute('attributes', []); + /** @var Document[] $columns */ + foreach ($columns as $column) { + if ($column->getAttribute('type') !== Database::VAR_RELATIONSHIP) { continue; } - if (\strtolower($attribute->getId()) === \strtolower($key)) { + if (\strtolower($column->getId()) === \strtolower($key)) { throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); } if ( - \strtolower($attribute->getAttribute('options')['twoWayKey']) === \strtolower($twoWayKey) && - $attribute->getAttribute('options')['relatedCollection'] === $relatedCollection->getId() + \strtolower($column->getAttribute('options')['twoWayKey']) === \strtolower($twoWayKey) && + $column->getAttribute('options')['relatedCollection'] === $relatedTable->getId() ) { // Console should provide a unique twoWayKey input! throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.'); @@ -1898,16 +1900,16 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati if ( $type === Database::RELATION_MANY_TO_MANY && - $attribute->getAttribute('options')['relationType'] === Database::RELATION_MANY_TO_MANY && - $attribute->getAttribute('options')['relatedCollection'] === $relatedCollection->getId() + $column->getAttribute('options')['relationType'] === Database::RELATION_MANY_TO_MANY && + $column->getAttribute('options')['relatedCollection'] === $relatedTable->getId() ) { - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Creating more than one "manyToMany" relationship on the same collection is currently not permitted.'); + throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Creating more than one "manyToMany" relationship on the same table is currently not permitted.'); } } - $attribute = createAttribute( + $column = createColumn( $databaseId, - $collectionId, + $tableId, new Document([ 'key' => $key, 'type' => Database::VAR_RELATIONSHIP, @@ -1917,7 +1919,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati 'array' => false, 'filters' => [], 'options' => [ - 'relatedCollection' => $relatedCollectionId, + 'relatedCollection' => $relatedTableId, 'relationType' => $type, 'twoWay' => $twoWay, 'twoWayKey' => $twoWayKey, @@ -1930,27 +1932,27 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati $queueForEvents ); - $options = $attribute->getAttribute('options', []); + $options = $column->getAttribute('options', []); foreach ($options as $key => $option) { - $attribute->setAttribute($key, $option); + $column->setAttribute($key, $option); } $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_RELATIONSHIP); + ->dynamic($column, Response::MODEL_ATTRIBUTE_RELATIONSHIP); }); -App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') - ->alias('/v1/database/collections/:collectionId/attributes') - ->desc('List attributes') +App::get('/v1/databases/:databaseId/tables/:tableId/columns') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes') + ->desc('List columns') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'listAttributes', + group: 'columns', + name: 'listColumns', description: '/docs/references/databases/list-attributes.md', auth: [AuthType::KEY], responses: [ @@ -1961,11 +1963,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { + ->action(function (string $databaseId, string $tableId, array $queries, Response $response, Database $dbForProject) { /** @var Document $database */ $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -1973,9 +1975,9 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -1984,7 +1986,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') \array_push( $queries, Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$collection->getInternalId()]), + Query::equal('collectionInternalId', [$table->getInternalId()]), ); /** @@ -2002,16 +2004,16 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); } - $attributeId = $cursor->getValue(); + $columnId = $cursor->getValue(); $cursorDocument = Authorization::skip(fn () => $dbForProject->find('attributes', [ Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$collection->getInternalId()]), - Query::equal('key', [$attributeId]), + Query::equal('collectionInternalId', [$table->getInternalId()]), + Query::equal('key', [$columnId]), Query::limit(1), ])); if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Attribute '{$attributeId}' for the 'cursor' value not found."); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Column '{$columnId}' for the 'cursor' value not found."); } $cursor->setValue($cursorDocument[0]); @@ -2019,28 +2021,28 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') $filters = Query::groupByType($queries)['filters']; try { - $attributes = $dbForProject->find('attributes', $queries); + $columns = $dbForProject->find('attributes', $queries); $total = $dbForProject->count('attributes', $filters, APP_LIMIT_COUNT); } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); } $response->dynamic(new Document([ - 'attributes' => $attributes, + 'attributes' => $columns, 'total' => $total, ]), Response::MODEL_ATTRIBUTE_LIST); }); -App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') - ->alias('/v1/database/collections/:collectionId/attributes/:key') - ->desc('Get attribute') +App::get('/v1/databases/:databaseId/tables/:tableId/columns/:key') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/:key') + ->desc('Get column') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'getAttribute', + group: 'columns', + name: 'getColumn', description: '/docs/references/databases/get-attribute.md', auth: [AuthType::KEY], responses: [ @@ -2062,11 +2064,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') ->inject('response') ->inject('dbForProject') - ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject) { + ->action(function (string $databaseId, string $tableId, string $key, Response $response, Database $dbForProject) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -2074,25 +2076,25 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $column = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $table->getInternalId() . '_' . $key); - if ($attribute->isEmpty()) { + if ($column->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } // Select response model based on type and format - $type = $attribute->getAttribute('type'); - $format = $attribute->getAttribute('format'); - $options = $attribute->getAttribute('options', []); + $type = $column->getAttribute('type'); + $format = $column->getAttribute('format'); + $options = $column->getAttribute('options', []); foreach ($options as $key => $option) { - $attribute->setAttribute($key, $option); + $column->setAttribute($key, $option); } $model = match ($type) { @@ -2111,21 +2113,22 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') default => Response::MODEL_ATTRIBUTE, }; - $response->dynamic($attribute, $model); + $response->dynamic($column, $model); }); -App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/string/:key') - ->desc('Update string attribute') +App::patch('/v1/databases/:databaseId/tables/:tableId/columns/string/:key') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/string/:key') + ->desc('Update string column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') - ->label('audits.event', 'attribute.update') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'updateStringAttribute', + group: 'columns', + name: 'updateStringColumn', description: '/docs/references/databases/update-string-attribute.md', auth: [AuthType::KEY], responses: [ @@ -2137,20 +2140,20 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/strin contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, new Nullable(new Text(0, 0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Nullable(new Text(0, 0)), 'Default value for column when not provided. Cannot be set when column is required.') ->param('size', null, new Range(1, APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH, Range::TYPE_INTEGER), 'Maximum size of the string attribute.', true) - ->param('newKey', null, new Key(), 'New attribute key.', true) + ->param('newKey', null, new Key(), 'New Column Key.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?int $size, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?int $size, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $attribute = updateAttribute( + $column = updateColumn( databaseId: $databaseId, - collectionId: $collectionId, + tableId: $tableId, key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, @@ -2163,21 +2166,22 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/strin $response ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_STRING); + ->dynamic($column, Response::MODEL_ATTRIBUTE_STRING); }); -App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/email/:key') - ->desc('Update email attribute') +App::patch('/v1/databases/:databaseId/tables/:tableId/columns/email/:key') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/email/:key') + ->desc('Update email column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') - ->label('audits.event', 'attribute.update') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'updateEmailAttribute', + group: 'columns', + name: 'updateEmailColumn', description: '/docs/references/databases/update-email-attribute.md', auth: [AuthType::KEY], responses: [ @@ -2189,18 +2193,18 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/email contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, new Nullable(new Email()), 'Default value for attribute when not provided. Cannot be set when attribute is required.') - ->param('newKey', null, new Key(), 'New attribute key.', true) + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Nullable(new Email()), 'Default value for column when not provided. Cannot be set when column is required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $attribute = updateAttribute( + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { + $column = updateColumn( databaseId: $databaseId, - collectionId: $collectionId, + tableId: $tableId, key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, @@ -2213,21 +2217,22 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/email $response ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_EMAIL); + ->dynamic($column, Response::MODEL_ATTRIBUTE_EMAIL); }); -App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/enum/:key') - ->desc('Update enum attribute') +App::patch('/v1/databases/:databaseId/tables/:tableId/columns/enum/:key') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/enum/:key') + ->desc('Update enum column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') - ->label('audits.event', 'attribute.update') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'updateEnumAttribute', + group: 'columns', + name: 'updateEnumColumn', description: '/docs/references/databases/update-enum-attribute.md', auth: [AuthType::KEY], responses: [ @@ -2239,19 +2244,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/enum/ contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') ->param('elements', null, new ArrayList(new Text(DATABASE::LENGTH_KEY), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' elements are allowed, each ' . DATABASE::LENGTH_KEY . ' characters long.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, new Nullable(new Text(0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.') - ->param('newKey', null, new Key(), 'New attribute key.', true) + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Nullable(new Text(0)), 'Default value for column when not provided. Cannot be set when column is required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $attribute = updateAttribute( + ->action(function (string $databaseId, string $tableId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { + $column = updateColumn( databaseId: $databaseId, - collectionId: $collectionId, + tableId: $tableId, key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, @@ -2265,21 +2270,22 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/enum/ $response ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_ENUM); + ->dynamic($column, Response::MODEL_ATTRIBUTE_ENUM); }); -App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/ip/:key') - ->desc('Update IP address attribute') +App::patch('/v1/databases/:databaseId/tables/:tableId/columns/ip/:key') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/ip/:key') + ->desc('Update IP address column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') - ->label('audits.event', 'attribute.update') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'updateIpAttribute', + group: 'columns', + name: 'updateIpColumn', description: '/docs/references/databases/update-ip-attribute.md', auth: [AuthType::KEY], responses: [ @@ -2291,18 +2297,18 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/ip/:k contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, new Nullable(new IP()), 'Default value for attribute when not provided. Cannot be set when attribute is required.') - ->param('newKey', null, new Key(), 'New attribute key.', true) + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Nullable(new IP()), 'Default value for column when not provided. Cannot be set when column is required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $attribute = updateAttribute( + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { + $column = updateColumn( databaseId: $databaseId, - collectionId: $collectionId, + tableId: $tableId, key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, @@ -2315,21 +2321,22 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/ip/:k $response ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_IP); + ->dynamic($column, Response::MODEL_ATTRIBUTE_IP); }); -App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/url/:key') - ->desc('Update URL attribute') +App::patch('/v1/databases/:databaseId/tables/:tableId/columns/url/:key') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/url/:key') + ->desc('Update URL column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') - ->label('audits.event', 'attribute.update') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'updateUrlAttribute', + group: 'columns', + name: 'updateUrlColumn', description: '/docs/references/databases/update-url-attribute.md', auth: [AuthType::KEY], responses: [ @@ -2341,18 +2348,18 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/url/: contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, new Nullable(new URL()), 'Default value for attribute when not provided. Cannot be set when attribute is required.') - ->param('newKey', null, new Key(), 'New attribute key.', true) + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Nullable(new URL()), 'Default value for column when not provided. Cannot be set when column is required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $attribute = updateAttribute( + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { + $column = updateColumn( databaseId: $databaseId, - collectionId: $collectionId, + tableId: $tableId, key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, @@ -2365,21 +2372,22 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/url/: $response ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_URL); + ->dynamic($column, Response::MODEL_ATTRIBUTE_URL); }); -App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/integer/:key') - ->desc('Update integer attribute') +App::patch('/v1/databases/:databaseId/tables/:tableId/columns/integer/:key') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/integer/:key') + ->desc('Update integer column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') - ->label('audits.event', 'attribute.update') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'updateIntegerAttribute', + group: 'columns', + name: 'updateIntegerColumn', description: '/docs/references/databases/update-integer-attribute.md', auth: [AuthType::KEY], responses: [ @@ -2391,20 +2399,20 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/integ contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') ->param('min', null, new Integer(), 'Minimum value to enforce on new documents', true) ->param('max', null, new Integer(), 'Maximum value to enforce on new documents', true) - ->param('default', null, new Nullable(new Integer()), 'Default value for attribute when not provided. Cannot be set when attribute is required.') - ->param('newKey', null, new Key(), 'New attribute key.', true) + ->param('default', null, new Nullable(new Integer()), 'Default value for column when not provided. Cannot be set when column is required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $attribute = updateAttribute( + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { + $column = updateColumn( databaseId: $databaseId, - collectionId: $collectionId, + tableId: $tableId, key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, @@ -2416,30 +2424,31 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/integ newKey: $newKey ); - $formatOptions = $attribute->getAttribute('formatOptions', []); + $formatOptions = $column->getAttribute('formatOptions', []); if (!empty($formatOptions)) { - $attribute->setAttribute('min', \intval($formatOptions['min'])); - $attribute->setAttribute('max', \intval($formatOptions['max'])); + $column->setAttribute('min', \intval($formatOptions['min'])); + $column->setAttribute('max', \intval($formatOptions['max'])); } $response ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_INTEGER); + ->dynamic($column, Response::MODEL_ATTRIBUTE_INTEGER); }); -App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/float/:key') - ->desc('Update float attribute') +App::patch('/v1/databases/:databaseId/tables/:tableId/columns/float/:key') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/float/:key') + ->desc('Update float column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') - ->label('audits.event', 'attribute.update') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'updateFloatAttribute', + group: 'columns', + name: 'updateFloatColumn', description: '/docs/references/databases/update-float-attribute.md', auth: [AuthType::KEY], responses: [ @@ -2451,20 +2460,20 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/float contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') ->param('min', null, new FloatValidator(), 'Minimum value to enforce on new documents', true) ->param('max', null, new FloatValidator(), 'Maximum value to enforce on new documents', true) - ->param('default', null, new Nullable(new FloatValidator()), 'Default value for attribute when not provided. Cannot be set when attribute is required.') - ->param('newKey', null, new Key(), 'New attribute key.', true) + ->param('default', null, new Nullable(new FloatValidator()), 'Default value for column when not provided. Cannot be set when column is required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $attribute = updateAttribute( + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { + $column = updateColumn( databaseId: $databaseId, - collectionId: $collectionId, + tableId: $tableId, key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, @@ -2476,30 +2485,31 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/float newKey: $newKey ); - $formatOptions = $attribute->getAttribute('formatOptions', []); + $formatOptions = $column->getAttribute('formatOptions', []); if (!empty($formatOptions)) { - $attribute->setAttribute('min', \floatval($formatOptions['min'])); - $attribute->setAttribute('max', \floatval($formatOptions['max'])); + $column->setAttribute('min', \floatval($formatOptions['min'])); + $column->setAttribute('max', \floatval($formatOptions['max'])); } $response ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_FLOAT); + ->dynamic($column, Response::MODEL_ATTRIBUTE_FLOAT); }); -App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/boolean/:key') - ->desc('Update boolean attribute') +App::patch('/v1/databases/:databaseId/tables/:tableId/columns/boolean/:key') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/boolean/:key') + ->desc('Update boolean column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') - ->label('audits.event', 'attribute.update') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'updateBooleanAttribute', + group: 'columns', + name: 'updateBooleanColumn', description: '/docs/references/databases/update-boolean-attribute.md', auth: [AuthType::KEY], responses: [ @@ -2511,18 +2521,18 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/boole contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, new Nullable(new Boolean()), 'Default value for attribute when not provided. Cannot be set when attribute is required.') - ->param('newKey', null, new Key(), 'New attribute key.', true) + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Nullable(new Boolean()), 'Default value for column when not provided. Cannot be set when column is required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $attribute = updateAttribute( + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { + $column = updateColumn( databaseId: $databaseId, - collectionId: $collectionId, + tableId: $tableId, key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, @@ -2534,21 +2544,22 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/boole $response ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_BOOLEAN); + ->dynamic($column, Response::MODEL_ATTRIBUTE_BOOLEAN); }); -App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/datetime/:key') - ->desc('Update dateTime attribute') +App::patch('/v1/databases/:databaseId/tables/:tableId/columns/datetime/:key') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/datetime/:key') + ->desc('Update dateTime column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') - ->label('audits.event', 'attribute.update') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'updateDatetimeAttribute', + group: 'columns', + name: 'updateDatetimeColumn', description: '/docs/references/databases/update-datetime-attribute.md', auth: [AuthType::KEY], responses: [ @@ -2560,18 +2571,18 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/datet contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') - ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('default', null, fn (Database $dbForProject) => new Nullable(new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime())), 'Default value for attribute when not provided. Cannot be set when attribute is required.', injections: ['dbForProject']) - ->param('newKey', null, new Key(), 'New attribute key.', true) + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, fn (Database $dbForProject) => new Nullable(new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime())), 'Default value for column when not provided. Cannot be set when column is required.', injections: ['dbForProject']) + ->param('newKey', null, new Key(), 'New Column Key.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $attribute = updateAttribute( + ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { + $column = updateColumn( databaseId: $databaseId, - collectionId: $collectionId, + tableId: $tableId, key: $key, dbForProject: $dbForProject, queueForEvents: $queueForEvents, @@ -2583,21 +2594,22 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/datet $response ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_DATETIME); + ->dynamic($column, Response::MODEL_ATTRIBUTE_DATETIME); }); -App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/relationship') - ->desc('Update relationship attribute') +App::patch('/v1/databases/:databaseId/tables/:tableId/columns/:key/relationship') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/:key/relationship') + ->desc('Update relationship column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') - ->label('audits.event', 'attribute.update') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'updateRelationshipAttribute', + group: 'columns', + name: 'updateRelationshipColumn', description: '/docs/references/databases/update-relationship-attribute.md', auth: [AuthType::KEY], responses: [ @@ -2609,16 +2621,16 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/ contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') ->param('onDelete', null, new WhiteList([Database::RELATION_MUTATE_CASCADE, Database::RELATION_MUTATE_RESTRICT, Database::RELATION_MUTATE_SET_NULL], true), 'Constraints option', true) - ->param('newKey', null, new Key(), 'New attribute key.', true) + ->param('newKey', null, new Key(), 'New Column Key.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') ->action(function ( string $databaseId, - string $collectionId, + string $tableId, string $key, ?string $onDelete, ?string $newKey, @@ -2626,9 +2638,9 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/ Database $dbForProject, Event $queueForEvents ) { - $attribute = updateAttribute( + $column = updateColumn( $databaseId, - $collectionId, + $tableId, $key, $dbForProject, $queueForEvents, @@ -2640,30 +2652,30 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/ newKey: $newKey ); - $options = $attribute->getAttribute('options', []); + $options = $column->getAttribute('options', []); foreach ($options as $key => $option) { - $attribute->setAttribute($key, $option); + $column->setAttribute($key, $option); } $response ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_RELATIONSHIP); + ->dynamic($column, Response::MODEL_ATTRIBUTE_RELATIONSHIP); }); -App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') - ->alias('/v1/database/collections/:collectionId/attributes/:key') - ->desc('Delete attribute') +App::delete('/v1/databases/:databaseId/tables/:tableId/columns/:key') + ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/:key') + ->desc('Delete column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') - ->label('audits.event', 'attribute.delete') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.delete') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'deleteAttribute', + group: 'columns', + name: 'deleteColumn', description: '/docs/references/databases/delete-attribute.md', auth: [AuthType::KEY], responses: [ @@ -2675,29 +2687,29 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key contentType: ContentType::NONE )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Attribute Key.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, StatsUsage $queueForStatsUsage) { + ->action(function (string $databaseId, string $tableId, string $key, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, StatsUsage $queueForStatsUsage) { $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $column = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); - if ($attribute->isEmpty()) { + if ($column->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } @@ -2705,55 +2717,55 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key * Check index dependency */ $validator = new IndexDependencyValidator( - $collection->getAttribute('indexes'), + $table->getAttribute('indexes'), $dbForProject->getAdapter()->getSupportForCastIndexArray(), ); - if (! $validator->isValid($attribute)) { + if (! $validator->isValid($column)) { throw new Exception(Exception::INDEX_DEPENDENCY); } // Only update status if removing available attribute - if ($attribute->getAttribute('status') === 'available') { - $attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting')); + if ($column->getAttribute('status') === 'available') { + $column = $dbForProject->updateDocument('attributes', $column->getId(), $column->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $table->getInternalId()); - if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { - $options = $attribute->getAttribute('options'); + if ($column->getAttribute('type') === Database::VAR_RELATIONSHIP) { + $options = $column->getAttribute('options'); if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection']); + $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection']); - if ($relatedCollection->isEmpty()) { + if ($relatedTable->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + $relatedColumn = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $options['twoWayKey']); - if ($relatedAttribute->isEmpty()) { + if ($relatedColumn->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } - if ($relatedAttribute->getAttribute('status') === 'available') { - $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'deleting')); + if ($relatedColumn->getAttribute('status') === 'available') { + $dbForProject->updateDocument('attributes', $relatedColumn->getId(), $relatedColumn->setAttribute('status', 'deleting')); } $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); } } $queueForDatabase ->setType(DATABASE_TYPE_DELETE_ATTRIBUTE) - ->setCollection($collection) + ->setCollection($table) ->setDatabase($db) - ->setDocument($attribute); + ->setDocument($column); // Select response model based on type and format - $type = $attribute->getAttribute('type'); - $format = $attribute->getAttribute('format'); + $type = $column->getAttribute('type'); + $format = $column->getAttribute('format'); $model = match ($type) { Database::VAR_BOOLEAN => Response::MODEL_ATTRIBUTE_BOOLEAN, @@ -2773,27 +2785,27 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key $queueForEvents ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collection->getId()) - ->setParam('attributeId', $attribute->getId()) - ->setContext('collection', $collection) + ->setParam('tableId', $table->getId()) + ->setParam('columnId', $column->getId()) + ->setContext('table', $table) ->setContext('database', $db) - ->setPayload($response->output($attribute, $model)); + ->setPayload($response->output($column, $model)); $response->noContent(); }); -App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') - ->alias('/v1/database/collections/:collectionId/indexes') +App::post('/v1/databases/:databaseId/tables/:tableId/indexes') + ->alias('/v1/databases/:databaseId/collections/:tableId/indexes') ->desc('Create index') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'index.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'collections', + group: 'tables', name: 'createIndex', description: '/docs/references/databases/create-index.md', auth: [AuthType::KEY], @@ -2806,16 +2818,16 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', null, new Key(), 'Index Key.') ->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE]), 'Index type.') - ->param('attributes', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' attributes are allowed, each 32 characters long.') + ->param('columns', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of columns to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' columns are allowed, each 32 characters long.') ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $key, string $type, array $columns, array $orders, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -2823,14 +2835,14 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } $count = $dbForProject->count('indexes', [ - Query::equal('collectionInternalId', [$collection->getInternalId()]), + Query::equal('collectionInternalId', [$table->getInternalId()]), Query::equal('databaseInternalId', [$db->getInternalId()]) ], 61); @@ -2841,9 +2853,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') } // Convert Document[] to array of attribute metadata - $oldAttributes = \array_map(fn ($a) => $a->getArrayCopy(), $collection->getAttribute('attributes')); + $oldColumns = \array_map(fn ($a) => $a->getArrayCopy(), $table->getAttribute('attributes')); - $oldAttributes[] = [ + $oldColumns[] = [ 'key' => '$id', 'type' => Database::VAR_STRING, 'status' => 'available', @@ -2853,7 +2865,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') 'size' => Database::LENGTH_KEY ]; - $oldAttributes[] = [ + $oldColumns[] = [ 'key' => '$createdAt', 'type' => Database::VAR_DATETIME, 'status' => 'available', @@ -2864,7 +2876,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') 'size' => 0 ]; - $oldAttributes[] = [ + $oldColumns[] = [ 'key' => '$updatedAt', 'type' => Database::VAR_DATETIME, 'status' => 'available', @@ -2878,51 +2890,51 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') // lengths hidden by default $lengths = []; - foreach ($attributes as $i => $attribute) { + foreach ($columns as $i => $column) { // find attribute metadata in collection document - $attributeIndex = \array_search($attribute, array_column($oldAttributes, 'key')); + $columnIndex = \array_search($column, array_column($oldColumns, 'key')); - if ($attributeIndex === false) { - throw new Exception(Exception::ATTRIBUTE_UNKNOWN, 'Unknown attribute: ' . $attribute . '. Verify the attribute name or create the attribute.'); + if ($columnIndex === false) { + throw new Exception(Exception::ATTRIBUTE_UNKNOWN, 'Unknown column: ' . $column . '. Verify the column name or create the column.'); } - $attributeStatus = $oldAttributes[$attributeIndex]['status']; - $attributeType = $oldAttributes[$attributeIndex]['type']; - $attributeArray = $oldAttributes[$attributeIndex]['array'] ?? false; + $columnStatus = $oldColumns[$columnIndex]['status']; + $columnType = $oldColumns[$columnIndex]['type']; + $columnArray = $oldColumns[$columnIndex]['array'] ?? false; - if ($attributeType === Database::VAR_RELATIONSHIP) { - throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Cannot create an index for a relationship attribute: ' . $oldAttributes[$attributeIndex]['key']); + if ($columnType === Database::VAR_RELATIONSHIP) { + throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Cannot create an index for a relationship column: ' . $oldColumns[$columnIndex]['key']); } // ensure attribute is available - if ($attributeStatus !== 'available') { - throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Attribute not available: ' . $oldAttributes[$attributeIndex]['key']); + if ($columnStatus !== 'available') { + throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Column not available: ' . $oldColumns[$columnIndex]['key']); } $lengths[$i] = null; - if ($attributeArray === true) { + if ($columnArray === true) { $lengths[$i] = Database::ARRAY_INDEX_LENGTH; $orders[$i] = null; } } $index = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), + '$id' => ID::custom($db->getInternalId() . '_' . $table->getInternalId() . '_' . $key), 'key' => $key, 'status' => 'processing', // processing, available, failed, deleting, stuck 'databaseInternalId' => $db->getInternalId(), 'databaseId' => $databaseId, - 'collectionInternalId' => $collection->getInternalId(), - 'collectionId' => $collectionId, + 'collectionInternalId' => $table->getInternalId(), + 'collectionId' => $tableId, 'type' => $type, - 'attributes' => $attributes, + 'attributes' => $columns, 'lengths' => $lengths, 'orders' => $orders, ]); $validator = new IndexValidator( - $collection->getAttribute('attributes'), + $table->getAttribute('attributes'), $dbForProject->getAdapter()->getMaxIndexLength(), $dbForProject->getAdapter()->getInternalIndexesKeys(), ); @@ -2936,19 +2948,19 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::INDEX_ALREADY_EXISTS); } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); $queueForDatabase ->setType(DATABASE_TYPE_CREATE_INDEX) ->setDatabase($db) - ->setCollection($collection) + ->setCollection($table) ->setDocument($index); $queueForEvents ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collection->getId()) + ->setParam('tableId', $table->getId()) ->setParam('indexId', $index->getId()) - ->setContext('collection', $collection) + ->setContext('table', $table) ->setContext('database', $db); $response @@ -2956,8 +2968,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') ->dynamic($index, Response::MODEL_INDEX); }); -App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') - ->alias('/v1/database/collections/:collectionId/indexes') +App::get('/v1/databases/:databaseId/tables/:tableId/indexes') + ->alias('/v1/databases/:databaseId/collections/:tableId/indexes') ->desc('List indexes') ->groups(['api', 'database']) ->label('scope', 'collections.read') @@ -2977,11 +2989,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { + ->action(function (string $databaseId, string $tableId, array $queries, Response $response, Database $dbForProject) { /** @var Document $database */ $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -2989,9 +3001,9 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -3000,7 +3012,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') \array_push( $queries, Query::equal('databaseId', [$databaseId]), - Query::equal('collectionId', [$collectionId]), + Query::equal('collectionId', [$tableId]), ); /** @@ -3019,7 +3031,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') $indexId = $cursor->getValue(); $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ - Query::equal('collectionInternalId', [$collection->getInternalId()]), + Query::equal('collectionInternalId', [$table->getInternalId()]), Query::equal('databaseInternalId', [$database->getInternalId()]), Query::equal('key', [$indexId]), Query::limit(1) @@ -3037,7 +3049,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') $total = $dbForProject->count('indexes', $filterQueries, APP_LIMIT_COUNT); $indexes = $dbForProject->find('indexes', $queries); } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); } $response->dynamic(new Document([ @@ -3046,8 +3058,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') ]), Response::MODEL_INDEX_LIST); }); -App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') - ->alias('/v1/database/collections/:collectionId/indexes/:key', ['databaseId' => 'default']) +App::get('/v1/databases/:databaseId/tables/:tableId/indexes/:key') + ->alias('/v1/databases/:databaseId/collections/:tableId/indexes/:key') ->desc('Get index') ->groups(['api', 'database']) ->label('scope', 'collections.read') @@ -3067,24 +3079,24 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') - ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject) { + ->action(function (string $databaseId, string $tableId, string $key, Response $response, Database $dbForProject) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $index = $collection->find('key', $key, 'indexes'); + $index = $table->find('key', $key, 'indexes'); if (empty($index)) { throw new Exception(Exception::INDEX_NOT_FOUND); } @@ -3093,15 +3105,15 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') }); -App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') - ->alias('/v1/database/collections/:collectionId/indexes/:key', ['databaseId' => 'default']) +App::delete('/v1/databases/:databaseId/tables/:tableId/indexes/:key') + ->alias('/v1/databases/:databaseId/collections/:tableId/indexes/:key') ->desc('Delete index') ->groups(['api', 'database']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].update') + ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].update') ->label('audits.event', 'index.delete') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', group: 'indexes', @@ -3117,26 +3129,26 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') contentType: ContentType::NONE )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->action(function (string $databaseId, string $tableId, string $key, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $index = $dbForProject->getDocument('indexes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $index = $dbForProject->getDocument('indexes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); if (empty($index->getId())) { throw new Exception(Exception::INDEX_NOT_FOUND); @@ -3147,34 +3159,34 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') $index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_INDEX) ->setDatabase($db) - ->setCollection($collection) + ->setCollection($table) ->setDocument($index); $queueForEvents ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collection->getId()) + ->setParam('tableId', $table->getId()) ->setParam('indexId', $index->getId()) - ->setContext('collection', $collection) + ->setContext('table', $table) ->setContext('database', $db) ->setPayload($response->output($index, Response::MODEL_INDEX)); $response->noContent(); }); -App::post('/v1/databases/:databaseId/collections/:collectionId/documents') - ->alias('/v1/database/collections/:collectionId/documents', ['databaseId' => 'default']) - ->desc('Create document') +App::post('/v1/databases/:databaseId/tables/:tableId/rows') + ->alias('/v1/databases/:databaseId/collections/:tableId/documents') + ->desc('Create row') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].create') ->label('scope', 'documents.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'document.create') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('audits.event', 'row.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) @@ -3183,8 +3195,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') [ new Method( namespace: 'databases', - group: 'documents', - name: 'createDocument', + group: 'rows', + name: 'createRow', description: '/docs/references/databases/create-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], responses: [ @@ -3198,16 +3210,16 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ] ) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('documentId', '', new CustomId(), 'Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define attributes before creating documents.') - ->param('data', [], new JSON(), 'Document data as JSON object.') + ->param('rowId', '', new CustomId(), 'Row ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define columns before creating rows.') + ->param('data', [], new JSON(), 'Row data as JSON object.') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->inject('response') ->inject('dbForProject') ->inject('user') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->action(function (string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage) { + ->action(function (string $databaseId, string $rowId, string $tableId, string|array $data, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage) { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -3228,9 +3240,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -3273,38 +3285,38 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } } - $data['$collection'] = $collection->getId(); // Adding this param to make API easier for developers - $data['$id'] = $documentId == 'unique()' ? ID::unique() : $documentId; + $data['$collection'] = $table->getId(); // Adding this param to make API easier for developers + $data['$id'] = $rowId == 'unique()' ? ID::unique() : $rowId; $data['$permissions'] = $permissions; - $document = new Document($data); + $row = new Document($data); $operations = 0; - $checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database, &$operations) { + $checkPermissions = function (Document $table, Document $row, string $permission) use (&$checkPermissions, $dbForProject, $database, &$operations) { $operations++; - $documentSecurity = $collection->getAttribute('documentSecurity', false); + $documentSecurity = $table->getAttribute('documentSecurity', false); $validator = new Authorization($permission); - $valid = $validator->isValid($collection->getPermissionsByType($permission)); + $valid = $validator->isValid($table->getPermissionsByType($permission)); if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } if ($permission === Database::PERMISSION_UPDATE) { - $valid = $valid || $validator->isValid($document->getUpdate()); + $valid = $valid || $validator->isValid($row->getUpdate()); if ($documentSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } } $relationships = \array_filter( - $collection->getAttribute('attributes', []), + $table->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); + $related = $row->getAttribute($relationship->getAttribute('key')); if (empty($related)) { continue; @@ -3318,9 +3330,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $relations = [$related]; } - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + $relatedTableId = $relationship->getAttribute('relatedCollection'); + $relatedTable = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) ); foreach ($relations as &$relation) { @@ -3334,7 +3346,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } if ($relation instanceof Document) { $current = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()) + fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(), $relation->getId()) ); if ($current->isEmpty()) { @@ -3346,26 +3358,26 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } else { $relation->removeAttribute('$collectionId'); $relation->removeAttribute('$databaseId'); - $relation->setAttribute('$collection', $relatedCollection->getId()); + $relation->setAttribute('$collection', $relatedTable->getId()); $type = Database::PERMISSION_UPDATE; } - $checkPermissions($relatedCollection, $relation, $type); + $checkPermissions($relatedTable, $relation, $type); } } if ($isList) { - $document->setAttribute($relationship->getAttribute('key'), \array_values($relations)); + $row->setAttribute($relationship->getAttribute('key'), \array_values($relations)); } else { - $document->setAttribute($relationship->getAttribute('key'), \reset($relations)); + $row->setAttribute($relationship->getAttribute('key'), \reset($relations)); } } }; - $checkPermissions($collection, $document, Database::PERMISSION_CREATE); + $checkPermissions($table, $row, Database::PERMISSION_CREATE); try { - $document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document); + $row = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $row); } catch (StructureException $e) { throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); } catch (DuplicateException $e) { @@ -3375,18 +3387,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } - // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { - $document->setAttribute('$databaseId', $database->getId()); - $document->setAttribute('$collectionId', $collection->getId()); + // Add $tableId and $databaseId for all rows + $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) { + $row->setAttribute('$databaseId', $database->getId()); + $row->setAttribute('$collectionId', $table->getId()); $relationships = \array_filter( - $collection->getAttribute('attributes', []), + $table->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); + $related = $row->getAttribute($relationship->getAttribute('key')); if (empty($related)) { continue; @@ -3395,20 +3407,20 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $related = [$related]; } - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + $relatedTableId = $relationship->getAttribute('relatedCollection'); + $relatedTable = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) ); foreach ($related as $relation) { if ($relation instanceof Document) { - $processDocument($relatedCollection, $relation); + $processRow($relatedTable, $relation); } } } }; - $processDocument($collection, $document); + $processRow($table, $row); $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) @@ -3418,35 +3430,35 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $response ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($document, Response::MODEL_DOCUMENT); + ->dynamic($row, Response::MODEL_DOCUMENT); $relationships = \array_map( fn ($document) => $document->getAttribute('key'), \array_filter( - $collection->getAttribute('attributes', []), + $table->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ) ); $queueForEvents ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collection->getId()) - ->setParam('documentId', $document->getId()) - ->setContext('collection', $collection) + ->setParam('tableId', $table->getId()) + ->setParam('rowId', $row->getId()) + ->setContext('table', $table) ->setContext('database', $database) ->setPayload($response->getPayload(), sensitive: $relationships); }); -App::get('/v1/databases/:databaseId/collections/:collectionId/documents') - ->alias('/v1/database/collections/:collectionId/documents', ['databaseId' => 'default']) - ->desc('List documents') +App::get('/v1/databases/:databaseId/tables/:tableId/rows') + ->alias('/v1/databases/:databaseId/collections/:tableId/documents') + ->desc('List rows') ->groups(['api', 'database']) ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'documents', - name: 'listDocuments', + group: 'rows', + name: 'listRows', description: '/docs/references/databases/list-documents.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], responses: [ @@ -3458,12 +3470,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') - ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, StatsUsage $queueForStatsUsage) { + ->action(function (string $databaseId, string $tableId, array $queries, Response $response, Database $dbForProject, StatsUsage $queueForStatsUsage) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3472,9 +3484,9 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -3499,44 +3511,44 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); } - $documentId = $cursor->getValue(); + $rowId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $cursorRow = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); - if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Document '{$documentId}' for the 'cursor' value not found."); + if ($cursorRow->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Row '{$rowId}' for the 'cursor' value not found."); } - $cursor->setValue($cursorDocument); + $cursor->setValue($cursorRow); } try { - $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); - $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); + $rows = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $queries); + $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $queries, APP_LIMIT_COUNT); } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); } $operations = 0; - // Add $collectionId and $databaseId for all documents - $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations): bool { - if ($document->isEmpty()) { + // Add $tableId and $databaseId for all rows + $processRow = (function (Document $table, Document $row) use (&$processRow, $dbForProject, $database, &$operations): bool { + if ($row->isEmpty()) { return false; } $operations++; - $document->removeAttribute('$collection'); - $document->setAttribute('$databaseId', $database->getId()); - $document->setAttribute('$collectionId', $collection->getId()); + $row->removeAttribute('$collection'); + $row->setAttribute('$databaseId', $database->getId()); + $row->setAttribute('$collectionId', $table->getId()); $relationships = \array_filter( - $collection->getAttribute('attributes', []), + $table->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); + $related = $row->getAttribute($relationship->getAttribute('key')); if (empty($related)) { if (\in_array(\gettype($related), ['array', 'object'])) { @@ -3552,30 +3564,30 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $relations = $related; } - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedTableId = $relationship->getAttribute('relatedCollection'); // todo: Use local cache for this getDocument - $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)); + $relatedTable = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId)); foreach ($relations as $index => $doc) { if ($doc instanceof Document) { - if (!$processDocument($relatedCollection, $doc)) { + if (!$processRow($relatedTable, $doc)) { unset($relations[$index]); } } } if (\is_array($related)) { - $document->setAttribute($relationship->getAttribute('key'), \array_values($relations)); + $row->setAttribute($relationship->getAttribute('key'), \array_values($relations)); } elseif (empty($relations)) { - $document->setAttribute($relationship->getAttribute('key'), null); + $row->setAttribute($relationship->getAttribute('key'), null); } } return true; }); - foreach ($documents as $document) { - $processDocument($collection, $document); + foreach ($rows as $row) { + $processRow($table, $row); } $queueForStatsUsage @@ -3590,43 +3602,43 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') // Check if the SELECT query includes $databaseId and $collectionId $hasDatabaseId = false; - $hasCollectionId = false; + $hasTableId = false; if ($select) { $hasDatabaseId = \array_reduce($queries, function ($result, $query) { return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$databaseId', $query->getValues())); }, false); - $hasCollectionId = \array_reduce($queries, function ($result, $query) { + $hasTableId = \array_reduce($queries, function ($result, $query) { return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$collectionId', $query->getValues())); }, false); } if ($select) { - foreach ($documents as $document) { + foreach ($rows as $row) { if (!$hasDatabaseId) { - $document->removeAttribute('$databaseId'); + $row->removeAttribute('$databaseId'); } - if (!$hasCollectionId) { - $document->removeAttribute('$collectionId'); + if (!$hasTableId) { + $row->removeAttribute('$collectionId'); } } } $response->dynamic(new Document([ 'total' => $total, - 'documents' => $documents, + 'documents' => $rows, ]), Response::MODEL_DOCUMENT_LIST); }); -App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') - ->alias('/v1/database/collections/:collectionId/documents/:documentId', ['databaseId' => 'default']) - ->desc('Get document') +App::get('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') + ->alias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId') + ->desc('Get row') ->groups(['api', 'database']) ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'documents', - name: 'getDocument', + group: 'rows', + name: 'getRow', description: '/docs/references/databases/get-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], responses: [ @@ -3638,13 +3650,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('documentId', '', new UID(), 'Document ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('rowId', '', new UID(), 'Row ID.') ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') - ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, StatsUsage $queueForStatsUsage) { + ->action(function (string $databaseId, string $tableId, string $rowId, array $queries, Response $response, Database $dbForProject, StatsUsage $queueForStatsUsage) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3653,45 +3665,45 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } try { $queries = Query::parseQueries($queries); - $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries); + $row = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId, $queries); } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } catch (QueryException $e) { throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - if ($document->isEmpty()) { + if ($row->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } $operations = 0; - // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { - if ($document->isEmpty()) { + // Add $tableId and $databaseId for all rows + $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database, &$operations) { + if ($row->isEmpty()) { return; } $operations++; - $document->setAttribute('$databaseId', $database->getId()); - $document->setAttribute('$collectionId', $collection->getId()); + $row->setAttribute('$databaseId', $database->getId()); + $row->setAttribute('$collectionId', $table->getId()); $relationships = \array_filter( - $collection->getAttribute('attributes', []), + $table->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); + $related = $row->getAttribute($relationship->getAttribute('key')); if (empty($related)) { if (\in_array(\gettype($related), ['array', 'object'])) { @@ -3705,20 +3717,20 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $related = [$related]; } - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + $relatedTableId = $relationship->getAttribute('relatedCollection'); + $relatedTable = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) ); foreach ($related as $relation) { if ($relation instanceof Document) { - $processDocument($relatedCollection, $relation); + $processRow($relatedTable, $relation); } } } }; - $processDocument($collection, $document); + $processRow($table, $row); $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) @@ -3726,19 +3738,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $response->addHeader('X-Debug-Operations', $operations); - $response->dynamic($document, Response::MODEL_DOCUMENT); + $response->dynamic($row, Response::MODEL_DOCUMENT); }); -App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId/logs') - ->alias('/v1/database/collections/:collectionId/documents/:documentId/logs', ['databaseId' => 'default']) - ->desc('List document logs') +App::get('/v1/databases/:databaseId/tables/:tableId/rows/:rowId/logs') + ->alias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId/logs') + ->desc('List row logs') ->groups(['api', 'database']) ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', group: 'logs', - name: 'listDocumentLogs', + name: 'listRowLogs', description: '/docs/references/databases/get-document-logs.md', auth: [AuthType::ADMIN], responses: [ @@ -3750,14 +3762,14 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen contentType: ContentType::JSON, )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID.') - ->param('documentId', '', new UID(), 'Document ID.') + ->param('tableId', '', new UID(), 'Collection ID.') + ->param('rowId', '', new UID(), 'Row ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) ->inject('response') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + ->action(function (string $databaseId, string $tableId, string $rowId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -3765,15 +3777,15 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); + $row = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId); - if ($document->isEmpty()) { + if ($row->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } @@ -3790,7 +3802,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ]); $audit = new Audit($dbForProject); - $resource = 'database/' . $databaseId . '/collection/' . $collectionId . '/document/' . $document->getId(); + $resource = 'database/' . $databaseId . '/table/' . $tableId . '/row/' . $row->getId(); $logs = $audit->getLogsByResource($resource, $queries); $output = []; @@ -3844,22 +3856,22 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ]), Response::MODEL_LOG_LIST); }); -App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') - ->alias('/v1/database/collections/:collectionId/documents/:documentId') - ->desc('Update document') +App::patch('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') + ->alias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId') + ->desc('Update row') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].update') + ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].update') ->label('scope', 'documents.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'document.update') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{response.$id}') + ->label('audits.event', 'row.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}/row/{response.$id}') ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', new Method( namespace: 'databases', - group: 'documents', - name: 'updateDocument', + group: 'rows', + name: 'updateRow', description: '/docs/references/databases/update-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], responses: [ @@ -3871,16 +3883,16 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID.') - ->param('documentId', '', new UID(), 'Document ID.') - ->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.', true) + ->param('tableId', '', new UID(), 'Collection ID.') + ->param('rowId', '', new UID(), 'Row ID.') + ->param('data', [], new JSON(), 'Row data as JSON object. Include only columns and value pairs to be updated.', true) ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->inject('requestTimestamp') ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { + ->action(function (string $databaseId, string $tableId, string $rowId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -3897,17 +3909,17 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Read permission should not be required for update - /** @var Document $document */ - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + /** @var Document $row */ + $row = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); - if ($document->isEmpty()) { + if ($row->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } @@ -3940,16 +3952,16 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } if (\is_null($permissions)) { - $permissions = $document->getPermissions() ?? []; + $permissions = $row->getPermissions() ?? []; } - $data['$id'] = $documentId; + $data['$id'] = $rowId; $data['$permissions'] = $permissions; - $newDocument = new Document($data); + $newRow = new Document($data); $operations = 0; - $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, &$operations) { + $setTable = (function (Document $collection, Document $document) use (&$setTable, $dbForProject, $database, &$operations) { $operations++; @@ -3973,9 +3985,9 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relations = [$related]; } - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + $relatedTableId = $relationship->getAttribute('relatedCollection'); + $relatedTable = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) ); foreach ($relations as &$relation) { @@ -3989,8 +4001,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relation = new Document($relation); } if ($relation instanceof Document) { - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + $oldRow = Authorization::skip(fn () => $dbForProject->getDocument( + 'database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(), $relation->getId() )); $relation->removeAttribute('$collectionId'); @@ -3998,15 +4010,15 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum // Attribute $collection is required for Utopia. $relation->setAttribute( '$collection', - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() + 'database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId() ); - if ($oldDocument->isEmpty()) { + if ($oldRow->isEmpty()) { if (isset($relation['$id']) && $relation['$id'] === 'unique()') { $relation['$id'] = ID::unique(); } } - $setCollection($relatedCollection, $relation); + $setTable($relatedTable, $relation); } } @@ -4018,7 +4030,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } }); - $setCollection($collection, $newDocument); + $setTable($table, $newRow); $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) @@ -4027,12 +4039,12 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $response->addHeader('X-Debug-Operations', $operations); try { - $document = $dbForProject->withRequestTimestamp( + $row = $dbForProject->withRequestTimestamp( $requestTimestamp, fn () => $dbForProject->updateDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), - $document->getId(), - $newDocument + 'database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), + $row->getId(), + $newRow ) ); } catch (AuthorizationException) { @@ -4045,18 +4057,18 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::COLLECTION_NOT_FOUND); } - // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { - $document->setAttribute('$databaseId', $database->getId()); - $document->setAttribute('$collectionId', $collection->getId()); + // Add $tableId and $databaseId for all rows + $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) { + $row->setAttribute('$databaseId', $database->getId()); + $row->setAttribute('$collectionId', $table->getId()); $relationships = \array_filter( - $collection->getAttribute('attributes', []), + $table->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); + $related = $row->getAttribute($relationship->getAttribute('key')); if (empty($related)) { continue; @@ -4065,56 +4077,56 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $related = [$related]; } - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + $relatedTableId = $relationship->getAttribute('relatedCollection'); + $relatedTable = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) ); foreach ($related as $relation) { if ($relation instanceof Document) { - $processDocument($relatedCollection, $relation); + $processRow($relatedTable, $relation); } } } }; - $processDocument($collection, $document); + $processRow($table, $row); - $response->dynamic($document, Response::MODEL_DOCUMENT); + $response->dynamic($row, Response::MODEL_DOCUMENT); $relationships = \array_map( fn ($document) => $document->getAttribute('key'), \array_filter( - $collection->getAttribute('attributes', []), + $table->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ) ); $queueForEvents ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collection->getId()) - ->setParam('documentId', $document->getId()) - ->setContext('collection', $collection) + ->setParam('tableId', $table->getId()) + ->setParam('rowId', $row->getId()) + ->setContext('table', $table) ->setContext('database', $database) ->setPayload($response->getPayload(), sensitive: $relationships); }); -App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') - ->alias('/v1/database/collections/:collectionId/documents/:documentId', ['databaseId' => 'default']) - ->desc('Delete document') +App::delete('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') + ->alias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId') + ->desc('Delete row') ->groups(['api', 'database']) ->label('scope', 'documents.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].delete') - ->label('audits.event', 'document.delete') - ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{request.documentId}') + ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].delete') + ->label('audits.event', 'row.delete') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}/row/{request.rowId}') ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', new Method( namespace: 'databases', - group: 'documents', - name: 'deleteDocument', + group: 'rows', + name: 'deleteRow', description: '/docs/references/databases/delete-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], responses: [ @@ -4126,14 +4138,14 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu contentType: ContentType::NONE )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('documentId', '', new UID(), 'Document ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('rowId', '', new UID(), 'Row ID.') ->inject('requestTimestamp') ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->action(function (string $databaseId, string $collectionId, string $documentId, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { + ->action(function (string $databaseId, string $tableId, string $rowId, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); @@ -4143,42 +4155,42 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Read permission should not be required for delete - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $row = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); - if ($document->isEmpty()) { + if ($row->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } try { - $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) { + $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $table, $rowId) { $dbForProject->deleteDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), - $documentId + 'database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), + $rowId ); }); } catch (NotFoundException $e) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { - $document->setAttribute('$databaseId', $database->getId()); - $document->setAttribute('$collectionId', $collection->getId()); + // Add $tableId and $databaseId for all rows + $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) { + $row->setAttribute('$databaseId', $database->getId()); + $row->setAttribute('$collectionId', $table->getId()); $relationships = \array_filter( - $collection->getAttribute('attributes', []), + $table->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); + $related = $row->getAttribute($relationship->getAttribute('key')); if (empty($related)) { continue; @@ -4187,20 +4199,20 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $related = [$related]; } - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + $relatedTableId = $relationship->getAttribute('relatedCollection'); + $relatedTable = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) ); foreach ($related as $relation) { if ($relation instanceof Document) { - $processDocument($relatedCollection, $relation); + $processRow($relatedTable, $relation); } } } }; - $processDocument($collection, $document); + $processRow($table, $row); $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) @@ -4211,18 +4223,18 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $relationships = \array_map( fn ($document) => $document->getAttribute('key'), \array_filter( - $collection->getAttribute('attributes', []), + $table->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ) ); $queueForEvents ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collection->getId()) - ->setParam('documentId', $document->getId()) - ->setContext('collection', $collection) + ->setParam('tableId', $table->getId()) + ->setParam('rowId', $row->getId()) + ->setContext('table', $table) ->setContext('database', $database) - ->setPayload($response->output($document, Response::MODEL_DOCUMENT), sensitive: $relationships); + ->setPayload($response->output($row, Response::MODEL_DOCUMENT), sensitive: $relationships); $response->noContent(); }); @@ -4424,16 +4436,16 @@ App::get('/v1/databases/:databaseId/usage') ]), Response::MODEL_USAGE_DATABASE); }); -App::get('/v1/databases/:databaseId/collections/:collectionId/usage') - ->alias('/v1/database/:collectionId/usage', ['databaseId' => 'default']) - ->desc('Get collection usage stats') +App::get('/v1/databases/:databaseId/tables/:tableId/usage') + ->alias('/v1/databases/:databaseId/collections/:tableId/usage') + ->desc('Get table usage stats') ->groups(['api', 'database', 'usage']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', group: null, - name: 'getCollectionUsage', + name: 'getTableUsage', description: '/docs/references/databases/get-collection-usage.md', auth: [AuthType::ADMIN], responses: [ @@ -4446,16 +4458,16 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) - ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('tableId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') - ->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject) { + ->action(function (string $databaseId, string $range, string $tableId, Response $response, Database $dbForProject) { $database = $dbForProject->getDocument('databases', $databaseId); - $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + $tableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $tableDocument->getInternalId()); - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4463,7 +4475,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collectionDocument->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), + str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $tableDocument->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { From 4f1f9bb4a23281a8088385b8065cfba64c8acc09 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 26 Apr 2025 16:06:53 +0530 Subject: [PATCH 019/343] add: filter for latest changes. --- app/controllers/general.php | 3 +- src/Appwrite/Utopia/Request/Filters/V19.php | 32 +++++++++++++++------ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 889571fe62..bf048be9d6 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -805,7 +805,8 @@ App::init() if (version_compare($requestFormat, '1.6.0', '<')) { $request->addFilter(new RequestV18()); } - if (version_compare($requestFormat, '1.7.0', '<')) { + // alias filters on 1.7.x, so we use `<=` and not just `<` + if (version_compare($requestFormat, '1.7.0', '<=')) { $request->addFilter(new RequestV19()); } } diff --git a/src/Appwrite/Utopia/Request/Filters/V19.php b/src/Appwrite/Utopia/Request/Filters/V19.php index 041c126a69..9597f40570 100644 --- a/src/Appwrite/Utopia/Request/Filters/V19.php +++ b/src/Appwrite/Utopia/Request/Filters/V19.php @@ -6,18 +6,32 @@ use Appwrite\Utopia\Request\Filter; class V19 extends Filter { - // Convert 1.6 params to 1.7 public function parse(array $content, string $model): array { - /* - Uncomment with first request filter; current is just a copy of V18 - switch ($model) { - case 'functions.create': - $content['something'] = $content['somethingElse'] ?? ""; - unset($content['something']); - break; + return $this->overrideDatabaseParams($content, $model); + } + + // Database terminology change handling. + protected function overrideDatabaseParams(array $content, string $model): array + { + if (!str_starts_with($model, 'databases.')) { + return $content; + } + + $map = [ + 'collectionId' => 'tableId', + 'attributeId' => 'columnId', + 'attributes' => 'columns', + 'documentId' => 'rowId', + 'relatedCollectionId' => 'relatedTableId' + ]; + + foreach ($map as $oldKey => $newKey) { + if (isset($content[$oldKey])) { + $content[$newKey] = $content[$oldKey]; + unset($content[$oldKey]); + } } - */ return $content; } From 21715448ac04b154df005e79135cb2f6ee6fdd33 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 26 Apr 2025 16:07:32 +0530 Subject: [PATCH 020/343] fix|update: database tests for new error messages. --- tests/e2e/Services/Databases/DatabasesBase.php | 4 ++-- tests/e2e/Services/Databases/DatabasesCustomClientTest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 0c7e1d386e..989d1217d3 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -1373,7 +1373,7 @@ trait DatabasesBase ]); $this->assertEquals(400, $unknown['headers']['status-code']); - $this->assertEquals('Unknown attribute: Unknown. Verify the attribute name or create the attribute.', $unknown['body']['message']); + $this->assertEquals('Unknown column: Unknown. Verify the column name or create the column.', $unknown['body']['message']); $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', @@ -2671,7 +2671,7 @@ trait DatabasesBase $this->assertEquals(400, $enumDefault['headers']['status-code']); $this->assertEquals(400, $enumDefaultStrict['headers']['status-code']); $this->assertEquals('Minimum value must be lesser than maximum value', $invalidRange['body']['message']); - $this->assertEquals('Cannot set default value for array attributes', $defaultArray['body']['message']); + $this->assertEquals('Cannot set default value for array columns', $defaultArray['body']['message']); $this->assertEquals(400, $datetimeDefault['headers']['status-code']); // wait for worker to add attributes sleep(3); diff --git a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php index 8484996058..d4a8c87868 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php @@ -472,7 +472,7 @@ class DatabasesCustomClientTest extends Scope \sleep(2); $this->assertEquals(409, $relation['body']['code']); - $this->assertEquals('Creating more than one "manyToMany" relationship on the same collection is currently not permitted.', $relation['body']['message']); + $this->assertEquals('Creating more than one "manyToMany" relationship on the same table is currently not permitted.', $relation['body']['message']); } public function testUpdateWithoutRelationPermission(): void From 89ce5a6e1044b6866613760381172a4b6fb727c3 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 26 Apr 2025 16:07:46 +0530 Subject: [PATCH 021/343] add: todo. --- app/config/scopes.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/config/scopes.php b/app/config/scopes.php index 7dea7b1cd5..d459ffb2fc 100644 --- a/app/config/scopes.php +++ b/app/config/scopes.php @@ -1,5 +1,6 @@ [ 'description' => 'Access to create, update, and delete user sessions', From 949f58522d7c46d6f6cb0bb782ed6fc8eecd576b Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 27 Apr 2025 10:33:44 +0530 Subject: [PATCH 022/343] change: events system. --- app/config/events.php | 28 +- app/config/templates/function.php | 2 +- app/controllers/api/databases.php | 21 +- app/controllers/general.php | 7 +- src/Appwrite/Event/Database.php | 36 +-- src/Appwrite/Event/Realtime.php | 4 +- src/Appwrite/Messaging/Adapter/Realtime.php | 35 +-- src/Appwrite/Platform/Workers/Databases.php | 284 +++++++++--------- .../Request/Filters/DatabaseAliases.php | 38 +++ src/Appwrite/Utopia/Request/Filters/V19.php | 32 +- .../Utopia/Response/Model/Webhook.php | 2 +- 11 files changed, 254 insertions(+), 235 deletions(-) create mode 100644 src/Appwrite/Utopia/Request/Filters/DatabaseAliases.php diff --git a/app/config/events.php b/app/config/events.php index 0bfddf4f1f..3b0cc982a0 100644 --- a/app/config/events.php +++ b/app/config/events.php @@ -95,22 +95,22 @@ return [ '$model' => Response::MODEL_DATABASE, '$resource' => true, '$description' => 'This event triggers on any database event.', - 'collections' => [ + 'tables' => [ '$model' => Response::MODEL_COLLECTION, '$resource' => true, - '$description' => 'This event triggers on any collection event.', - 'documents' => [ + '$description' => 'This event triggers on any table event.', + 'rows' => [ '$model' => Response::MODEL_DOCUMENT, '$resource' => true, - '$description' => 'This event triggers on any documents event.', + '$description' => 'This event triggers on any rows event.', 'create' => [ - '$description' => 'This event triggers when a document is created.', + '$description' => 'This event triggers when a row is created.', ], 'delete' => [ - '$description' => 'This event triggers when a document is deleted.' + '$description' => 'This event triggers when a row is deleted.' ], 'update' => [ - '$description' => 'This event triggers when a document is updated.' + '$description' => 'This event triggers when a row is updated.' ], ], 'indexes' => [ @@ -124,25 +124,25 @@ return [ '$description' => 'This event triggers when an index is deleted.' ] ], - 'attributes' => [ + 'columns' => [ '$model' => Response::MODEL_ATTRIBUTE, '$resource' => true, - '$description' => 'This event triggers on any attributes event.', + '$description' => 'This event triggers on any columns event.', 'create' => [ - '$description' => 'This event triggers when an attribute is created.', + '$description' => 'This event triggers when an column is created.', ], 'delete' => [ - '$description' => 'This event triggers when an attribute is deleted.' + '$description' => 'This event triggers when an column is deleted.' ] ], 'create' => [ - '$description' => 'This event triggers when a collection is created.' + '$description' => 'This event triggers when a table is created.' ], 'delete' => [ - '$description' => 'This event triggers when a collection is deleted.', + '$description' => 'This event triggers when a table is deleted.', ], 'update' => [ - '$description' => 'This event triggers when a collection is updated.', + '$description' => 'This event triggers when a table is updated.', ] ], 'create' => [ diff --git a/app/config/templates/function.php b/app/config/templates/function.php index d8426ad900..b017281dbe 100644 --- a/app/config/templates/function.php +++ b/app/config/templates/function.php @@ -1395,7 +1395,7 @@ return [ 'score' => 5, 'tagline' => 'Convert text to speech using the Hugging Face inference API.', 'permissions' => ['any'], - 'events' => ['databases.*.collections.*.documents.*.create'], + 'events' => ['databases.*.tables.*.rows.*.create'], 'cron' => '', 'timeout' => 15, 'useCases' => ['ai'], diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index d3a34f56e8..d8556dd4fe 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -218,8 +218,8 @@ function createColumn(string $databaseId, string $tableId, Document $column, Res $queueForDatabase ->setType(DATABASE_TYPE_CREATE_ATTRIBUTE) ->setDatabase($db) - ->setCollection($table) - ->setDocument($column); + ->setTable($table) + ->setRow($column); $queueForEvents ->setContext('table', $table) @@ -485,8 +485,7 @@ App::post('/v1/databases') ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('queueForStatsUsage') - ->action(function (string $databaseId, string $name, bool $enabled, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { + ->action(function (string $databaseId, string $name, bool $enabled, Response $response, Database $dbForProject, Event $queueForEvents) { $databaseId = $databaseId == 'unique()' ? ID::unique() : $databaseId; @@ -1280,7 +1279,7 @@ App::delete('/v1/databases/:databaseId/tables/:tableId') $queueForDatabase ->setType(DATABASE_TYPE_DELETE_COLLECTION) ->setDatabase($database) - ->setCollection($table); + ->setTable($table); $queueForEvents ->setContext('database', $database) @@ -2759,9 +2758,9 @@ App::delete('/v1/databases/:databaseId/tables/:tableId/columns/:key') $queueForDatabase ->setType(DATABASE_TYPE_DELETE_ATTRIBUTE) - ->setCollection($table) + ->setTable($table) ->setDatabase($db) - ->setDocument($column); + ->setRow($column); // Select response model based on type and format $type = $column->getAttribute('type'); @@ -2953,8 +2952,8 @@ App::post('/v1/databases/:databaseId/tables/:tableId/indexes') $queueForDatabase ->setType(DATABASE_TYPE_CREATE_INDEX) ->setDatabase($db) - ->setCollection($table) - ->setDocument($index); + ->setTable($table) + ->setRow($index); $queueForEvents ->setParam('databaseId', $databaseId) @@ -3164,8 +3163,8 @@ App::delete('/v1/databases/:databaseId/tables/:tableId/indexes/:key') $queueForDatabase ->setType(DATABASE_TYPE_DELETE_INDEX) ->setDatabase($db) - ->setCollection($table) - ->setDocument($index); + ->setTable($table) + ->setRow($index); $queueForEvents ->setParam('databaseId', $databaseId) diff --git a/app/controllers/general.php b/app/controllers/general.php index bf048be9d6..fdef1e9cee 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -18,6 +18,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Transformation\Adapter\Preview; use Appwrite\Transformation\Transformation; use Appwrite\Utopia\Request; +use Appwrite\Utopia\Request\Filters\DatabaseAliases; use Appwrite\Utopia\Request\Filters\V16 as RequestV16; use Appwrite\Utopia\Request\Filters\V17 as RequestV17; use Appwrite\Utopia\Request\Filters\V18 as RequestV18; @@ -805,12 +806,14 @@ App::init() if (version_compare($requestFormat, '1.6.0', '<')) { $request->addFilter(new RequestV18()); } - // alias filters on 1.7.x, so we use `<=` and not just `<` - if (version_compare($requestFormat, '1.7.0', '<=')) { + if (version_compare($requestFormat, '1.7.0', '<')) { $request->addFilter(new RequestV19()); } } + // process on all databases endpoints! + $request->addFilter(new DatabaseAliases()); + $domain = $request->getHostname(); $domains = Config::getParam('domains', []); if (!array_key_exists($domain, $domains)) { diff --git a/src/Appwrite/Event/Database.php b/src/Appwrite/Event/Database.php index d2f70dddf2..797574d2fc 100644 --- a/src/Appwrite/Event/Database.php +++ b/src/Appwrite/Event/Database.php @@ -10,8 +10,8 @@ class Database extends Event { protected string $type = ''; protected ?Document $database = null; - protected ?Document $collection = null; - protected ?Document $document = null; + protected ?Document $table = null; + protected ?Document $row = null; public function __construct(protected Publisher $publisher) { @@ -55,48 +55,48 @@ class Database extends Event } /** - * Set the collection for this database event. + * Set the table for this database event. * - * @param Document $collection + * @param Document $table * @return self */ - public function setCollection(Document $collection): self + public function setTable(Document $table): self { - $this->collection = $collection; + $this->table = $table; return $this; } /** - * Returns set collection for this event. + * Returns set table for this event. * * @return null|Document */ - public function getCollection(): ?Document + public function getTable(): ?Document { - return $this->collection; + return $this->table; } /** - * Set the document for this database event. + * Set the row for this database event. * - * @param Document $document + * @param Document $row * @return self */ - public function setDocument(Document $document): self + public function setRow(Document $row): self { - $this->document = $document; + $this->row = $row; return $this; } /** - * Returns set document for this database event. + * Returns set row for this database event. * @return null|Document */ - public function getDocument(): ?Document + public function getRow(): ?Document { - return $this->document; + return $this->row; } public function getQueue(): string @@ -123,8 +123,8 @@ class Database extends Event 'project' => $this->project, 'user' => $this->user, 'type' => $this->type, - 'collection' => $this->collection, - 'document' => $this->document, + 'table' => $this->table, + 'row' => $this->row, 'database' => $this->database, 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) ]; diff --git a/src/Appwrite/Event/Realtime.php b/src/Appwrite/Event/Realtime.php index 4d8c9a321b..e1ec891e67 100644 --- a/src/Appwrite/Event/Realtime.php +++ b/src/Appwrite/Event/Realtime.php @@ -76,7 +76,7 @@ class Realtime extends Event $payload = new Document($this->getPayload()); $db = $this->getContext('database'); - $collection = $this->getContext('collection'); + $table = $this->getContext('table'); $bucket = $this->getContext('bucket'); $target = RealtimeAdapter::fromPayload( @@ -85,7 +85,7 @@ class Realtime extends Event payload: $payload, project: $this->getProject(), database: $db, - collection: $collection, + table: $table, bucket: $bucket, ); diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index 568132ceb1..400589f677 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -252,12 +252,12 @@ class Realtime extends Adapter * @param Document $payload * @param Document|null $project * @param Document|null $database - * @param Document|null $collection + * @param Document|null $table * @param Document|null $bucket * @return array * @throws \Exception */ - public static function fromPayload(string $event, Document $payload, Document $project = null, Document $database = null, Document $collection = null, Document $bucket = null): array + public static function fromPayload(string $event, Document $payload, Document $project = null, Document $database = null, Document $table = null, Document $bucket = null): array { $channels = []; $roles = []; @@ -273,6 +273,7 @@ class Realtime extends Adapter $roles = [Role::user(ID::custom($parts[1]))->toString()]; break; case 'rules': + case 'migrations': $channels[] = 'console'; $channels[] = 'projects.' . $project->getId(); $projectId = 'console'; @@ -297,26 +298,26 @@ class Realtime extends Adapter $roles = [Role::team(ID::custom($parts[1]))->toString()]; break; case 'databases': - if (in_array($parts[4] ?? [], ['attributes', 'indexes'])) { + if (in_array($parts[4] ?? [], ['columns', 'indexes'])) { $channels[] = 'console'; $channels[] = 'projects.' . $project->getId(); $projectId = 'console'; $roles = [Role::team($project->getAttribute('teamId'))->toString()]; - } elseif (($parts[4] ?? '') === 'documents') { + } elseif (($parts[4] ?? '') === 'rows') { if ($database->isEmpty()) { - throw new \Exception('Database needs to be passed to Realtime for Document events in the Database.'); + throw new \Exception('Database needs to be passed to Realtime for Row events in the Database.'); } - if ($collection->isEmpty()) { - throw new \Exception('Collection needs to be passed to Realtime for Document events in the Database.'); + if ($table->isEmpty()) { + throw new \Exception('Table needs to be passed to Realtime for Row events in the Database.'); } - $channels[] = 'documents'; - $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents'; - $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents.' . $payload->getId(); + $channels[] = 'rows'; + $channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$collectionId') . '.rows'; + $channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$collectionId') . '.rows.' . $payload->getId(); - $roles = $collection->getAttribute('documentSecurity', false) - ? \array_merge($collection->getRead(), $payload->getRead()) - : $collection->getRead(); + $roles = $table->getAttribute('documentSecurity', false) + ? \array_merge($table->getRead(), $payload->getRead()) + : $table->getRead(); } break; case 'buckets': @@ -334,7 +335,6 @@ class Realtime extends Adapter } break; - case 'functions': if ($parts[2] === 'executions') { if (!empty($payload->getRead())) { @@ -353,7 +353,6 @@ class Realtime extends Adapter } break; - case 'sites': if ($parts[2] === 'deployments') { $channels[] = 'console'; @@ -362,12 +361,6 @@ class Realtime extends Adapter $roles = [Role::team($project->getAttribute('teamId'))->toString()]; } - break; - case 'migrations': - $channels[] = 'console'; - $channels[] = 'projects.' . $project->getId(); - $projectId = 'console'; - $roles = [Role::team($project->getAttribute('teamId'))->toString()]; break; } diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index b2691b420e..1f3b76d6eb 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -60,8 +60,8 @@ class Databases extends Action } $type = $payload['type']; - $collection = new Document($payload['collection'] ?? []); - $document = new Document($payload['document'] ?? []); + $row = new Document($payload['row'] ?? []); + $table = new Document($payload['table'] ?? []); $database = new Document($payload['database'] ?? []); $log->addTag('projectId', $project->getId()); @@ -75,19 +75,19 @@ class Databases extends Action match (\strval($type)) { DATABASE_TYPE_DELETE_DATABASE => $this->deleteDatabase($database, $project, $dbForProject), - DATABASE_TYPE_DELETE_COLLECTION => $this->deleteCollection($database, $collection, $project, $dbForProject), - DATABASE_TYPE_CREATE_ATTRIBUTE => $this->createAttribute($database, $collection, $document, $project, $dbForPlatform, $dbForProject, $queueForRealtime), - DATABASE_TYPE_DELETE_ATTRIBUTE => $this->deleteAttribute($database, $collection, $document, $project, $dbForPlatform, $dbForProject, $queueForRealtime), - DATABASE_TYPE_CREATE_INDEX => $this->createIndex($database, $collection, $document, $project, $dbForPlatform, $dbForProject, $queueForRealtime), - DATABASE_TYPE_DELETE_INDEX => $this->deleteIndex($database, $collection, $document, $project, $dbForPlatform, $dbForProject, $queueForRealtime), + DATABASE_TYPE_DELETE_COLLECTION => $this->deleteTable($database, $table, $project, $dbForProject), + DATABASE_TYPE_CREATE_ATTRIBUTE => $this->createColumn($database, $table, $row, $project, $dbForPlatform, $dbForProject, $queueForRealtime), + DATABASE_TYPE_DELETE_ATTRIBUTE => $this->deleteColumn($database, $table, $row, $project, $dbForPlatform, $dbForProject, $queueForRealtime), + DATABASE_TYPE_CREATE_INDEX => $this->createIndex($database, $table, $row, $project, $dbForPlatform, $dbForProject, $queueForRealtime), + DATABASE_TYPE_DELETE_INDEX => $this->deleteIndex($database, $table, $row, $project, $dbForPlatform, $dbForProject, $queueForRealtime), default => throw new Exception('No database operation for type: ' . \strval($type)), }; } /** * @param Document $database - * @param Document $collection - * @param Document $attribute + * @param Document $table + * @param Document $column * @param Document $project * @param Database $dbForPlatform * @param Database $dbForProject @@ -98,64 +98,64 @@ class Databases extends Action * @throws \Exception * @throws \Throwable */ - private function createAttribute( + private function createColumn( Document $database, - Document $collection, - Document $attribute, + Document $table, + Document $column, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime ): void { - if ($collection->isEmpty()) { - throw new Exception('Missing collection'); + if ($table->isEmpty()) { + throw new Exception('Missing table'); } - if ($attribute->isEmpty()) { - throw new Exception('Missing attribute'); + if ($column->isEmpty()) { + throw new Exception('Missing column'); } $projectId = $project->getId(); - $event = "databases.[databaseId].collections.[collectionId].attributes.[attributeId].update"; + $event = "databases.[databaseId].tables.[tableId].columns.[columnId].update"; /** * TODO @christyjacob4 verify if this is still the case * Fetch attribute from the database, since with Resque float values are loosing informations. */ - $attribute = $dbForProject->getDocument('attributes', $attribute->getId()); + $column = $dbForProject->getDocument('attributes', $column->getId()); - if ($attribute->isEmpty()) { + if ($column->isEmpty()) { // Attribute was deleted before job was processed return; } - $collectionId = $collection->getId(); - $key = $attribute->getAttribute('key', ''); - $type = $attribute->getAttribute('type', ''); - $size = $attribute->getAttribute('size', 0); - $required = $attribute->getAttribute('required', false); - $default = $attribute->getAttribute('default', null); - $signed = $attribute->getAttribute('signed', true); - $array = $attribute->getAttribute('array', false); - $format = $attribute->getAttribute('format', ''); - $formatOptions = $attribute->getAttribute('formatOptions', []); - $filters = $attribute->getAttribute('filters', []); - $options = $attribute->getAttribute('options', []); + $tableId = $table->getId(); + $key = $column->getAttribute('key', ''); + $type = $column->getAttribute('type', ''); + $size = $column->getAttribute('size', 0); + $required = $column->getAttribute('required', false); + $default = $column->getAttribute('default', null); + $signed = $column->getAttribute('signed', true); + $array = $column->getAttribute('array', false); + $format = $column->getAttribute('format', ''); + $formatOptions = $column->getAttribute('formatOptions', []); + $filters = $column->getAttribute('filters', []); + $options = $column->getAttribute('options', []); $project = $dbForPlatform->getDocument('projects', $projectId); - $relatedAttribute = new Document(); - $relatedCollection = new Document(); + $relatedColumn = new Document(); + $relatedTable = new Document(); try { switch ($type) { case Database::VAR_RELATIONSHIP: - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); - if ($relatedCollection->isEmpty()) { - throw new DatabaseException('Collection not found'); + $relatedTable = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + if ($relatedTable->isEmpty()) { + throw new DatabaseException('Table not found'); } if ( !$dbForProject->createRelationship( - collection: 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), - relatedCollection: 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + collection: 'database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), + relatedCollection: 'database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(), type: $options['relationType'], twoWay: $options['twoWay'], id: $key, @@ -163,61 +163,61 @@ class Databases extends Action onDelete: $options['onDelete'], ) ) { - throw new DatabaseException('Failed to create Attribute'); + throw new DatabaseException('Failed to create Column'); } if ($options['twoWay']) { - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); - $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'available')); + $relatedColumn = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $options['twoWayKey']); + $dbForProject->updateDocument('attributes', $relatedColumn->getId(), $relatedColumn->setAttribute('status', 'available')); } break; default: - if (!$dbForProject->createAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { - throw new Exception('Failed to create Attribute'); + if (!$dbForProject->createAttribute('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { + throw new Exception('Failed to create Column'); } } - $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'available')); + $dbForProject->updateDocument('attributes', $column->getId(), $column->setAttribute('status', 'available')); } catch (\Throwable $e) { Console::error($e->getMessage()); if ($e instanceof DatabaseException) { - $attribute->setAttribute('error', $e->getMessage()); - if (! $relatedAttribute->isEmpty()) { - $relatedAttribute->setAttribute('error', $e->getMessage()); + $column->setAttribute('error', $e->getMessage()); + if (! $relatedColumn->isEmpty()) { + $relatedColumn->setAttribute('error', $e->getMessage()); } } $dbForProject->updateDocument( 'attributes', - $attribute->getId(), - $attribute->setAttribute('status', 'failed') + $column->getId(), + $column->setAttribute('status', 'failed') ); - if (! $relatedAttribute->isEmpty()) { + if (! $relatedColumn->isEmpty()) { $dbForProject->updateDocument( 'attributes', - $relatedAttribute->getId(), - $relatedAttribute->setAttribute('status', 'failed') + $relatedColumn->getId(), + $relatedColumn->setAttribute('status', 'failed') ); } throw $e; } finally { - $this->trigger($database, $collection, $project, $event, $queueForRealtime, $attribute); + $this->trigger($database, $table, $project, $event, $queueForRealtime, $column); - if (! $relatedCollection->isEmpty()) { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + if (! $relatedTable->isEmpty()) { + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedTable->getId()); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $tableId); } } /** * @param Document $database - * @param Document $collection - * @param Document $attribute + * @param Document $table + * @param Document $column * @param Document $project * @param Database $dbForPlatform * @param Database $dbForProject @@ -228,24 +228,24 @@ class Databases extends Action * @throws \Exception * @throws \Throwable **/ - private function deleteAttribute(Document $database, Document $collection, Document $attribute, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void + private function deleteColumn(Document $database, Document $table, Document $column, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void { - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception('Missing collection'); } - if ($attribute->isEmpty()) { + if ($column->isEmpty()) { throw new Exception('Missing attribute'); } $projectId = $project->getId(); - $event = 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].delete'; - $collectionId = $collection->getId(); - $key = $attribute->getAttribute('key', ''); - $type = $attribute->getAttribute('type', ''); + $event = 'databases.[databaseId].tables.[tableId].columns.[columnId].delete'; + $tableId = $table->getId(); + $key = $column->getAttribute('key', ''); + $type = $column->getAttribute('type', ''); $project = $dbForPlatform->getDocument('projects', $projectId); - $options = $attribute->getAttribute('options', []); - $relatedAttribute = new Document(); - $relatedCollection = new Document(); + $options = $column->getAttribute('options', []); + $relatedColumn = new Document(); + $relatedTable = new Document(); // possible states at this point: // - available: should not land in queue; controller flips these to 'deleting' // - processing: hasn't finished creating @@ -257,89 +257,89 @@ class Databases extends Action try { if ($type === Database::VAR_RELATIONSHIP) { if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); - if ($relatedCollection->isEmpty()) { - throw new DatabaseException('Collection not found'); + $relatedTable = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + if ($relatedTable->isEmpty()) { + throw new DatabaseException('Table not found'); } - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + $relatedColumn = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $options['twoWayKey']); } - if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { - $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck')); + if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $key)) { + $dbForProject->updateDocument('attributes', $relatedColumn->getId(), $relatedColumn->setAttribute('status', 'stuck')); throw new DatabaseException('Failed to delete Relationship'); } - } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { - throw new DatabaseException('Failed to delete Attribute'); + } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $key)) { + throw new DatabaseException('Failed to delete Column'); } - $dbForProject->deleteDocument('attributes', $attribute->getId()); + $dbForProject->deleteDocument('attributes', $column->getId()); - if (!$relatedAttribute->isEmpty()) { - $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); + if (!$relatedColumn->isEmpty()) { + $dbForProject->deleteDocument('attributes', $relatedColumn->getId()); } } catch (NotFound $e) { Console::error($e->getMessage()); - $dbForProject->deleteDocument('attributes', $attribute->getId()); + $dbForProject->deleteDocument('attributes', $column->getId()); - if (!$relatedAttribute->isEmpty()) { - $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); + if (!$relatedColumn->isEmpty()) { + $dbForProject->deleteDocument('attributes', $relatedColumn->getId()); } } catch (\Throwable $e) { Console::error($e->getMessage()); if ($e instanceof DatabaseException) { - $attribute->setAttribute('error', $e->getMessage()); - if (!$relatedAttribute->isEmpty()) { - $relatedAttribute->setAttribute('error', $e->getMessage()); + $column->setAttribute('error', $e->getMessage()); + if (!$relatedColumn->isEmpty()) { + $relatedColumn->setAttribute('error', $e->getMessage()); } } $dbForProject->updateDocument( 'attributes', - $attribute->getId(), - $attribute->setAttribute('status', 'stuck') + $column->getId(), + $column->setAttribute('status', 'stuck') ); - if (!$relatedAttribute->isEmpty()) { + if (!$relatedColumn->isEmpty()) { $dbForProject->updateDocument( 'attributes', - $relatedAttribute->getId(), - $relatedAttribute->setAttribute('status', 'stuck') + $relatedColumn->getId(), + $relatedColumn->setAttribute('status', 'stuck') ); } throw $e; } finally { - $this->trigger($database, $collection, $project, $event, $queueForRealtime, $attribute); + $this->trigger($database, $table, $project, $event, $queueForRealtime, $column); } // The underlying database removes/rebuilds indexes when attribute is removed // Update indexes table with changes /** @var Document[] $indexes */ - $indexes = $collection->getAttribute('indexes', []); + $indexes = $table->getAttribute('indexes', []); foreach ($indexes as $index) { - /** @var string[] $attributes */ - $attributes = $index->getAttribute('attributes'); + /** @var string[] $columns */ + $columns = $index->getAttribute('attributes'); $lengths = $index->getAttribute('lengths'); $orders = $index->getAttribute('orders'); - $found = \array_search($key, $attributes); + $found = \array_search($key, $columns); if ($found !== false) { // If found, remove entry from attributes, lengths, and orders // array_values wraps array_diff to reindex array keys // when found attribute is removed from array - $attributes = \array_values(\array_diff($attributes, [$attributes[$found]])); + $columns = \array_values(\array_diff($columns, [$columns[$found]])); $lengths = \array_values(\array_diff($lengths, isset($lengths[$found]) ? [$lengths[$found]] : [])); $orders = \array_values(\array_diff($orders, isset($orders[$found]) ? [$orders[$found]] : [])); - if (empty($attributes)) { + if (empty($columns)) { $dbForProject->deleteDocument('indexes', $index->getId()); } else { $index - ->setAttribute('attributes', $attributes, Document::SET_TYPE_ASSIGN) + ->setAttribute('attributes', $columns, Document::SET_TYPE_ASSIGN) ->setAttribute('lengths', $lengths, Document::SET_TYPE_ASSIGN) ->setAttribute('orders', $orders, Document::SET_TYPE_ASSIGN); @@ -357,7 +357,7 @@ class Databases extends Action } if ($exists) { // Delete the duplicate if created, else update in db - $this->deleteIndex($database, $collection, $index, $project, $dbForPlatform, $dbForProject, $queueForRealtime); + $this->deleteIndex($database, $table, $index, $project, $dbForPlatform, $dbForProject, $queueForRealtime); } else { $dbForProject->updateDocument('indexes', $index->getId(), $index); } @@ -365,17 +365,17 @@ class Databases extends Action } } } finally { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $tableId); - if (! $relatedCollection->isEmpty()) { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + if (! $relatedTable->isEmpty()) { + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedTable->getId()); } } } /** * @param Document $database - * @param Document $collection + * @param Document $table * @param Document $index * @param Document $project * @param Database $dbForPlatform @@ -388,9 +388,9 @@ class Databases extends Action * @throws DatabaseException * @throws \Throwable */ - private function createIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void + private function createIndex(Document $database, Document $table, Document $index, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void { - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception('Missing collection'); } if ($index->isEmpty()) { @@ -398,8 +398,8 @@ class Databases extends Action } $projectId = $project->getId(); - $event = 'databases.[databaseId].collections.[collectionId].indexes.[indexId].update'; - $collectionId = $collection->getId(); + $event = 'databases.[databaseId].tables.[tableId].indexes.[indexId].update'; + $collectionId = $table->getId(); $key = $index->getAttribute('key', ''); $type = $index->getAttribute('type', ''); $attributes = $index->getAttribute('attributes', []); @@ -408,7 +408,7 @@ class Databases extends Action $project = $dbForPlatform->getDocument('projects', $projectId); try { - if (!$dbForProject->createIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { + if (!$dbForProject->createIndex('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { throw new DatabaseException('Failed to create Index'); } $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); @@ -425,14 +425,14 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $collection, $project, $event, $queueForRealtime, null, $index); + $this->trigger($database, $table, $project, $event, $queueForRealtime, null, $index); $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } } /** * @param Document $database - * @param Document $collection + * @param Document $table * @param Document $index * @param Document $project * @param Database $dbForPlatform @@ -445,9 +445,9 @@ class Databases extends Action * @throws DatabaseException * @throws \Throwable */ - private function deleteIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void + private function deleteIndex(Document $database, Document $table, Document $index, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void { - if ($collection->isEmpty()) { + if ($table->isEmpty()) { throw new Exception('Missing collection'); } if ($index->isEmpty()) { @@ -455,13 +455,13 @@ class Databases extends Action } $projectId = $project->getId(); - $event = 'databases.[databaseId].collections.[collectionId].indexes.[indexId].delete'; + $event = 'databases.[databaseId].tables.[tableId].indexes.[indexId].delete'; $key = $index->getAttribute('key'); $status = $index->getAttribute('status', ''); $project = $dbForPlatform->getDocument('projects', $projectId); try { - if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $key)) { throw new DatabaseException('Failed to delete index'); } $dbForProject->deleteDocument('indexes', $index->getId()); @@ -481,8 +481,8 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $collection, $project, $event, $queueForRealtime, null, $index); - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); + $this->trigger($database, $table, $project, $event, $queueForRealtime, null, $index); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $table->getId()); } } @@ -496,7 +496,7 @@ class Databases extends Action protected function deleteDatabase(Document $database, Document $project, $dbForProject): void { $this->deleteByGroup('database_' . $database->getInternalId(), [], $dbForProject, function ($collection) use ($database, $project, $dbForProject) { - $this->deleteCollection($database, $collection, $project, $dbForProject); + $this->deleteTable($database, $collection, $project, $dbForProject); }); $dbForProject->deleteCollection('database_' . $database->getInternalId()); @@ -504,7 +504,7 @@ class Databases extends Action /** * @param Document $database - * @param Document $collection + * @param Document $table * @param Document $project * @param Database $dbForProject * @return void @@ -515,17 +515,17 @@ class Databases extends Action * @throws Structure * @throws Exception */ - protected function deleteCollection(Document $database, Document $collection, Document $project, Database $dbForProject): void + protected function deleteTable(Document $database, Document $table, Document $project, Database $dbForProject): void { - if ($collection->isEmpty()) { - throw new Exception('Missing collection'); + if ($table->isEmpty()) { + throw new Exception('Missing table'); } - $collectionId = $collection->getId(); - $collectionInternalId = $collection->getInternalId(); + $collectionId = $table->getId(); + $collectionInternalId = $table->getInternalId(); $databaseInternalId = $database->getInternalId(); - $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $collection->getInternalId()); + $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $table->getInternalId()); /** * Related collections relating to current collection @@ -558,50 +558,50 @@ class Databases extends Action /** - * @param string $collectionId + * @param string $tableId * @param array $queries * @param Database $database * @param callable|null $callback * @return void * @throws Exception */ - protected function deleteByGroup(string $collectionId, array $queries, Database $database, callable $callback = null): void + protected function deleteByGroup(string $tableId, array $queries, Database $database, callable $callback = null): void { $start = \microtime(true); try { $count = $database->deleteDocuments( - $collectionId, + $tableId, $queries, Database::DELETE_BATCH_SIZE, $callback ); } catch (\Throwable $th) { $tenant = $database->getSharedTables() ? 'Tenant:'.$database->getTenant() : ''; - Console::error("Failed to delete documents for collection:{$database->getNamespace()}_{$collectionId} {$tenant} :{$th->getMessage()}"); + Console::error("Failed to delete rows for table:{$database->getNamespace()}_{$tableId} {$tenant} :{$th->getMessage()}"); return; } $end = \microtime(true); - Console::info("Deleted {$count} documents by group in " . ($end - $start) . " seconds"); + Console::info("Deleted {$count} rows by group in " . ($end - $start) . " seconds"); } /** * @param Document $database - * @param Document $collection + * @param Document $table * @param Document $project * @param Realtime $queueForRealtime - * @param Document|null $attribute + * @param Document|null $column * @param Document|null $index * @return void */ protected function trigger( - Document $database, - Document $collection, - Document $project, - string $event, - Realtime $queueForRealtime, - Document|null $attribute = null, + Document $database, + Document $table, + Document $project, + string $event, + Realtime $queueForRealtime, + Document|null $column = null, Document|null $index = null, ): void { $queueForRealtime @@ -609,14 +609,14 @@ class Databases extends Action ->setSubscribers(['console']) ->setEvent($event) ->setParam('databaseId', $database->getId()) - ->setParam('collectionId', $collection->getId()); + ->setParam('tableId', $table->getId()); - if ($attribute !== null && !empty($attribute)) { + if (! empty($column)) { $queueForRealtime - ->setParam('attributeId', $attribute->getId()) - ->setPayload($attribute->getArrayCopy()); + ->setParam('columnId', $column->getId()) + ->setPayload($column->getArrayCopy()); } - if ($index !== null && !empty($index)) { + if (! empty($index)) { $queueForRealtime ->setParam('indexId', $index->getId()) ->setPayload($index->getArrayCopy()); diff --git a/src/Appwrite/Utopia/Request/Filters/DatabaseAliases.php b/src/Appwrite/Utopia/Request/Filters/DatabaseAliases.php new file mode 100644 index 0000000000..b2b772be11 --- /dev/null +++ b/src/Appwrite/Utopia/Request/Filters/DatabaseAliases.php @@ -0,0 +1,38 @@ + 'rowId', + 'attributes' => 'columns', + 'collectionId' => 'tableId', + 'attributeId' => 'columnId', + 'relatedCollectionId' => 'relatedTableId' + ]; + + public function parse(array $content, string $model): array + { + return $this->overrideDatabaseParams($content, $model); + } + + protected function overrideDatabaseParams(array $content, string $model): array + { + if (!str_starts_with($model, 'databases.')) { + return $content; + } + + $intersect = array_intersect_key(self::PARAMS_MAP, $content); + + foreach ($intersect as $oldKey => $newKey) { + $content[$newKey] = $content[$oldKey]; + unset($content[$oldKey]); + } + + return $content; + } +} diff --git a/src/Appwrite/Utopia/Request/Filters/V19.php b/src/Appwrite/Utopia/Request/Filters/V19.php index 9597f40570..041c126a69 100644 --- a/src/Appwrite/Utopia/Request/Filters/V19.php +++ b/src/Appwrite/Utopia/Request/Filters/V19.php @@ -6,32 +6,18 @@ use Appwrite\Utopia\Request\Filter; class V19 extends Filter { + // Convert 1.6 params to 1.7 public function parse(array $content, string $model): array { - return $this->overrideDatabaseParams($content, $model); - } - - // Database terminology change handling. - protected function overrideDatabaseParams(array $content, string $model): array - { - if (!str_starts_with($model, 'databases.')) { - return $content; - } - - $map = [ - 'collectionId' => 'tableId', - 'attributeId' => 'columnId', - 'attributes' => 'columns', - 'documentId' => 'rowId', - 'relatedCollectionId' => 'relatedTableId' - ]; - - foreach ($map as $oldKey => $newKey) { - if (isset($content[$oldKey])) { - $content[$newKey] = $content[$oldKey]; - unset($content[$oldKey]); - } + /* + Uncomment with first request filter; current is just a copy of V18 + switch ($model) { + case 'functions.create': + $content['something'] = $content['somethingElse'] ?? ""; + unset($content['something']); + break; } + */ return $content; } diff --git a/src/Appwrite/Utopia/Response/Model/Webhook.php b/src/Appwrite/Utopia/Response/Model/Webhook.php index 57abb4900d..8e53b41e6e 100644 --- a/src/Appwrite/Utopia/Response/Model/Webhook.php +++ b/src/Appwrite/Utopia/Response/Model/Webhook.php @@ -49,7 +49,7 @@ class Webhook extends Model 'type' => self::TYPE_STRING, 'description' => 'Webhook trigger events.', 'default' => [], - 'example' => 'database.collections.update', + 'example' => 'database.tables.update', 'array' => true, ]) ->addRule('security', [ From f94ecc885a4c4852f90f1c2ceac2d1c5d6adea58 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 27 Apr 2025 10:36:21 +0530 Subject: [PATCH 023/343] fix: tests as per new events system. --- tests/e2e/Services/Realtime/RealtimeBase.php | 6 +- .../Realtime/RealtimeConsoleClientTest.php | 98 ++++----- .../Realtime/RealtimeCustomClientTest.php | 202 +++++++++--------- tests/e2e/Services/Webhooks/WebhooksBase.php | 92 ++++---- .../Webhooks/WebhooksCustomServerTest.php | 40 ++-- tests/unit/Event/EventTest.php | 78 +++---- tests/unit/Event/MockPublisher.php | 2 +- .../Event/Validator/EventValidatorTest.php | 44 ++-- .../Validator/FunctionEventValidatorTest.php | 44 ++-- tests/unit/Messaging/MessagingTest.php | 38 ++-- 10 files changed, 322 insertions(+), 322 deletions(-) diff --git a/tests/e2e/Services/Realtime/RealtimeBase.php b/tests/e2e/Services/Realtime/RealtimeBase.php index 99f31134c0..0004781773 100644 --- a/tests/e2e/Services/Realtime/RealtimeBase.php +++ b/tests/e2e/Services/Realtime/RealtimeBase.php @@ -42,7 +42,7 @@ trait RealtimeBase /** * Test for SUCCESS */ - $client = $this->getWebsocket(["documents"]); + $client = $this->getWebsocket(["rows"]); $this->assertNotEmpty($client->receive()); $client->close(); } @@ -58,7 +58,7 @@ trait RealtimeBase $this->assertEquals(1008, $payload["data"]["code"]); $this->assertEquals("Missing channels", $payload["data"]["message"]); \usleep(250000); // 250ms - $this->expectException(ConnectionException::class); // Check if server disconnnected client + $this->expectException(ConnectionException::class); // Check if server disconnected client $client->close(); } @@ -83,7 +83,7 @@ trait RealtimeBase $payload["data"]["message"] ); \usleep(250000); // 250ms - $this->expectException(ConnectionException::class); // Check if server disconnnected client + $this->expectException(ConnectionException::class); // Check if server disconnected client $client->close(); } } diff --git a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php index 4e27457b05..a206692ea2 100644 --- a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php @@ -201,12 +201,12 @@ class RealtimeConsoleClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertContains('console', $response['data']['channels']); $this->assertContains("projects.{$projectId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.attributes.*.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.attributes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.columns.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.columns.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.columns.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.columns.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); @@ -222,12 +222,12 @@ class RealtimeConsoleClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertContains('console', $response['data']['channels']); $this->assertContains("projects.{$projectId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.attributes.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.attributes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.columns.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.columns.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.columns.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.columns.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); @@ -292,12 +292,12 @@ class RealtimeConsoleClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertContains('console', $response['data']['channels']); $this->assertContains("projects.{$projectId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.indexes.*.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.indexes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.indexes.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.indexes.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals('processing', $response['data']['payload']['status']); @@ -311,12 +311,12 @@ class RealtimeConsoleClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertContains('console', $response['data']['channels']); $this->assertContains("projects.{$projectId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.indexes.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.indexes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.indexes.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.indexes.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $this->assertEquals('available', $response['data']['payload']['status']); @@ -372,12 +372,12 @@ class RealtimeConsoleClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertContains('console', $response['data']['channels']); $this->assertContains("projects.{$projectId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.indexes.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.indexes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.indexes.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.indexes.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); /** Delete index generates two events. One from the API and one from the database worker */ @@ -390,12 +390,12 @@ class RealtimeConsoleClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertContains('console', $response['data']['channels']); $this->assertContains("projects.{$projectId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.indexes.*.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.indexes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.indexes.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.indexes.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $client->close(); @@ -449,12 +449,12 @@ class RealtimeConsoleClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertContains('console', $response['data']['channels']); $this->assertContains("projects.{$projectId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.attributes.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.attributes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.columns.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.columns.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.columns.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.columns.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $response = json_decode($client->receive(), true); @@ -467,12 +467,12 @@ class RealtimeConsoleClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertContains('console', $response['data']['channels']); $this->assertContains("projects.{$projectId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.attributes.*.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.attributes.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.columns.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.columns.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.columns.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.columns.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); $client->close(); @@ -607,7 +607,7 @@ class RealtimeConsoleClientTest extends Scope $this->assertContains("projects.{$projectId}", $response['data']['channels']); $this->assertArrayHasKey('buildLogs', $response['data']['payload']); - // Ignore comparasion for first payload + // Ignore comparison for first payload if ($previousBuildLogs !== null) { $this->assertNotEquals($previousBuildLogs, $response['data']['payload']['buildLogs']); } diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index e356397408..d279bb45c7 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -31,7 +31,7 @@ class RealtimeCustomClientTest extends Scope 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session ]; - $client = $this->getWebsocket(['documents'], $headers); + $client = $this->getWebsocket(['rows'], $headers); $response = json_decode($client->receive(), true); $this->assertArrayHasKey('type', $response); @@ -40,7 +40,7 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']['user']); $this->assertCount(1, $response['data']['channels']); - $this->assertContains('documents', $response['data']['channels']); + $this->assertContains('rows', $response['data']['channels']); $this->assertEquals($userId, $response['data']['user']['$id']); $client->close(); @@ -60,7 +60,7 @@ class RealtimeCustomClientTest extends Scope $client->close(); - $client = $this->getWebsocket(['account', 'documents', 'account.123'], $headers); + $client = $this->getWebsocket(['account', 'rows', 'account.123'], $headers); $response = json_decode($client->receive(), true); $this->assertArrayHasKey('type', $response); @@ -69,7 +69,7 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']['user']); $this->assertCount(3, $response['data']['channels']); - $this->assertContains('documents', $response['data']['channels']); + $this->assertContains('rows', $response['data']['channels']); $this->assertContains('account', $response['data']['channels']); $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertEquals($userId, $response['data']['user']['$id']); @@ -80,12 +80,12 @@ class RealtimeCustomClientTest extends Scope 'account', 'files', 'files.1', - 'collections', - 'collections.1.documents', - 'collections.2.documents', - 'documents', - 'collections.1.documents.1', - 'collections.2.documents.2', + 'tables', + 'tables.1.rows', + 'tables.2.rows', + 'rows', + 'tables.1.rows.1', + 'tables.2.rows.2', ], $headers); $response = json_decode($client->receive(), true); @@ -100,12 +100,12 @@ class RealtimeCustomClientTest extends Scope $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains('files', $response['data']['channels']); $this->assertContains('files.1', $response['data']['channels']); - $this->assertContains('collections', $response['data']['channels']); - $this->assertContains('collections.1.documents', $response['data']['channels']); - $this->assertContains('collections.2.documents', $response['data']['channels']); - $this->assertContains('documents', $response['data']['channels']); - $this->assertContains('collections.1.documents.1', $response['data']['channels']); - $this->assertContains('collections.2.documents.2', $response['data']['channels']); + $this->assertContains('tables', $response['data']['channels']); + $this->assertContains('tables.1.rows', $response['data']['channels']); + $this->assertContains('tables.2.rows', $response['data']['channels']); + $this->assertContains('rows', $response['data']['channels']); + $this->assertContains('tables.1.rows.1', $response['data']['channels']); + $this->assertContains('tables.2.rows.2', $response['data']['channels']); $this->assertEquals($userId, $response['data']['user']['$id']); $client->close(); @@ -245,7 +245,7 @@ class RealtimeCustomClientTest extends Scope /** * Test for FAILURE */ - $client = $this->getWebsocket(['documents'], ['origin' => 'http://appwrite.unknown']); + $client = $this->getWebsocket(['rows'], ['origin' => 'http://appwrite.unknown']); $payload = json_decode($client->receive(), true); $this->assertArrayHasKey('type', $payload); @@ -675,7 +675,7 @@ class RealtimeCustomClientTest extends Scope $session = $user['session'] ?? ''; $projectId = $this->getProject()['$id']; - $client = $this->getWebsocket(['documents', 'collections'], [ + $client = $this->getWebsocket(['rows', 'tables'], [ 'origin' => 'http://localhost', 'cookie' => 'a_session_' . $projectId . '=' . $session ]); @@ -687,8 +687,8 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('connected', $response['type']); $this->assertNotEmpty($response['data']); $this->assertCount(2, $response['data']['channels']); - $this->assertContains('documents', $response['data']['channels']); - $this->assertContains('collections', $response['data']['channels']); + $this->assertContains('rows', $response['data']['channels']); + $this->assertContains('tables', $response['data']['channels']); $this->assertNotEmpty($response['data']['user']); $this->assertEquals($user['$id'], $response['data']['user']['$id']); @@ -770,19 +770,19 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertCount(3, $response['data']['channels']); - $this->assertContains('documents', $response['data']['channels']); - $this->assertContains('databases.' . $databaseId . '.collections.' . $actorsId . '.documents.' . $documentId, $response['data']['channels']); - $this->assertContains('databases.' . $databaseId . '.collections.' . $actorsId . '.documents', $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.*.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains('rows', $response['data']['channels']); + $this->assertContains('databases.' . $databaseId . '.tables.' . $actorsId . '.rows.' . $documentId, $response['data']['channels']); + $this->assertContains('databases.' . $databaseId . '.tables.' . $actorsId . '.rows', $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); @@ -814,19 +814,19 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertCount(3, $response['data']['channels']); - $this->assertContains('documents', $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains('rows', $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); @@ -868,19 +868,19 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertCount(3, $response['data']['channels']); - $this->assertContains('documents', $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains('rows', $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); @@ -895,7 +895,7 @@ class RealtimeCustomClientTest extends Scope $session = $user['session'] ?? ''; $projectId = $this->getProject()['$id']; - $client = $this->getWebsocket(['documents', 'collections'], [ + $client = $this->getWebsocket(['rows', 'tables'], [ 'origin' => 'http://localhost', 'cookie' => 'a_session_' . $projectId . '=' . $session ]); @@ -907,8 +907,8 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('connected', $response['type']); $this->assertNotEmpty($response['data']); $this->assertCount(2, $response['data']['channels']); - $this->assertContains('documents', $response['data']['channels']); - $this->assertContains('collections', $response['data']['channels']); + $this->assertContains('rows', $response['data']['channels']); + $this->assertContains('tables', $response['data']['channels']); $this->assertNotEmpty($response['data']['user']); $this->assertEquals($user['$id'], $response['data']['user']['$id']); @@ -988,19 +988,19 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertCount(3, $response['data']['channels']); - $this->assertContains('documents', $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.*.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains('rows', $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); @@ -1027,19 +1027,19 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertCount(3, $response['data']['channels']); - $this->assertContains('documents', $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains('rows', $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); @@ -1077,19 +1077,19 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); $this->assertCount(3, $response['data']['channels']); - $this->assertContains('documents', $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains('rows', $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*.rows.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index c743810feb..5cd95c220d 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -83,10 +83,10 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -155,12 +155,12 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.columns.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.columns.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.columns.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.columns.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -181,12 +181,12 @@ trait WebhooksBase // $this->assertEquals($webhook['method'], 'DELETE'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.columns.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.columns.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.columns.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.columns.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -234,16 +234,16 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -296,16 +296,16 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -366,16 +366,16 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php index d2f132e960..14188a807b 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php @@ -48,10 +48,10 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -96,12 +96,12 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.indexes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.indexes.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -121,12 +121,12 @@ class WebhooksCustomServerTest extends Scope // $this->assertEquals($webhook['method'], 'DELETE'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.indexes.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.indexes.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -189,10 +189,10 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); diff --git a/tests/unit/Event/EventTest.php b/tests/unit/Event/EventTest.php index c852cf2757..d5936e4b8f 100644 --- a/tests/unit/Event/EventTest.php +++ b/tests/unit/Event/EventTest.php @@ -93,57 +93,57 @@ class EventTest extends TestCase $this->assertContains('users.*.update', $event); $this->assertContains('users.*', $event); - $event = Event::generateEvents('collections.[collectionId].documents.[documentId].create', [ - 'collectionId' => 'chapters', - 'documentId' => 'prolog', + $event = Event::generateEvents('tables.[tableId].rows.[rowId].create', [ + 'tableId' => 'chapters', + 'rowId' => 'prolog', ]); $this->assertCount(10, $event); - $this->assertContains('collections.chapters.documents.prolog.create', $event); - $this->assertContains('collections.chapters.documents.prolog', $event); - $this->assertContains('collections.chapters.documents.*.create', $event); - $this->assertContains('collections.chapters.documents.*', $event); - $this->assertContains('collections.chapters', $event); - $this->assertContains('collections.*.documents.prolog.create', $event); - $this->assertContains('collections.*.documents.prolog', $event); - $this->assertContains('collections.*.documents.*.create', $event); - $this->assertContains('collections.*.documents.*', $event); - $this->assertContains('collections.*', $event); + $this->assertContains('tables.chapters.rows.prolog.create', $event); + $this->assertContains('tables.chapters.rows.prolog', $event); + $this->assertContains('tables.chapters.rows.*.create', $event); + $this->assertContains('tables.chapters.rows.*', $event); + $this->assertContains('tables.chapters', $event); + $this->assertContains('tables.*.rows.prolog.create', $event); + $this->assertContains('tables.*.rows.prolog', $event); + $this->assertContains('tables.*.rows.*.create', $event); + $this->assertContains('tables.*.rows.*', $event); + $this->assertContains('tables.*', $event); - $event = Event::generateEvents('databases.[databaseId].collections.[collectionId].documents.[documentId].create', [ + $event = Event::generateEvents('databases.[databaseId].tables.[tableId].rows.[rowId].create', [ 'databaseId' => 'chaptersDB', - 'collectionId' => 'chapters', - 'documentId' => 'prolog', + 'tableId' => 'chapters', + 'rowId' => 'prolog', ]); $this->assertCount(22, $event); - $this->assertContains('databases.chaptersDB.collections.chapters.documents.prolog.create', $event); - $this->assertContains('databases.chaptersDB.collections.chapters.documents.prolog', $event); - $this->assertContains('databases.chaptersDB.collections.chapters.documents.*.create', $event); - $this->assertContains('databases.chaptersDB.collections.chapters.documents.*', $event); - $this->assertContains('databases.chaptersDB.collections.chapters', $event); - $this->assertContains('databases.chaptersDB.collections.*.documents.prolog.create', $event); - $this->assertContains('databases.chaptersDB.collections.*.documents.prolog', $event); - $this->assertContains('databases.chaptersDB.collections.*', $event); + $this->assertContains('databases.chaptersDB.tables.chapters.rows.prolog.create', $event); + $this->assertContains('databases.chaptersDB.tables.chapters.rows.prolog', $event); + $this->assertContains('databases.chaptersDB.tables.chapters.rows.*.create', $event); + $this->assertContains('databases.chaptersDB.tables.chapters.rows.*', $event); + $this->assertContains('databases.chaptersDB.tables.chapters', $event); + $this->assertContains('databases.chaptersDB.tables.*.rows.prolog.create', $event); + $this->assertContains('databases.chaptersDB.tables.*.rows.prolog', $event); + $this->assertContains('databases.chaptersDB.tables.*', $event); $this->assertContains('databases.chaptersDB', $event); - $this->assertContains('databases.*.collections.chapters.documents.prolog.create', $event); - $this->assertContains('databases.*.collections.chapters.documents.prolog', $event); - $this->assertContains('databases.*.collections.chapters', $event); - $this->assertContains('databases.*.collections.*.documents.*.create', $event); - $this->assertContains('databases.*.collections.*.documents.*', $event); - $this->assertContains('databases.*.collections.*', $event); + $this->assertContains('databases.*.tables.chapters.rows.prolog.create', $event); + $this->assertContains('databases.*.tables.chapters.rows.prolog', $event); + $this->assertContains('databases.*.tables.chapters', $event); + $this->assertContains('databases.*.tables.*.rows.*.create', $event); + $this->assertContains('databases.*.tables.*.rows.*', $event); + $this->assertContains('databases.*.tables.*', $event); $this->assertContains('databases.*', $event); - $this->assertContains('databases.*.collections.*.documents.prolog', $event); - $this->assertContains('databases.*.collections.*.documents.prolog.create', $event); - $this->assertContains('databases.*.collections.chapters.documents.*', $event); - $this->assertContains('databases.*.collections.chapters.documents.*.create', $event); - $this->assertContains('databases.chaptersDB.collections.*.documents.*', $event); - $this->assertContains('databases.chaptersDB.collections.*.documents.*.create', $event); + $this->assertContains('databases.*.tables.*.rows.prolog', $event); + $this->assertContains('databases.*.tables.*.rows.prolog.create', $event); + $this->assertContains('databases.*.tables.chapters.rows.*', $event); + $this->assertContains('databases.*.tables.chapters.rows.*.create', $event); + $this->assertContains('databases.chaptersDB.tables.*.rows.*', $event); + $this->assertContains('databases.chaptersDB.tables.*.rows.*.create', $event); try { - $event = Event::generateEvents('collections.[collectionId].documents.[documentId].create', [ - 'collectionId' => 'chapters' + $event = Event::generateEvents('tables.[tableId].rows.[rowId].create', [ + 'tableId' => 'chapters' ]); $this->fail(); } catch (\Throwable $th) { @@ -151,7 +151,7 @@ class EventTest extends TestCase } try { - $event = Event::generateEvents('collections.[collectionId].documents.[documentId].create'); + $event = Event::generateEvents('tables.[tableId].rows.[rowId].create'); $this->fail(); } catch (\Throwable $th) { $this->assertInstanceOf(InvalidArgumentException::class, $th, 'An invalid exception was thrown'); diff --git a/tests/unit/Event/MockPublisher.php b/tests/unit/Event/MockPublisher.php index 54fcc89358..0b812e7032 100644 --- a/tests/unit/Event/MockPublisher.php +++ b/tests/unit/Event/MockPublisher.php @@ -7,7 +7,7 @@ use Utopia\Queue\Queue; class MockPublisher implements Publisher { - private $events = []; + private array $events = []; public function enqueue(Queue $queue, array $payload): bool { diff --git a/tests/unit/Event/Validator/EventValidatorTest.php b/tests/unit/Event/Validator/EventValidatorTest.php index e9f652adeb..6885d20bfb 100644 --- a/tests/unit/Event/Validator/EventValidatorTest.php +++ b/tests/unit/Event/Validator/EventValidatorTest.php @@ -29,27 +29,27 @@ class EventValidatorTest extends TestCase $this->assertTrue($this->object->isValid('users.*.update.email')); $this->assertTrue($this->object->isValid('users.*.update')); $this->assertTrue($this->object->isValid('users.*')); - $this->assertTrue($this->object->isValid('databases.books.collections.chapters.documents.prolog.create')); - $this->assertTrue($this->object->isValid('databases.books.collections.chapters.documents.prolog')); - $this->assertTrue($this->object->isValid('databases.books.collections.chapters.documents.*.create')); - $this->assertTrue($this->object->isValid('databases.books.collections.chapters.documents.*')); - $this->assertTrue($this->object->isValid('databases.books.collections.*.documents.prolog.create')); - $this->assertTrue($this->object->isValid('databases.books.collections.*.documents.prolog')); - $this->assertTrue($this->object->isValid('databases.books.collections.*.documents.*.create')); - $this->assertTrue($this->object->isValid('databases.books.collections.*.documents.*')); - $this->assertTrue($this->object->isValid('databases.*.collections.chapters.documents.prolog.create')); - $this->assertTrue($this->object->isValid('databases.*.collections.chapters.documents.prolog')); - $this->assertTrue($this->object->isValid('databases.*.collections.chapters.documents.*.create')); - $this->assertTrue($this->object->isValid('databases.*.collections.chapters.documents.*')); - $this->assertTrue($this->object->isValid('databases.*.collections.*.documents.prolog.create')); - $this->assertTrue($this->object->isValid('databases.*.collections.*.documents.prolog')); - $this->assertTrue($this->object->isValid('databases.*.collections.*.documents.*.create')); - $this->assertTrue($this->object->isValid('databases.*.collections.*.documents.*')); - $this->assertTrue($this->object->isValid('databases.*.collections.*')); + $this->assertTrue($this->object->isValid('databases.books.tables.chapters.rows.prolog.create')); + $this->assertTrue($this->object->isValid('databases.books.tables.chapters.rows.prolog')); + $this->assertTrue($this->object->isValid('databases.books.tables.chapters.rows.*.create')); + $this->assertTrue($this->object->isValid('databases.books.tables.chapters.rows.*')); + $this->assertTrue($this->object->isValid('databases.books.tables.*.rows.prolog.create')); + $this->assertTrue($this->object->isValid('databases.books.tables.*.rows.prolog')); + $this->assertTrue($this->object->isValid('databases.books.tables.*.rows.*.create')); + $this->assertTrue($this->object->isValid('databases.books.tables.*.rows.*')); + $this->assertTrue($this->object->isValid('databases.*.tables.chapters.rows.prolog.create')); + $this->assertTrue($this->object->isValid('databases.*.tables.chapters.rows.prolog')); + $this->assertTrue($this->object->isValid('databases.*.tables.chapters.rows.*.create')); + $this->assertTrue($this->object->isValid('databases.*.tables.chapters.rows.*')); + $this->assertTrue($this->object->isValid('databases.*.tables.*.rows.prolog.create')); + $this->assertTrue($this->object->isValid('databases.*.tables.*.rows.prolog')); + $this->assertTrue($this->object->isValid('databases.*.tables.*.rows.*.create')); + $this->assertTrue($this->object->isValid('databases.*.tables.*.rows.*')); + $this->assertTrue($this->object->isValid('databases.*.tables.*')); $this->assertTrue($this->object->isValid('databases.*')); $this->assertTrue($this->object->isValid('databases.books')); - $this->assertTrue($this->object->isValid('databases.books.collections.chapters')); - $this->assertTrue($this->object->isValid('databases.books.collections.*')); + $this->assertTrue($this->object->isValid('databases.books.tables.chapters')); + $this->assertTrue($this->object->isValid('databases.books.tables.*')); $this->assertTrue($this->object->isValid('functions.*')); $this->assertTrue($this->object->isValid('buckets.*')); $this->assertTrue($this->object->isValid('teams.*')); @@ -63,9 +63,9 @@ class EventValidatorTest extends TestCase $this->assertFalse($this->object->isValid(null)); $this->assertFalse($this->object->isValid('')); $this->assertFalse($this->object->isValid('unknown.*')); - $this->assertFalse($this->object->isValid('collections')); - $this->assertFalse($this->object->isValid('collections.*.unknown')); - $this->assertFalse($this->object->isValid('collections.*.documents.*.unknown')); + $this->assertFalse($this->object->isValid('tables')); + $this->assertFalse($this->object->isValid('tables.*.unknown')); + $this->assertFalse($this->object->isValid('tables.*.rows.*.unknown')); $this->assertFalse($this->object->isValid('users.torsten.unknown')); $this->assertFalse($this->object->isValid('users.torsten.delete.email')); $this->assertFalse($this->object->isValid('teams.*.memberships.*.update.unknown')); diff --git a/tests/unit/Event/Validator/FunctionEventValidatorTest.php b/tests/unit/Event/Validator/FunctionEventValidatorTest.php index ea59f6771a..9b6e05b9f7 100644 --- a/tests/unit/Event/Validator/FunctionEventValidatorTest.php +++ b/tests/unit/Event/Validator/FunctionEventValidatorTest.php @@ -29,27 +29,27 @@ class FunctionEventValidatorTest extends TestCase $this->assertTrue($this->object->isValid('users.*.update.email')); $this->assertTrue($this->object->isValid('users.*.update')); $this->assertTrue($this->object->isValid('users.*')); - $this->assertTrue($this->object->isValid('databases.books.collections.chapters.documents.prolog.create')); - $this->assertTrue($this->object->isValid('databases.books.collections.chapters.documents.prolog')); - $this->assertTrue($this->object->isValid('databases.books.collections.chapters.documents.*.create')); - $this->assertTrue($this->object->isValid('databases.books.collections.chapters.documents.*')); - $this->assertTrue($this->object->isValid('databases.books.collections.*.documents.prolog.create')); - $this->assertTrue($this->object->isValid('databases.books.collections.*.documents.prolog')); - $this->assertTrue($this->object->isValid('databases.books.collections.*.documents.*.create')); - $this->assertTrue($this->object->isValid('databases.books.collections.*.documents.*')); - $this->assertTrue($this->object->isValid('databases.*.collections.chapters.documents.prolog.create')); - $this->assertTrue($this->object->isValid('databases.*.collections.chapters.documents.prolog')); - $this->assertTrue($this->object->isValid('databases.*.collections.chapters.documents.*.create')); - $this->assertTrue($this->object->isValid('databases.*.collections.chapters.documents.*')); - $this->assertTrue($this->object->isValid('databases.*.collections.*.documents.prolog.create')); - $this->assertTrue($this->object->isValid('databases.*.collections.*.documents.prolog')); - $this->assertTrue($this->object->isValid('databases.*.collections.*.documents.*.create')); - $this->assertTrue($this->object->isValid('databases.*.collections.*.documents.*')); - $this->assertTrue($this->object->isValid('databases.*.collections.*')); + $this->assertTrue($this->object->isValid('databases.books.tables.chapters.rows.prolog.create')); + $this->assertTrue($this->object->isValid('databases.books.tables.chapters.rows.prolog')); + $this->assertTrue($this->object->isValid('databases.books.tables.chapters.rows.*.create')); + $this->assertTrue($this->object->isValid('databases.books.tables.chapters.rows.*')); + $this->assertTrue($this->object->isValid('databases.books.tables.*.rows.prolog.create')); + $this->assertTrue($this->object->isValid('databases.books.tables.*.rows.prolog')); + $this->assertTrue($this->object->isValid('databases.books.tables.*.rows.*.create')); + $this->assertTrue($this->object->isValid('databases.books.tables.*.rows.*')); + $this->assertTrue($this->object->isValid('databases.*.tables.chapters.rows.prolog.create')); + $this->assertTrue($this->object->isValid('databases.*.tables.chapters.rows.prolog')); + $this->assertTrue($this->object->isValid('databases.*.tables.chapters.rows.*.create')); + $this->assertTrue($this->object->isValid('databases.*.tables.chapters.rows.*')); + $this->assertTrue($this->object->isValid('databases.*.tables.*.rows.prolog.create')); + $this->assertTrue($this->object->isValid('databases.*.tables.*.rows.prolog')); + $this->assertTrue($this->object->isValid('databases.*.tables.*.rows.*.create')); + $this->assertTrue($this->object->isValid('databases.*.tables.*.rows.*')); + $this->assertTrue($this->object->isValid('databases.*.tables.*')); $this->assertTrue($this->object->isValid('databases.*')); $this->assertTrue($this->object->isValid('databases.books')); - $this->assertTrue($this->object->isValid('databases.books.collections.chapters')); - $this->assertTrue($this->object->isValid('databases.books.collections.*')); + $this->assertTrue($this->object->isValid('databases.books.tables.chapters')); + $this->assertTrue($this->object->isValid('databases.books.tables.*')); $this->assertTrue($this->object->isValid('buckets.*')); $this->assertTrue($this->object->isValid('teams.*')); $this->assertTrue($this->object->isValid('users.*')); @@ -62,9 +62,9 @@ class FunctionEventValidatorTest extends TestCase $this->assertFalse($this->object->isValid(null)); $this->assertFalse($this->object->isValid('')); $this->assertFalse($this->object->isValid('unknown.*')); - $this->assertFalse($this->object->isValid('collections')); - $this->assertFalse($this->object->isValid('collections.*.unknown')); - $this->assertFalse($this->object->isValid('collections.*.documents.*.unknown')); + $this->assertFalse($this->object->isValid('tables')); + $this->assertFalse($this->object->isValid('tables.*.unknown')); + $this->assertFalse($this->object->isValid('tables.*.rows.*.unknown')); $this->assertFalse($this->object->isValid('users.torsten.unknown')); $this->assertFalse($this->object->isValid('users.torsten.delete.email')); $this->assertFalse($this->object->isValid('teams.*.memberships.*.update.unknown')); diff --git a/tests/unit/Messaging/MessagingTest.php b/tests/unit/Messaging/MessagingTest.php index c2b6490869..2cb15c5750 100644 --- a/tests/unit/Messaging/MessagingTest.php +++ b/tests/unit/Messaging/MessagingTest.php @@ -35,7 +35,7 @@ class MessagingTest extends TestCase Role::team(ID::custom('def'))->toString(), Role::team(ID::custom('def'), 'guest')->toString(), ], - ['files' => 0, 'documents' => 0, 'documents.789' => 0, 'account.123' => 0] + ['files' => 0, 'rows' => 0, 'rows.789' => 0, 'account.123' => 0] ); $event = [ @@ -115,13 +115,13 @@ class MessagingTest extends TestCase $this->assertEmpty($receivers); $event['roles'] = [Role::any()->toString()]; - $event['data']['channels'] = ['documents.123']; + $event['data']['channels'] = ['rows.123']; $receivers = $realtime->getSubscribers($event); $this->assertEmpty($receivers); - $event['data']['channels'] = ['documents.789']; + $event['data']['channels'] = ['rows.789']; $receivers = $realtime->getSubscribers($event); @@ -153,8 +153,8 @@ class MessagingTest extends TestCase $channels = [ 0 => 'files', - 1 => 'documents', - 2 => 'documents.789', + 1 => 'rows', + 2 => 'rows.789', 3 => 'account', 4 => 'account.456' ]; @@ -162,8 +162,8 @@ class MessagingTest extends TestCase $channels = Realtime::convertChannels($channels, $user->getId()); $this->assertCount(4, $channels); $this->assertArrayHasKey('files', $channels); - $this->assertArrayHasKey('documents', $channels); - $this->assertArrayHasKey('documents.789', $channels); + $this->assertArrayHasKey('rows', $channels); + $this->assertArrayHasKey('rows.789', $channels); $this->assertArrayHasKey('account', $channels); $this->assertArrayNotHasKey('account.456', $channels); } @@ -190,8 +190,8 @@ class MessagingTest extends TestCase ]); $channels = [ 0 => 'files', - 1 => 'documents', - 2 => 'documents.789', + 1 => 'rows', + 2 => 'rows.789', 3 => 'account', 4 => 'account.456' ]; @@ -200,8 +200,8 @@ class MessagingTest extends TestCase $this->assertCount(5, $channels); $this->assertArrayHasKey('files', $channels); - $this->assertArrayHasKey('documents', $channels); - $this->assertArrayHasKey('documents.789', $channels); + $this->assertArrayHasKey('rows', $channels); + $this->assertArrayHasKey('rows.789', $channels); $this->assertArrayHasKey('account.123', $channels); $this->assertArrayHasKey('account', $channels); $this->assertArrayNotHasKey('account.456', $channels); @@ -213,10 +213,10 @@ class MessagingTest extends TestCase * Test Collection Level Permissions */ $result = Realtime::fromPayload( - event: 'databases.database_id.collections.collection_id.documents.document_id.create', + event: 'databases.database_id.tables.collection_id.rows.document_id.create', payload: new Document([ '$id' => ID::custom('test'), - '$collection' => ID::custom('collection'), + '$collection' => ID::custom('table'), '$permissions' => [ Permission::read(Role::team('123abc')), Permission::update(Role::team('123abc')), @@ -226,8 +226,8 @@ class MessagingTest extends TestCase database: new Document([ '$id' => ID::custom('database'), ]), - collection: new Document([ - '$id' => ID::custom('collection'), + table: new Document([ + '$id' => ID::custom('table'), '$permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -243,10 +243,10 @@ class MessagingTest extends TestCase * Test Document Level Permissions */ $result = Realtime::fromPayload( - event: 'databases.database_id.collections.collection_id.documents.document_id.create', + event: 'databases.database_id.tables.collection_id.rows.document_id.create', payload: new Document([ '$id' => ID::custom('test'), - '$collection' => ID::custom('collection'), + '$collection' => ID::custom('table'), '$permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -256,8 +256,8 @@ class MessagingTest extends TestCase database: new Document([ '$id' => ID::custom('database'), ]), - collection: new Document([ - '$id' => ID::custom('collection'), + table: new Document([ + '$id' => ID::custom('table'), '$permissions' => [ Permission::read(Role::team('123abc')), Permission::update(Role::team('123abc')), From 9cccd89439431736ead2620732fe9fd64fda9048 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 27 Apr 2025 14:08:26 +0530 Subject: [PATCH 024/343] fix: graphql tests. --- tests/e2e/Services/GraphQL/AbuseTest.php | 6 +- tests/e2e/Services/GraphQL/AuthTest.php | 53 +-- tests/e2e/Services/GraphQL/Base.php | 302 +++++++++--------- .../Services/GraphQL/DatabaseClientTest.php | 2 +- .../Services/GraphQL/DatabaseServerTest.php | 287 ++++++++--------- 5 files changed, 326 insertions(+), 324 deletions(-) diff --git a/tests/e2e/Services/GraphQL/AbuseTest.php b/tests/e2e/Services/GraphQL/AbuseTest.php index ea97492c2b..7137123757 100644 --- a/tests/e2e/Services/GraphQL/AbuseTest.php +++ b/tests/e2e/Services/GraphQL/AbuseTest.php @@ -32,7 +32,7 @@ class AbuseTest extends Scope $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_DOCUMENT); + $query = $this->getQuery(self::$CREATE_ROW); $max = 120; for ($i = 0; $i <= $max + 1; $i++) { @@ -133,7 +133,7 @@ class AbuseTest extends Scope $databaseId = $response['body']['data']['databasesCreate']['_id']; - $query = $this->getQuery(self::$CREATE_COLLECTION); + $query = $this->getQuery(self::$CREATE_TABLE); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -156,7 +156,7 @@ class AbuseTest extends Scope $collectionId = $response['body']['data']['databasesCreateCollection']['_id']; - $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_STRING_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ diff --git a/tests/e2e/Services/GraphQL/AuthTest.php b/tests/e2e/Services/GraphQL/AuthTest.php index ecce29f2b3..d8bd0d6326 100644 --- a/tests/e2e/Services/GraphQL/AuthTest.php +++ b/tests/e2e/Services/GraphQL/AuthTest.php @@ -23,7 +23,7 @@ class AuthTest extends Scope private string $token2; private array $database; - private array $collection; + private array $table; public function setUp(): void { @@ -101,7 +101,7 @@ class AuthTest extends Scope ], $gqlPayload); // Create collection - $query = $this->getQuery(self::$CREATE_COLLECTION); + $query = $this->getQuery(self::$CREATE_TABLE); $userId = $this->account1['body']['data']['accountCreate']['_id']; $gqlPayload = [ 'query' => $query, @@ -115,19 +115,19 @@ class AuthTest extends Scope ] ] ]; - $this->collection = $this->client->call(Client::METHOD_POST, '/graphql', [ + $this->table = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $this->getProject()['apiKey'], ], $gqlPayload); // Create string attribute - $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_STRING_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], + 'collectionId' => $this->table['body']['data']['databasesCreateTable']['_id'], 'key' => 'name', 'size' => 256, 'required' => true, @@ -147,13 +147,13 @@ class AuthTest extends Scope $projectId = $this->getProject()['$id']; // Create document as account 1 - $query = $this->getQuery(self::$CREATE_DOCUMENT); + $query = $this->getQuery(self::$CREATE_ROW); $userId = $this->account1['body']['data']['accountCreate']['_id']; $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], + 'collectionId' => $this->table['body']['data']['databasesCreateTable']['_id'], 'documentId' => ID::unique(), 'data' => [ 'name' => 'John Doe', @@ -165,40 +165,41 @@ class AuthTest extends Scope ] ] ]; - $document = $this->client->call(Client::METHOD_POST, '/graphql', [ + + $row = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); // Try to read as account 1 - $query = $this->getQuery(self::$GET_DOCUMENT); + $query = $this->getQuery(self::$GET_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], - 'documentId' => $document['body']['data']['databasesCreateDocument']['_id'], + 'collectionId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'documentId' => $row['body']['data']['databasesCreateRow']['_id'], ] ]; - $document = $this->client->call(Client::METHOD_POST, '/graphql', [ + $row = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); - $this->assertIsArray($document['body']['data']['databasesGetDocument']); - $this->assertArrayNotHasKey('errors', $document['body']); + $this->assertIsArray($row['body']['data']['databasesGetRow']); + $this->assertArrayNotHasKey('errors', $row['body']); // Try to read as account 2 - $document = $this->client->call(Client::METHOD_POST, '/graphql', [ + $row = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'cookie' => 'a_session_' . $projectId . '=' . $this->token2, ], $gqlPayload); - $this->assertArrayHasKey('errors', $document['body']); - $this->assertEquals('Document with the requested ID could not be found.', $document['body']['errors'][0]['message']); + $this->assertArrayHasKey('errors', $row['body']); + $this->assertEquals('Document with the requested ID could not be found.', $row['body']['errors'][0]['message']); } public function testValidAuth() @@ -206,13 +207,13 @@ class AuthTest extends Scope $projectId = $this->getProject()['$id']; // Create document as account 1 - $query = $this->getQuery(self::$CREATE_DOCUMENT); + $query = $this->getQuery(self::$CREATE_ROW); $userId = $this->account1['body']['data']['accountCreate']['_id']; $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], + 'collectionId' => $this->table['body']['data']['databasesCreateTable']['_id'], 'documentId' => ID::unique(), 'data' => [ 'name' => 'John Doe', @@ -224,29 +225,29 @@ class AuthTest extends Scope ], ] ]; - $document = $this->client->call(Client::METHOD_POST, '/graphql', [ + $row = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); // Try to delete as account 1 - $query = $this->getQuery(self::$DELETE_DOCUMENT); + $query = $this->getQuery(self::$DELETE_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], - 'documentId' => $document['body']['data']['databasesCreateDocument']['_id'], + 'collectionId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'documentId' => $row['body']['data']['databasesCreateRow']['_id'], ] ]; - $document = $this->client->call(Client::METHOD_POST, '/graphql', [ + $row = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); - $this->assertIsNotArray($document['body']); - $this->assertEquals(204, $document['headers']['status-code']); + $this->assertIsNotArray($row['body']); + $this->assertEquals(204, $row['headers']['status-code']); } } diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 121d40156e..95f446cf6f 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -13,49 +13,49 @@ trait Base public static string $GET_DATABASE = 'get_database'; public static string $UPDATE_DATABASE = 'update_database'; public static string $DELETE_DATABASE = 'delete_database'; - // Collections - public static string $CREATE_COLLECTION = 'create_collection'; - public static string $GET_COLLECTION = 'get_collection'; - public static string $GET_COLLECTIONS = 'list_collections'; - public static string $UPDATE_COLLECTION = 'update_collection'; - public static string $DELETE_COLLECTION = 'delete_collection'; - // Attributes - public static string $CREATE_STRING_ATTRIBUTE = 'create_string_attribute'; - public static string $CREATE_INTEGER_ATTRIBUTE = 'create_integer_attribute'; - public static string $CREATE_FLOAT_ATTRIBUTE = 'create_float_attribute'; - public static string $CREATE_BOOLEAN_ATTRIBUTE = 'create_boolean_attribute'; - public static string $CREATE_URL_ATTRIBUTE = 'create_url_attribute'; - public static string $CREATE_EMAIL_ATTRIBUTE = 'create_email_attribute'; - public static string $CREATE_IP_ATTRIBUTE = 'create_ip_attribute'; - public static string $CREATE_ENUM_ATTRIBUTE = 'create_enum_attribute'; - public static string $CREATE_DATETIME_ATTRIBUTE = 'create_datetime_attribute'; + // Tables + public static string $CREATE_TABLE = 'create_table'; + public static string $GET_TABLE = 'get_table'; + public static string $GET_TABLES = 'list_tables'; + public static string $UPDATE_TABLE = 'update_table'; + public static string $DELETE_TABLE = 'delete_table'; + // Columns + public static string $CREATE_STRING_COLUMN = 'create_string_column'; + public static string $CREATE_INTEGER_COLUMN = 'create_integer_column'; + public static string $CREATE_FLOAT_COLUMN = 'create_float_column'; + public static string $CREATE_BOOLEAN_COLUMN = 'create_boolean_column'; + public static string $CREATE_URL_COLUMN = 'create_url_column'; + public static string $CREATE_EMAIL_COLUMN = 'create_email_column'; + public static string $CREATE_IP_COLUMN = 'create_ip_column'; + public static string $CREATE_ENUM_COLUMN = 'create_enum_column'; + public static string $CREATE_DATETIME_COLUMN = 'create_datetime_column'; - public static string $CREATE_RELATIONSHIP_ATTRIBUTE = 'create_relationship_attribute'; - public static string $UPDATE_STRING_ATTRIBUTE = 'update_string_attribute'; - public static string $UPDATE_INTEGER_ATTRIBUTE = 'update_integer_attribute'; - public static string $UPDATE_FLOAT_ATTRIBUTE = 'update_float_attribute'; - public static string $UPDATE_BOOLEAN_ATTRIBUTE = 'update_boolean_attribute'; - public static string $UPDATE_URL_ATTRIBUTE = 'update_url_attribute'; - public static string $UPDATE_EMAIL_ATTRIBUTE = 'update_email_attribute'; - public static string $UPDATE_IP_ATTRIBUTE = 'update_ip_attribute'; - public static string $UPDATE_ENUM_ATTRIBUTE = 'update_enum_attribute'; - public static string $UPDATE_DATETIME_ATTRIBUTE = 'update_datetime_attribute'; + public static string $CREATE_RELATIONSHIP_COLUMN = 'create_relationship_column'; + public static string $UPDATE_STRING_COLUMN = 'update_string_column'; + public static string $UPDATE_INTEGER_COLUMN = 'update_integer_column'; + public static string $UPDATE_FLOAT_COLUMN = 'update_float_column'; + public static string $UPDATE_BOOLEAN_COLUMN = 'update_boolean_column'; + public static string $UPDATE_URL_COLUMN = 'update_url_column'; + public static string $UPDATE_EMAIL_COLUMN = 'update_email_column'; + public static string $UPDATE_IP_COLUMN = 'update_ip_column'; + public static string $UPDATE_ENUM_COLUMN = 'update_enum_column'; + public static string $UPDATE_DATETIME_COLUMN = 'update_datetime_column'; - public static string $UPDATE_RELATIONSHIP_ATTRIBUTE = 'update_relationship_attribute'; - public static string $GET_ATTRIBUTES = 'get_attributes'; - public static string $GET_ATTRIBUTE = 'get_attribute'; - public static string $DELETE_ATTRIBUTE = 'delete_attribute'; + public static string $UPDATE_RELATIONSHIP_COLUMN = 'update_relationship_column'; + public static string $GET_COLUMNS = 'get_columns'; + public static string $GET_COLUMN = 'get_column'; + public static string $DELETE_COLUMN = 'delete_column'; // Indexes public static string $CREATE_INDEX = 'create_index'; public static string $GET_INDEXES = 'get_indexes'; public static string $GET_INDEX = 'get_index'; public static string $DELETE_INDEX = 'delete_index'; // Documents - public static string $CREATE_DOCUMENT = 'create_document_rest'; - public static string $GET_DOCUMENTS = 'list_documents'; - public static string $GET_DOCUMENT = 'get_document'; - public static string $UPDATE_DOCUMENT = 'update_document'; - public static string $DELETE_DOCUMENT = 'delete_document'; + public static string $CREATE_ROW = 'create_row_rest'; + public static string $GET_ROWS = 'list_rows'; + public static string $GET_ROW = 'get_row'; + public static string $UPDATE_ROW = 'update_row'; + public static string $DELETE_ROW = 'delete_row'; // Custom Entities public static string $CREATE_CUSTOM_ENTITY = 'create_custom_entity'; @@ -258,7 +258,7 @@ trait Base public static string $COMPLEX_QUERY = 'complex_query'; // Fragments - public static string $FRAGMENT_ATTRIBUTES = ' + public static string $FRAGMENT_COLUMNS = ' fragment attributeProperties on Attributes { ... on AttributeString { key @@ -393,18 +393,18 @@ trait Base status } }'; - case self::$GET_COLLECTION: - return 'query getCollection($databaseId: String!, $collectionId: String!) { - databasesGetCollection(databaseId: $databaseId, collectionId: $collectionId) { + case self::$GET_TABLE: + return 'query getTable($databaseId: String!, $tableId: String!) { + databasesGetTable(databaseId: $databaseId, tableId: $tableId) { _id _permissions documentSecurity name } }'; - case self::$GET_COLLECTIONS: - return 'query listCollections($databaseId: String!) { - databasesListCollections(databaseId: $databaseId) { + case self::$GET_TABLES: + return 'query listTables($databaseId: String!) { + databasesListTables(databaseId: $databaseId) { total collections { _id @@ -414,42 +414,42 @@ trait Base } } }'; - case self::$CREATE_COLLECTION: - return 'mutation createCollection($databaseId: String!, $collectionId: String!, $name: String!, $documentSecurity: Boolean!, $permissions: [String!]!) { - databasesCreateCollection(databaseId: $databaseId, collectionId: $collectionId, name: $name, documentSecurity: $documentSecurity, permissions: $permissions) { + case self::$CREATE_TABLE: + return 'mutation createTable($databaseId: String!, $tableId: String!, $name: String!, $documentSecurity: Boolean!, $permissions: [String!]!) { + databasesCreateTable(databaseId: $databaseId, tableId: $tableId, name: $name, documentSecurity: $documentSecurity, permissions: $permissions) { _id _permissions documentSecurity name } }'; - case self::$UPDATE_COLLECTION: - return 'mutation updateCollection($databaseId: String!, $collectionId: String!, $name: String!, $documentSecurity: Boolean!, $permissions: [String!], $enabled: Boolean){ - databasesUpdateCollection(databaseId: $databaseId, collectionId: $collectionId, name: $name, documentSecurity: $documentSecurity, permissions: $permissions, enabled: $enabled) { + case self::$UPDATE_TABLE: + return 'mutation updateTable($databaseId: String!, $tableId: String!, $name: String!, $documentSecurity: Boolean!, $permissions: [String!], $enabled: Boolean){ + databasesUpdateTable(databaseId: $databaseId, tableId: $tableId, name: $name, documentSecurity: $documentSecurity, permissions: $permissions, enabled: $enabled) { _id _permissions documentSecurity name } }'; - case self::$DELETE_COLLECTION: - return 'mutation deleteCollection($databaseId: String!, $collectionId: String!){ - databasesDeleteCollection(databaseId: $databaseId, collectionId: $collectionId) { + case self::$DELETE_TABLE: + return 'mutation deleteTable($databaseId: String!, $tableId: String!){ + databasesDeleteTable(databaseId: $databaseId, tableId: $tableId) { status } }'; - case self::$CREATE_STRING_ATTRIBUTE: - return 'mutation createStringAttribute($databaseId: String!, $collectionId: String!, $key: String!, $size: Int!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, size: $size, required: $required, default: $default, array: $array) { + case self::$CREATE_STRING_COLUMN: + return 'mutation createStringColumn($databaseId: String!, $tableId: String!, $key: String!, $size: Int!, $required: Boolean!, $default: String, $array: Boolean){ + databasesCreateStringColumn(databaseId: $databaseId, tableId: $tableId, key: $key, size: $size, required: $required, default: $default, array: $array) { key required default array } }'; - case self::$CREATE_INTEGER_ATTRIBUTE: - return 'mutation createIntegerAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Int, $max: Int, $default: Int, $array: Boolean){ - databasesCreateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { + case self::$CREATE_INTEGER_COLUMN: + return 'mutation createIntegerColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $min: Int, $max: Int, $default: Int, $array: Boolean){ + databasesCreateIntegerColumn(databaseId: $databaseId, tableId: $tableId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { key required min @@ -458,9 +458,9 @@ trait Base array } }'; - case self::$CREATE_FLOAT_ATTRIBUTE: - return 'mutation createFloatAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Float, $max: Float, $default: Float, $array: Boolean){ - databasesCreateFloatAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { + case self::$CREATE_FLOAT_COLUMN: + return 'mutation createFloatColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $min: Float, $max: Float, $default: Float, $array: Boolean){ + databasesCreateFloatColumn(databaseId: $databaseId, tableId: $tableId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { key required min @@ -469,45 +469,45 @@ trait Base array } }'; - case self::$CREATE_BOOLEAN_ATTRIBUTE: - return 'mutation createBooleanAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: Boolean, $array: Boolean){ - databasesCreateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + case self::$CREATE_BOOLEAN_COLUMN: + return 'mutation createBooleanColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: Boolean, $array: Boolean){ + databasesCreateBooleanColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { key required default array } }'; - case self::$CREATE_URL_ATTRIBUTE: - return 'mutation createUrlAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateUrlAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + case self::$CREATE_URL_COLUMN: + return 'mutation createUrlColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ + databasesCreateUrlColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { key required default array } }'; - case self::$CREATE_EMAIL_ATTRIBUTE: - return 'mutation createEmailAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateEmailAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + case self::$CREATE_EMAIL_COLUMN: + return 'mutation createEmailColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ + databasesCreateEmailColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { key required default array } }'; - case self::$CREATE_IP_ATTRIBUTE: - return 'mutation createIpAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateIpAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + case self::$CREATE_IP_COLUMN: + return 'mutation createIpColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ + databasesCreateIpColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { key required default array } }'; - case self::$CREATE_ENUM_ATTRIBUTE: - return 'mutation createEnumAttribute($databaseId: String!, $collectionId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateEnumAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, elements: $elements, required: $required, default: $default, array: $array) { + case self::$CREATE_ENUM_COLUMN: + return 'mutation createEnumColumn($databaseId: String!, $tableId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String, $array: Boolean){ + databasesCreateEnumColumn(databaseId: $databaseId, tableId: $tableId, key: $key, elements: $elements, required: $required, default: $default, array: $array) { key elements required @@ -515,18 +515,18 @@ trait Base array } }'; - case self::$CREATE_DATETIME_ATTRIBUTE: - return 'mutation createDatetimeAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + case self::$CREATE_DATETIME_COLUMN: + return 'mutation createDatetimeColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ + databasesCreateDatetimeColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { key required default array } }'; - case self::$CREATE_RELATIONSHIP_ATTRIBUTE: - return 'mutation createRelationshipAttribute($databaseId: String!, $collectionId: String!, $relatedCollectionId: String!, $type: String!, $twoWay: Boolean, $key: String, $twoWayKey: String, $onDelete: String){ - databasesCreateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, relatedCollectionId: $relatedCollectionId, type: $type, twoWay: $twoWay, key: $key, twoWayKey: $twoWayKey, onDelete: $onDelete) { + case self::$CREATE_RELATIONSHIP_COLUMN: + return 'mutation createRelationshipColumn($databaseId: String!, $tableId: String!, $relatedTableId: String!, $type: String!, $twoWay: Boolean, $key: String, $twoWayKey: String, $onDelete: String){ + databasesCreateRelationshipColumn(databaseId: $databaseId, tableId: $tableId, relatedTableId: $relatedTableId, type: $type, twoWay: $twoWay, key: $key, twoWayKey: $twoWayKey, onDelete: $onDelete) { relatedCollection relationType twoWay @@ -535,77 +535,77 @@ trait Base onDelete } }'; - case self::$UPDATE_STRING_ATTRIBUTE: - return 'mutation updateStringAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + case self::$UPDATE_STRING_COLUMN: + return 'mutation updateStringColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ + databasesUpdateStringColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { required default } }'; - case self::$UPDATE_INTEGER_ATTRIBUTE: - return 'mutation updateIntegerAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Int!, $max: Int!, $default: Int){ - databasesUpdateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, min: $min, max: $max, default: $default) { + case self::$UPDATE_INTEGER_COLUMN: + return 'mutation updateIntegerColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $min: Int!, $max: Int!, $default: Int){ + databasesUpdateIntegerColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, min: $min, max: $max, default: $default) { required min max default } }'; - case self::$UPDATE_FLOAT_ATTRIBUTE: - return 'mutation updateFloatAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Float!, $max: Float!, $default: Float){ - databasesUpdateFloatAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default) { + case self::$UPDATE_FLOAT_COLUMN: + return 'mutation updateFloatColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $min: Float!, $max: Float!, $default: Float){ + databasesUpdateFloatColumn(databaseId: $databaseId, tableId: $tableId, key: $key, min: $min, max: $max, required: $required, default: $default) { required min max default } }'; - case self::$UPDATE_BOOLEAN_ATTRIBUTE: - return 'mutation updateBooleanAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: Boolean){ - databasesUpdateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + case self::$UPDATE_BOOLEAN_COLUMN: + return 'mutation updateBooleanColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: Boolean){ + databasesUpdateBooleanColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { required default } }'; - case self::$UPDATE_URL_ATTRIBUTE: - return 'mutation updateUrlAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateUrlAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + case self::$UPDATE_URL_COLUMN: + return 'mutation updateUrlColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ + databasesUpdateUrlColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { required default } }'; - case self::$UPDATE_EMAIL_ATTRIBUTE: - return 'mutation updateEmailAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateEmailAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + case self::$UPDATE_EMAIL_COLUMN: + return 'mutation updateEmailColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ + databasesUpdateEmailColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { required default } }'; - case self::$UPDATE_IP_ATTRIBUTE: - return 'mutation updateIpAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateIpAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + case self::$UPDATE_IP_COLUMN: + return 'mutation updateIpColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ + databasesUpdateIpColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { required default } }'; - case self::$UPDATE_ENUM_ATTRIBUTE: - return 'mutation updateEnumAttribute($databaseId: String!, $collectionId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String){ - databasesUpdateEnumAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, elements: $elements, required: $required, default: $default) { + case self::$UPDATE_ENUM_COLUMN: + return 'mutation updateEnumColumn($databaseId: String!, $tableId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String){ + databasesUpdateEnumColumn(databaseId: $databaseId, tableId: $tableId, key: $key, elements: $elements, required: $required, default: $default) { elements required default } }'; - case self::$UPDATE_DATETIME_ATTRIBUTE: - return 'mutation updateDatetimeAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + case self::$UPDATE_DATETIME_COLUMN: + return 'mutation updateDatetimeColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ + databasesUpdateDatetimeColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { required default } }'; - case self::$UPDATE_RELATIONSHIP_ATTRIBUTE: - return 'mutation updateRelationshipAttribute($databaseId: String!, $collectionId: String!, $key: String!, $onDelete: String){ - databasesUpdateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, onDelete: $onDelete) { + case self::$UPDATE_RELATIONSHIP_COLUMN: + return 'mutation updateRelationshipColumn($databaseId: String!, $tableId: String!, $key: String!, $onDelete: String){ + databasesUpdateRelationshipColumn(databaseId: $databaseId, tableId: $tableId, key: $key, onDelete: $onDelete) { relatedCollection relationType twoWay @@ -615,16 +615,16 @@ trait Base } }'; case self::$CREATE_INDEX: - return 'mutation createIndex($databaseId: String!, $collectionId: String!, $key: String!, $type: String!, $attributes: [String!]!, $orders: [String!]){ - databasesCreateIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key, type: $type, attributes: $attributes, orders: $orders) { + return 'mutation createIndex($databaseId: String!, $tableId: String!, $key: String!, $type: String!, $columns: [String!]!, $orders: [String!]){ + databasesCreateIndex(databaseId: $databaseId, tableId: $tableId, key: $key, type: $type, columns: $columns, orders: $orders) { key type status } }'; case self::$GET_INDEXES: - return 'query listIndexes($databaseId: String!, $collectionId: String!) { - databasesListIndexes(databaseId: $databaseId, collectionId: $collectionId) { + return 'query listIndexes($databaseId: String!, $tableId: String!) { + databasesListIndexes(databaseId: $databaseId, tableId: $tableId) { total indexes { key @@ -634,52 +634,52 @@ trait Base } }'; case self::$GET_INDEX: - return 'query getIndex($databaseId: String!, $collectionId: String!, $key: String!) { - databasesGetIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key) { + return 'query getIndex($databaseId: String!, $tableId: String!, $key: String!) { + databasesGetIndex(databaseId: $databaseId, tableId: $tableId, key: $key) { key type status } }'; case self::$DELETE_INDEX: - return 'mutation deleteIndex($databaseId: String!, $collectionId: String!, $key: String!) { - databasesDeleteIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key) { + return 'mutation deleteIndex($databaseId: String!, $tableId: String!, $key: String!) { + databasesDeleteIndex(databaseId: $databaseId, tableId: $tableId, key: $key) { status } }'; - case self::$GET_ATTRIBUTES: - return 'query listAttributes($databaseId: String!, $collectionId: String!) { - databasesListAttributes(databaseId: $databaseId, collectionId: $collectionId) { + case self::$GET_COLUMNS: + return 'query listColumns($databaseId: String!, $tableId: String!) { + databasesListColumns(databaseId: $databaseId, tableId: $tableId) { total attributes { ...attributeProperties } } - }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; - case self::$GET_ATTRIBUTE: - return 'query getAttribute($databaseId: String!, $collectionId: String!, $key: String!) { - databasesGetAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { + }' . PHP_EOL . self::$FRAGMENT_COLUMNS; + case self::$GET_COLUMN: + return 'query getColumn($databaseId: String!, $tableId: String!, $key: String!) { + databasesGetColumn(databaseId: $databaseId, tableId: $tableId, key: $key) { ...attributeProperties } - }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; - case self::$DELETE_ATTRIBUTE: - return 'mutation deleteAttribute($databaseId: String!, $collectionId: String!, $key: String!) { - databasesDeleteAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { + }' . PHP_EOL . self::$FRAGMENT_COLUMNS; + case self::$DELETE_COLUMN: + return 'mutation deleteColumn($databaseId: String!, $tableId: String!, $key: String!) { + databasesDeleteColumn(databaseId: $databaseId, tableId: $tableId, key: $key) { status } }'; - case self::$GET_DOCUMENT: - return 'query getDocument($databaseId: String!, $collectionId: String!, $documentId: String!) { - databasesGetDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { + case self::$GET_ROW: + return 'query getRow($databaseId: String!, $tableId: String!, $rowId: String!) { + databasesGetRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId) { _id _collectionId _permissions data } }'; - case self::$GET_DOCUMENTS: - return 'query listDocuments($databaseId: String!, $collectionId: String!){ - databasesListDocuments(databaseId: $databaseId, collectionId: $collectionId) { + case self::$GET_ROWS: + return 'query listRows($databaseId: String!, $tableId: String!){ + databasesListRows(databaseId: $databaseId, tableId: $tableId) { total documents { _id @@ -689,9 +689,9 @@ trait Base } } }'; - case self::$CREATE_DOCUMENT: - return 'mutation createDocument($databaseId: String!, $collectionId: String!, $documentId: String!, $data: Json!, $permissions: [String!]){ - databasesCreateDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { + case self::$CREATE_ROW: + return 'mutation createRow($databaseId: String!, $tableId: String!, $rowId: String!, $data: Json!, $permissions: [String!]){ + databasesCreateRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId, data: $data, permissions: $permissions) { _id _collectionId _permissions @@ -756,17 +756,17 @@ trait Base return 'mutation deleteCustomEntity($id: String!){ actorsDelete(id: $id) }'; - case self::$UPDATE_DOCUMENT: - return 'mutation updateDocument($databaseId: String!, $collectionId: String!, $documentId: String!, $data: Json!, $permissions: [String!]){ - databasesUpdateDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { + case self::$UPDATE_ROW: + return 'mutation updateRow($databaseId: String!, $tableId: String!, $rowId: String!, $data: Json!, $permissions: [String!]){ + databasesUpdateRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId, data: $data, permissions: $permissions) { _id _collectionId data } }'; - case self::$DELETE_DOCUMENT: - return 'mutation deleteDocument($databaseId: String!, $collectionId: String!, $documentId: String!){ - databasesDeleteDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { + case self::$DELETE_ROW: + return 'mutation deleteRow($databaseId: String!, $tableId: String!, $rowId: String!){ + databasesDeleteRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId) { status } }'; @@ -2246,12 +2246,12 @@ trait Base } }'; case self::$COMPLEX_QUERY: - return 'mutation complex($databaseId: String!, $databaseName: String!, $collectionId: String!, $collectionName: String!, $documentSecurity: Boolean!, $collectionPermissions: [String!]!) { + return 'mutation complex($databaseId: String!, $databaseName: String!, $tableId: String!, $collectionName: String!, $documentSecurity: Boolean!, $collectionPermissions: [String!]!) { databasesCreate(databaseId: $databaseId, name: $databaseName) { _id name } - databasesCreateCollection(databaseId: $databaseId, collectionId: $collectionId, name: $collectionName, documentSecurity: $documentSecurity, permissions: $collectionPermissions) { + databasesCreateTable(databaseId: $databaseId, tableId: $tableId, name: $collectionName, documentSecurity: $documentSecurity, permissions: $collectionPermissions) { _id _createdAt _updatedAt @@ -2268,7 +2268,7 @@ trait Base status } } - databasesCreateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "name", size: 255, required: true) { + databasesCreateStringColumn(databaseId: $databaseId, tableId: $tableId, key: "name", size: 255, required: true) { key type status @@ -2277,7 +2277,7 @@ trait Base default array } - databasesCreateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "age", min: 0, max: 150, required: true) { + databasesCreateIntegerColumn(databaseId: $databaseId, tableId: $tableId, key: "age", min: 0, max: 150, required: true) { key type status @@ -2287,7 +2287,7 @@ trait Base default array } - databasesCreateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "alive", required: false, default: true) { + databasesCreateBooleanColumn(databaseId: $databaseId, tableId: $tableId, key: "alive", required: false, default: true) { key type status @@ -2487,7 +2487,7 @@ trait Base data } } - }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; + }' . PHP_EOL . self::$FRAGMENT_COLUMNS; } throw new \InvalidArgumentException('Invalid query type'); diff --git a/tests/e2e/Services/GraphQL/DatabaseClientTest.php b/tests/e2e/Services/GraphQL/DatabaseClientTest.php index 3853a3fc17..327b68224b 100644 --- a/tests/e2e/Services/GraphQL/DatabaseClientTest.php +++ b/tests/e2e/Services/GraphQL/DatabaseClientTest.php @@ -48,7 +48,7 @@ class DatabaseClientTest extends Scope public function testCreateCollection($database): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_COLLECTION); + $query = $this->getQuery(self::$CREATE_TABLE); $gqlPayload = [ 'query' => $query, 'variables' => [ diff --git a/tests/e2e/Services/GraphQL/DatabaseServerTest.php b/tests/e2e/Services/GraphQL/DatabaseServerTest.php index 87006a1bea..0ea86c03cf 100644 --- a/tests/e2e/Services/GraphQL/DatabaseServerTest.php +++ b/tests/e2e/Services/GraphQL/DatabaseServerTest.php @@ -49,12 +49,12 @@ class DatabaseServerTest extends Scope public function testCreateCollection($database): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_COLLECTION); + $query = $this->getQuery(self::$CREATE_TABLE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $database['_id'], - 'collectionId' => 'actors', + 'tableId' => 'actors', 'name' => 'Actors', 'documentSecurity' => false, 'permissions' => [ @@ -73,14 +73,14 @@ class DatabaseServerTest extends Scope $this->assertIsArray($collection['body']['data']); $this->assertArrayNotHasKey('errors', $collection['body']); - $collection = $collection['body']['data']['databasesCreateCollection']; + $collection = $collection['body']['data']['databasesCreateTable']; $this->assertEquals('Actors', $collection['name']); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $database['_id'], - 'collectionId' => 'movies', + 'tableId' => 'movies', 'name' => 'Movies', 'documentSecurity' => false, 'permissions' => [ @@ -92,20 +92,20 @@ class DatabaseServerTest extends Scope ] ]; - $collection2 = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + $table2 = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), $gqlPayload); - $this->assertIsArray($collection2['body']['data']); - $this->assertArrayNotHasKey('errors', $collection2['body']); - $collection2 = $collection2['body']['data']['databasesCreateCollection']; - $this->assertEquals('Movies', $collection2['name']); + $this->assertIsArray($table2['body']['data']); + $this->assertArrayNotHasKey('errors', $table2['body']); + $table2 = $table2['body']['data']['databasesCreateTable']; + $this->assertEquals('Movies', $table2['name']); return [ 'database' => $database, - 'collection' => $collection, - 'collection2' => $collection2, + 'table' => $collection, + 'table2' => $table2, ]; } @@ -116,12 +116,12 @@ class DatabaseServerTest extends Scope public function testCreateStringAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_STRING_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'name', 'size' => 256, 'required' => true, @@ -135,7 +135,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateStringAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateStringColumn']); return $data; } @@ -150,12 +150,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_STRING_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_STRING_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'name', 'required' => false, 'default' => 'Default Value', @@ -168,9 +168,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateStringAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateStringAttribute']['required']); - $this->assertEquals('Default Value', $attribute['body']['data']['databasesUpdateStringAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateStringColumn']); + $this->assertFalse($attribute['body']['data']['databasesUpdateStringColumn']['required']); + $this->assertEquals('Default Value', $attribute['body']['data']['databasesUpdateStringColumn']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -183,12 +183,12 @@ class DatabaseServerTest extends Scope public function testCreateIntegerAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_INTEGER_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_INTEGER_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'age', 'min' => 18, 'max' => 150, @@ -203,7 +203,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateIntegerAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateIntegerColumn']); return $data; } @@ -218,12 +218,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_INTEGER_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_INTEGER_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'age', 'required' => false, 'min' => 12, @@ -238,11 +238,11 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateIntegerAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateIntegerAttribute']['required']); - $this->assertEquals(12, $attribute['body']['data']['databasesUpdateIntegerAttribute']['min']); - $this->assertEquals(160, $attribute['body']['data']['databasesUpdateIntegerAttribute']['max']); - $this->assertEquals(50, $attribute['body']['data']['databasesUpdateIntegerAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateIntegerColumn']); + $this->assertFalse($attribute['body']['data']['databasesUpdateIntegerColumn']['required']); + $this->assertEquals(12, $attribute['body']['data']['databasesUpdateIntegerColumn']['min']); + $this->assertEquals(160, $attribute['body']['data']['databasesUpdateIntegerColumn']['max']); + $this->assertEquals(50, $attribute['body']['data']['databasesUpdateIntegerColumn']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -255,12 +255,12 @@ class DatabaseServerTest extends Scope public function testCreateBooleanAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_BOOLEAN_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_BOOLEAN_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'alive', 'required' => true, ] @@ -273,7 +273,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateBooleanAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateBooleanColumn']); return $data; } @@ -288,12 +288,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_BOOLEAN_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_BOOLEAN_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'alive', 'required' => false, 'default' => true @@ -306,9 +306,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateBooleanAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateBooleanAttribute']['required']); - $this->assertTrue($attribute['body']['data']['databasesUpdateBooleanAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateBooleanColumn']); + $this->assertFalse($attribute['body']['data']['databasesUpdateBooleanColumn']['required']); + $this->assertTrue($attribute['body']['data']['databasesUpdateBooleanColumn']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -321,12 +321,12 @@ class DatabaseServerTest extends Scope public function testCreateFloatAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_FLOAT_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_FLOAT_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'salary', 'min' => 1000.0, 'max' => 999999.99, @@ -342,7 +342,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateFloatAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateFloatColumn']); return $data; } @@ -357,12 +357,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_FLOAT_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_FLOAT_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'salary', 'required' => false, 'min' => 100.0, @@ -377,11 +377,11 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateFloatAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateFloatAttribute']['required']); - $this->assertEquals(100.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['min']); - $this->assertEquals(1000000.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['max']); - $this->assertEquals(2500.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateFloatColumn']); + $this->assertFalse($attribute['body']['data']['databasesUpdateFloatColumn']['required']); + $this->assertEquals(100.0, $attribute['body']['data']['databasesUpdateFloatColumn']['min']); + $this->assertEquals(1000000.0, $attribute['body']['data']['databasesUpdateFloatColumn']['max']); + $this->assertEquals(2500.0, $attribute['body']['data']['databasesUpdateFloatColumn']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -394,12 +394,12 @@ class DatabaseServerTest extends Scope public function testCreateEmailAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_EMAIL_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_EMAIL_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'email', 'required' => true, ] @@ -412,7 +412,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateEmailAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateEmailColumn']); return $data; } @@ -427,12 +427,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_EMAIL_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_EMAIL_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'email', 'required' => false, 'default' => 'torsten@appwrite.io', @@ -445,9 +445,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateEmailAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateEmailAttribute']['required']); - $this->assertEquals('torsten@appwrite.io', $attribute['body']['data']['databasesUpdateEmailAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateEmailColumn']); + $this->assertFalse($attribute['body']['data']['databasesUpdateEmailColumn']['required']); + $this->assertEquals('torsten@appwrite.io', $attribute['body']['data']['databasesUpdateEmailColumn']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -460,12 +460,12 @@ class DatabaseServerTest extends Scope public function testCreateEnumAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_ENUM_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_ENUM_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'role', 'elements' => [ 'crew', @@ -483,7 +483,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateEnumAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateEnumColumn']); return $data; } @@ -499,12 +499,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_ENUM_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_ENUM_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'role', 'required' => false, 'elements' => [ @@ -522,11 +522,11 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateEnumAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateEnumAttribute']['required']); - $this->assertEquals('tech', $attribute['body']['data']['databasesUpdateEnumAttribute']['default']); - $this->assertContains('tech', $attribute['body']['data']['databasesUpdateEnumAttribute']['elements']); - $this->assertNotContains('guest', $attribute['body']['data']['databasesUpdateEnumAttribute']['elements']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateEnumColumn']); + $this->assertFalse($attribute['body']['data']['databasesUpdateEnumColumn']['required']); + $this->assertEquals('tech', $attribute['body']['data']['databasesUpdateEnumColumn']['default']); + $this->assertContains('tech', $attribute['body']['data']['databasesUpdateEnumColumn']['elements']); + $this->assertNotContains('guest', $attribute['body']['data']['databasesUpdateEnumColumn']['elements']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -539,12 +539,12 @@ class DatabaseServerTest extends Scope public function testCreateDatetimeAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_DATETIME_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_DATETIME_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'dob', 'required' => true, ] @@ -557,7 +557,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateDatetimeAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateDatetimeColumn']); return $data; } @@ -572,12 +572,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_DATETIME_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_DATETIME_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'dob', 'required' => false, 'default' => '2000-01-01T00:00:00Z' @@ -590,9 +590,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateDatetimeAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateDatetimeAttribute']['required']); - $this->assertEquals('2000-01-01T00:00:00Z', $attribute['body']['data']['databasesUpdateDatetimeAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateDatetimeColumn']); + $this->assertFalse($attribute['body']['data']['databasesUpdateDatetimeColumn']['required']); + $this->assertEquals('2000-01-01T00:00:00Z', $attribute['body']['data']['databasesUpdateDatetimeColumn']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -604,13 +604,13 @@ class DatabaseServerTest extends Scope public function testCreateRelationshipAttribute(array $data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_RELATIONSHIP_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_RELATIONSHIP_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection2']['_id'], // Movies - 'relatedCollectionId' => $data['collection']['_id'], // Actors + 'tableId' => $data['table2']['_id'], // Movies + 'relatedTableId' => $data['table']['_id'], // Actors 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => true, 'key' => 'actors', @@ -623,9 +623,10 @@ class DatabaseServerTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), $gqlPayload); + $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateRelationshipAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateRelationshipColumn']); return $data; } @@ -638,12 +639,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_RELATIONSHIP_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_RELATIONSHIP_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection2']['_id'], + 'tableId' => $data['table2']['_id'], 'key' => 'actors', 'onDelete' => Database::RELATION_MUTATE_CASCADE, ] @@ -656,7 +657,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateRelationshipAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateRelationshipColumn']); return $data; } @@ -668,12 +669,12 @@ class DatabaseServerTest extends Scope public function testCreateIPAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_IP_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_IP_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'ip', 'required' => false, 'default' => '::1', @@ -687,7 +688,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateIpAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateIpColumn']); return $data; } @@ -702,12 +703,12 @@ class DatabaseServerTest extends Scope sleep(3); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_IP_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_IP_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'ip', 'required' => false, 'default' => '127.0.0.1' @@ -720,9 +721,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateIpAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateIpAttribute']['required']); - $this->assertEquals('127.0.0.1', $attribute['body']['data']['databasesUpdateIpAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateIpColumn']); + $this->assertFalse($attribute['body']['data']['databasesUpdateIpColumn']['required']); + $this->assertEquals('127.0.0.1', $attribute['body']['data']['databasesUpdateIpColumn']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -735,12 +736,12 @@ class DatabaseServerTest extends Scope public function testCreateURLAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_URL_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_URL_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'url', 'required' => false, 'default' => 'https://appwrite.io', @@ -754,7 +755,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateUrlAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateUrlColumn']); return $data; } @@ -769,12 +770,12 @@ class DatabaseServerTest extends Scope sleep(3); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_URL_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_URL_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'url', 'required' => false, 'default' => 'https://cloud.appwrite.io' @@ -787,9 +788,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateUrlAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateUrlAttribute']['required']); - $this->assertEquals('https://cloud.appwrite.io', $attribute['body']['data']['databasesUpdateUrlAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateUrlColumn']); + $this->assertFalse($attribute['body']['data']['databasesUpdateUrlColumn']['required']); + $this->assertEquals('https://cloud.appwrite.io', $attribute['body']['data']['databasesUpdateUrlColumn']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); } @@ -806,10 +807,10 @@ class DatabaseServerTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'index', 'type' => 'key', - 'attributes' => [ + 'columns' => [ 'name', 'age', ], @@ -827,7 +828,7 @@ class DatabaseServerTest extends Scope return [ 'database' => $data['database'], - 'collection' => $data['collection'], + 'table' => $data['table'], 'index' => $index['body']['data']['databasesCreateIndex'], ]; } @@ -842,13 +843,13 @@ class DatabaseServerTest extends Scope public function testCreateDocument($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_DOCUMENT); + $query = $this->getQuery(self::$CREATE_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], - 'documentId' => ID::unique(), + 'tableId' => $data['table']['_id'], + 'rowId' => ID::unique(), 'data' => [ 'name' => 'John Doe', 'email' => 'example@appwrite.io', @@ -866,21 +867,21 @@ class DatabaseServerTest extends Scope ] ]; - $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + $row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), $gqlPayload); - $this->assertArrayNotHasKey('errors', $document['body']); - $this->assertIsArray($document['body']['data']); + $this->assertArrayNotHasKey('errors', $row['body']); + $this->assertIsArray($row['body']['data']); - $document = $document['body']['data']['databasesCreateDocument']; - $this->assertIsArray($document); + $row = $row['body']['data']['databasesCreateRow']; + $this->assertIsArray($row); return [ 'database' => $data['database'], - 'collection' => $data['collection'], - 'document' => $document, + 'table' => $data['table'], + 'row' => $row, ]; } @@ -974,7 +975,7 @@ class DatabaseServerTest extends Scope public function testGetCollections($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_COLLECTIONS); + $query = $this->getQuery(self::$GET_TABLES); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -989,7 +990,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $collections['body']); $this->assertIsArray($collections['body']['data']); - $this->assertIsArray($collections['body']['data']['databasesListCollections']); + $this->assertIsArray($collections['body']['data']['databasesListTables']); } /** @@ -999,12 +1000,12 @@ class DatabaseServerTest extends Scope public function testGetCollection($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_COLLECTION); + $query = $this->getQuery(self::$GET_TABLE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], ] ]; @@ -1015,7 +1016,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $collection['body']); $this->assertIsArray($collection['body']['data']); - $this->assertIsArray($collection['body']['data']['databasesGetCollection']); + $this->assertIsArray($collection['body']['data']['databasesGetTable']); } /** @@ -1026,12 +1027,12 @@ class DatabaseServerTest extends Scope public function testGetAttributes($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_ATTRIBUTES); + $query = $this->getQuery(self::$GET_COLUMNS); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], ] ]; @@ -1042,7 +1043,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attributes['body']); $this->assertIsArray($attributes['body']['data']); - $this->assertIsArray($attributes['body']['data']['databasesListAttributes']); + $this->assertIsArray($attributes['body']['data']['databasesListColumns']); } /** @@ -1052,12 +1053,12 @@ class DatabaseServerTest extends Scope public function testGetAttribute($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_ATTRIBUTE); + $query = $this->getQuery(self::$GET_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'name', ] ]; @@ -1069,7 +1070,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesGetAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesGetColumn']); } /** @@ -1084,7 +1085,7 @@ class DatabaseServerTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], ] ]; @@ -1110,7 +1111,7 @@ class DatabaseServerTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => $data['index']['key'], ] ]; @@ -1132,12 +1133,12 @@ class DatabaseServerTest extends Scope public function testGetDocuments($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_DOCUMENTS); + $query = $this->getQuery(self::$GET_ROWS); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], ] ]; @@ -1148,7 +1149,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $documents['body']); $this->assertIsArray($documents['body']['data']); - $this->assertIsArray($documents['body']['data']['databasesListDocuments']); + $this->assertIsArray($documents['body']['data']['databasesListRows']); } /** @@ -1158,13 +1159,13 @@ class DatabaseServerTest extends Scope public function testGetDocument($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_DOCUMENT); + $query = $this->getQuery(self::$GET_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], - 'documentId' => $data['document']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => $data['row']['_id'], ] ]; @@ -1175,7 +1176,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $this->assertIsArray($document['body']['data']['databasesGetDocument']); + $this->assertIsArray($document['body']['data']['databasesGetRow']); } // /** @@ -1258,12 +1259,12 @@ class DatabaseServerTest extends Scope public function testUpdateCollection($data) { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_COLLECTION); + $query = $this->getQuery(self::$UPDATE_TABLE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'name' => 'New Collection Name', 'documentSecurity' => false, ] @@ -1276,7 +1277,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $collection['body']); $this->assertIsArray($collection['body']['data']); - $this->assertIsArray($collection['body']['data']['databasesUpdateCollection']); + $this->assertIsArray($collection['body']['data']['databasesUpdateTable']); } /** @@ -1286,13 +1287,13 @@ class DatabaseServerTest extends Scope public function testUpdateDocument($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_DOCUMENT); + $query = $this->getQuery(self::$UPDATE_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], - 'documentId' => $data['document']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => $data['row']['_id'], 'data' => [ 'name' => 'New Document Name', ], @@ -1306,7 +1307,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['databasesUpdateDocument']; + $document = $document['body']['data']['databasesUpdateRow']; $this->assertIsArray($document); $this->assertStringContainsString('New Document Name', $document['data']); } @@ -1346,13 +1347,13 @@ class DatabaseServerTest extends Scope public function testDeleteDocument($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$DELETE_DOCUMENT); + $query = $this->getQuery(self::$DELETE_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], - 'documentId' => $data['document']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => $data['row']['_id'], ] ]; @@ -1396,12 +1397,12 @@ class DatabaseServerTest extends Scope public function testDeleteAttribute($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$DELETE_ATTRIBUTE); + $query = $this->getQuery(self::$DELETE_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'name', ] ]; @@ -1422,12 +1423,12 @@ class DatabaseServerTest extends Scope public function testDeleteCollection($data) { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$DELETE_COLLECTION); + $query = $this->getQuery(self::$DELETE_TABLE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], ] ]; From 9bf1fdc2ff386ecb301551f993d62989b4840287 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 27 Apr 2025 14:27:07 +0530 Subject: [PATCH 025/343] fix: graphql tests. --- tests/e2e/Services/GraphQL/AuthTest.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/e2e/Services/GraphQL/AuthTest.php b/tests/e2e/Services/GraphQL/AuthTest.php index d8bd0d6326..48a2f475e6 100644 --- a/tests/e2e/Services/GraphQL/AuthTest.php +++ b/tests/e2e/Services/GraphQL/AuthTest.php @@ -107,7 +107,7 @@ class AuthTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Actors', 'documentSecurity' => true, 'permissions' => [ @@ -127,7 +127,7 @@ class AuthTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'collectionId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], 'key' => 'name', 'size' => 256, 'required' => true, @@ -153,8 +153,8 @@ class AuthTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'collectionId' => $this->table['body']['data']['databasesCreateTable']['_id'], - 'documentId' => ID::unique(), + 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'rowId' => ID::unique(), 'data' => [ 'name' => 'John Doe', ], @@ -178,8 +178,8 @@ class AuthTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'collectionId' => $this->table['body']['data']['databasesCreateTable']['_id'], - 'documentId' => $row['body']['data']['databasesCreateRow']['_id'], + 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'rowId' => $row['body']['data']['databasesCreateRow']['_id'], ] ]; $row = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -213,8 +213,8 @@ class AuthTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'collectionId' => $this->table['body']['data']['databasesCreateTable']['_id'], - 'documentId' => ID::unique(), + 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'rowId' => ID::unique(), 'data' => [ 'name' => 'John Doe', ], @@ -237,8 +237,8 @@ class AuthTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'collectionId' => $this->table['body']['data']['databasesCreateTable']['_id'], - 'documentId' => $row['body']['data']['databasesCreateRow']['_id'], + 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'rowId' => $row['body']['data']['databasesCreateRow']['_id'], ] ]; $row = $this->client->call(Client::METHOD_POST, '/graphql', [ From 7ffd5cfde6c92e00cd4bf8cac0b19860aaebeefc Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 27 Apr 2025 14:47:59 +0530 Subject: [PATCH 026/343] fix: graphql tests, again. --- .../Services/GraphQL/DatabaseClientTest.php | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/tests/e2e/Services/GraphQL/DatabaseClientTest.php b/tests/e2e/Services/GraphQL/DatabaseClientTest.php index 327b68224b..efd2430629 100644 --- a/tests/e2e/Services/GraphQL/DatabaseClientTest.php +++ b/tests/e2e/Services/GraphQL/DatabaseClientTest.php @@ -53,7 +53,7 @@ class DatabaseClientTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $database['_id'], - 'collectionId' => 'actors', + 'tableId' => 'actors', 'name' => 'Actors', 'documentSecurity' => false, 'permissions' => [ @@ -65,20 +65,20 @@ class DatabaseClientTest extends Scope ] ]; - $collection = $this->client->call(Client::METHOD_POST, '/graphql', [ + $table = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $this->getProject()['apiKey'], ], $gqlPayload); - $this->assertIsArray($collection['body']['data']); - $this->assertArrayNotHasKey('errors', $collection['body']); - $collection = $collection['body']['data']['databasesCreateCollection']; - $this->assertEquals('Actors', $collection['name']); + $this->assertIsArray($table['body']['data']); + $this->assertArrayNotHasKey('errors', $table['body']); + $table = $table['body']['data']['databasesCreateTable']; + $this->assertEquals('Actors', $table['name']); return [ 'database' => $database, - 'collection' => $collection, + 'table' => $table, ]; } @@ -88,12 +88,12 @@ class DatabaseClientTest extends Scope public function testCreateStringAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_STRING_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'name', 'size' => 256, 'required' => true, @@ -108,7 +108,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateStringAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateStringColumn']); return $data; } @@ -119,12 +119,12 @@ class DatabaseClientTest extends Scope public function testCreateIntegerAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_INTEGER_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_INTEGER_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], 'key' => 'age', 'min' => 18, 'max' => 150, @@ -140,7 +140,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateIntegerAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateIntegerColumn']); return $data; } @@ -154,13 +154,13 @@ class DatabaseClientTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_DOCUMENT); + $query = $this->getQuery(self::$CREATE_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], - 'documentId' => ID::unique(), + 'tableId' => $data['table']['_id'], + 'rowId' => ID::unique(), 'data' => [ 'name' => 'John Doe', 'age' => 35, @@ -181,13 +181,13 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['databasesCreateDocument']; + $document = $document['body']['data']['databasesCreateRow']; $this->assertIsArray($document); return [ 'database' => $data['database'], - 'collection' => $data['collection'], - 'document' => $document, + 'table' => $data['table'], + 'row' => $document, ]; } @@ -198,12 +198,12 @@ class DatabaseClientTest extends Scope public function testGetDocuments($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_DOCUMENTS); + $query = $this->getQuery(self::$GET_ROWS); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], + 'tableId' => $data['table']['_id'], ] ]; @@ -214,7 +214,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $documents['body']); $this->assertIsArray($documents['body']['data']); - $this->assertIsArray($documents['body']['data']['databasesListDocuments']); + $this->assertIsArray($documents['body']['data']['databasesListRows']); } /** @@ -224,13 +224,13 @@ class DatabaseClientTest extends Scope public function testGetDocument($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_DOCUMENT); + $query = $this->getQuery(self::$GET_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], - 'documentId' => $data['document']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => $data['row']['_id'], ] ]; @@ -241,7 +241,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $this->assertIsArray($document['body']['data']['databasesGetDocument']); + $this->assertIsArray($document['body']['data']['databasesGetRow']); } /** @@ -251,13 +251,13 @@ class DatabaseClientTest extends Scope public function testUpdateDocument($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_DOCUMENT); + $query = $this->getQuery(self::$UPDATE_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], - 'documentId' => $data['document']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => $data['row']['_id'], 'data' => [ 'name' => 'New Document Name', ], @@ -271,7 +271,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['databasesUpdateDocument']; + $document = $document['body']['data']['databasesUpdateRow']; $this->assertIsArray($document); $this->assertStringContainsString('New Document Name', $document['data']); @@ -284,13 +284,13 @@ class DatabaseClientTest extends Scope public function testDeleteDocument($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$DELETE_DOCUMENT); + $query = $this->getQuery(self::$DELETE_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'collectionId' => $data['collection']['_id'], - 'documentId' => $data['document']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => $data['row']['_id'], ] ]; From b3b99618603ba4aca2e6dc1b72ca4e1184e83416 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 13:22:26 +0530 Subject: [PATCH 027/343] init: move to module structure for database; start with columns. --- app/controllers/api/databases.php | 1956 +---------------- .../Modules/Databases/Http/Columns/Action.php | 417 ++++ .../Databases/Http/Columns/Boolean/Create.php | 84 + .../Databases/Http/Columns/Boolean/Update.php | 86 + .../Http/Columns/Datetime/Create.php | 106 + .../Http/Columns/Datetime/Update.php | 97 + .../Modules/Databases/Http/Columns/Delete.php | 164 ++ .../Databases/Http/Columns/Email/Create.php | 104 + .../Databases/Http/Columns/Email/Update.php | 98 + .../Databases/Http/Columns/Enum/Create.php | 113 + .../Databases/Http/Columns/Enum/Update.php | 102 + .../Databases/Http/Columns/Float/Create.php | 123 ++ .../Databases/Http/Columns/Float/Update.php | 109 + .../Modules/Databases/Http/Columns/Get.php | 112 + .../Databases/Http/Columns/IP/Create.php | 96 + .../Databases/Http/Columns/IP/Update.php | 98 + .../Databases/Http/Columns/Integer/Create.php | 123 ++ .../Databases/Http/Columns/Integer/Update.php | 109 + .../Http/Columns/Relationship/Create.php | 168 ++ .../Http/Columns/Relationship/Update.php | 103 + .../Databases/Http/Columns/String/Create.php | 122 + .../Databases/Http/Columns/String/Update.php | 101 + .../Databases/Http/Columns/URL/Create.php | 96 + .../Databases/Http/Columns/URL/Update.php | 98 + .../Modules/Databases/Http/Columns/XList.php | 125 ++ .../Platform/Modules/Databases/Module.php | 16 + .../Modules/Databases/Services/Http.php | 110 + .../Modules/Databases/Services/Workers.php | 15 + .../Databases}/Workers/Databases.php | 2 +- src/Appwrite/Platform/Services/Workers.php | 2 - 30 files changed, 3125 insertions(+), 1930 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Module.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Services/Http.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Services/Workers.php rename src/Appwrite/Platform/{ => Modules/Databases}/Workers/Databases.php (99%) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index d8556dd4fe..33b839fc41 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -6,13 +6,11 @@ use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; -use Appwrite\Network\Validator\Email; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; -use Appwrite\Utopia\Database\Validator\Queries\Attributes; use Appwrite\Utopia\Database\Validator\Queries\Collections; use Appwrite\Utopia\Database\Validator\Queries\Databases; use Appwrite\Utopia\Database\Validator\Queries\Indexes; @@ -26,425 +24,32 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Authorization as AuthorizationException; -use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Duplicate as DuplicateException; -use Utopia\Database\Exception\Index as IndexException; use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Exception\Order as OrderException; use Utopia\Database\Exception\Query as QueryException; -use Utopia\Database\Exception\Restricted as RestrictedException; use Utopia\Database\Exception\Structure as StructureException; -use Utopia\Database\Exception\Truncate as TruncateException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Index as IndexValidator; -use Utopia\Database\Validator\IndexDependency as IndexDependencyValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; -use Utopia\Database\Validator\Structure; use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; -use Utopia\Validator\FloatValidator; -use Utopia\Validator\Integer; -use Utopia\Validator\IP; use Utopia\Validator\JSON; -use Utopia\Validator\Nullable; -use Utopia\Validator\Range; use Utopia\Validator\Text; -use Utopia\Validator\URL; use Utopia\Validator\WhiteList; -/** - * * Create column of varying type - * - * @param string $databaseId - * @param string $tableId - * @param Document $column - * @param Response $response - * @param Database $dbForProject - * @param EventDatabase $queueForDatabase - * @param Event $queueForEvents - * @return Document Newly created attribute document - * @throws AuthorizationException - * @throws Exception - * @throws LimitException - * @throws RestrictedException - * @throws StructureException - * @throws \Utopia\Database\Exception - * @throws ConflictException - * @throws Exception - */ -function createColumn(string $databaseId, string $tableId, Document $column, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): Document -{ - $key = $column->getAttribute('key'); - $type = $column->getAttribute('type', ''); - $size = $column->getAttribute('size', 0); - $required = $column->getAttribute('required', true); - $signed = $column->getAttribute('signed', true); // integers are signed by default - $array = $column->getAttribute('array', false); - $format = $column->getAttribute('format', ''); - $formatOptions = $column->getAttribute('formatOptions', []); - $filters = $column->getAttribute('filters', []); // filters are hidden from the endpoint - $default = $column->getAttribute('default'); - $options = $column->getAttribute('options', []); - - $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($db->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - if (!empty($format)) { - if (!Structure::hasFormat($format, $type)) { - throw new Exception(Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, "Format {$format} not available for {$type} columns."); - } - } - - // Must throw here since dbForProject->createAttribute is performed by db worker - if ($required && isset($default)) { - throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for required column'); - } - - if ($array && isset($default)) { - throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array columns'); - } - - if ($type === Database::VAR_RELATIONSHIP) { - $options['side'] = Database::RELATION_SIDE_PARENT; - $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection'] ?? ''); - if ($relatedTable->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND, 'The related table was not found.'); - } - } - - try { - $column = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $table->getInternalId() . '_' . $key), - 'key' => $key, - 'databaseInternalId' => $db->getInternalId(), - 'databaseId' => $db->getId(), - 'collectionInternalId' => $table->getInternalId(), - 'collectionId' => $tableId, - 'type' => $type, - 'status' => 'processing', // processing, available, failed, deleting, stuck - 'size' => $size, - 'required' => $required, - 'signed' => $signed, - 'default' => $default, - 'array' => $array, - 'format' => $format, - 'formatOptions' => $formatOptions, - 'filters' => $filters, - 'options' => $options, - ]); - - $dbForProject->checkAttribute($table, $column); - $column = $dbForProject->createDocument('attributes', $column); - } catch (DuplicateException) { - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); - } catch (LimitException) { - throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); - } catch (\Throwable $e) { - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $table->getInternalId()); - throw $e; - } - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $table->getInternalId()); - - if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { - $twoWayKey = $options['twoWayKey']; - $options['relatedCollection'] = $table->getId(); - $options['twoWayKey'] = $key; - $options['side'] = Database::RELATION_SIDE_CHILD; - - try { - $twoWayAttribute = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $twoWayKey), - 'key' => $twoWayKey, - 'databaseInternalId' => $db->getInternalId(), - 'databaseId' => $db->getId(), - 'collectionInternalId' => $relatedTable->getInternalId(), - 'collectionId' => $relatedTable->getId(), - 'type' => $type, - 'status' => 'processing', // processing, available, failed, deleting, stuck - 'size' => $size, - 'required' => $required, - 'signed' => $signed, - 'default' => $default, - 'array' => $array, - 'format' => $format, - 'formatOptions' => $formatOptions, - 'filters' => $filters, - 'options' => $options, - ]); - - $dbForProject->checkAttribute($relatedTable, $twoWayAttribute); - $dbForProject->createDocument('attributes', $twoWayAttribute); - } catch (DuplicateException) { - $dbForProject->deleteDocument('attributes', $column->getId()); - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); - } catch (LimitException) { - $dbForProject->deleteDocument('attributes', $column->getId()); - throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); - } catch (\Throwable $e) { - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); - throw $e; - } - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); - } - - $queueForDatabase - ->setType(DATABASE_TYPE_CREATE_ATTRIBUTE) - ->setDatabase($db) - ->setTable($table) - ->setRow($column); - - $queueForEvents - ->setContext('table', $table) - ->setContext('database', $db) - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('columnId', $column->getId()); - - $response->setStatusCode(Response::STATUS_CODE_CREATED); - - return $column; -} - -function updateColumn( - string $databaseId, - string $tableId, - string $key, - Database $dbForProject, - Event $queueForEvents, - string $type, - int $size = null, - string $filter = null, - string|bool|int|float $default = null, - bool $required = null, - int|float|null $min = null, - int|float|null $max = null, - array $elements = null, - array $options = [], - string $newKey = null, -): Document { - $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($db->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $column = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); - - if ($column->isEmpty()) { - throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); - } - - if ($column->getAttribute('status') !== 'available') { - throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE); - } - - if ($column->getAttribute(('type') !== $type)) { - throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID); - } - - if ($column->getAttribute('type') === Database::VAR_STRING && $column->getAttribute(('filter') !== $filter)) { - throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID); - } - - if ($required && isset($default)) { - throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for required column'); - } - - if ($column->getAttribute('array', false) && isset($default)) { - throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array columns'); - } - - $tableId = 'database_' . $db->getInternalId() . '_collection_' . $table->getInternalId(); - - $column - ->setAttribute('default', $default) - ->setAttribute('required', $required); - - if (!empty($size)) { - $column->setAttribute('size', $size); - } - - switch ($column->getAttribute('format')) { - case APP_DATABASE_ATTRIBUTE_INT_RANGE: - case APP_DATABASE_ATTRIBUTE_FLOAT_RANGE: - $min ??= $column->getAttribute('formatOptions')['min']; - $max ??= $column->getAttribute('formatOptions')['max']; - - if ($min > $max) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); - } - - if ($column->getAttribute('format') === APP_DATABASE_ATTRIBUTE_INT_RANGE) { - $validator = new Range($min, $max, Database::VAR_INTEGER); - } else { - $validator = new Range($min, $max, Database::VAR_FLOAT); - - if (!is_null($default)) { - $default = \floatval($default); - } - } - - if (!is_null($default) && !$validator->isValid($default)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); - } - - $options = [ - 'min' => $min, - 'max' => $max - ]; - $column->setAttribute('formatOptions', $options); - - break; - case APP_DATABASE_ATTRIBUTE_ENUM: - if (empty($elements)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Enum elements must not be empty'); - } - - foreach ($elements as $element) { - if (\strlen($element) === 0) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Each enum element must not be empty'); - } - } - - if (!is_null($default) && !in_array($default, $elements)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements'); - } - - $options = [ - 'elements' => $elements - ]; - - $column->setAttribute('formatOptions', $options); - - break; - } - - if ($type === Database::VAR_RELATIONSHIP) { - $primaryRowOptions = \array_merge($column->getAttribute('options', []), $options); - $column->setAttribute('options', $primaryRowOptions); - try { - $dbForProject->updateRelationship( - collection: $tableId, - id: $key, - newKey: $newKey, - onDelete: $primaryRowOptions['onDelete'], - ); - } catch (NotFoundException) { - throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); - } - - if ($primaryRowOptions['twoWay']) { - $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $primaryRowOptions['relatedCollection']); - - $relatedColumn = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $primaryRowOptions['twoWayKey']); - - if (!empty($newKey) && $newKey !== $key) { - $options['twoWayKey'] = $newKey; - } - - $relatedOptions = \array_merge($relatedColumn->getAttribute('options'), $options); - $relatedColumn->setAttribute('options', $relatedOptions); - $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $primaryRowOptions['twoWayKey'], $relatedColumn); - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); - } - } else { - try { - $dbForProject->updateAttribute( - collection: $tableId, - id: $key, - size: $size, - required: $required, - default: $default, - formatOptions: $options, - newKey: $newKey ?? null - ); - } catch (TruncateException) { - throw new Exception(Exception::ATTRIBUTE_INVALID_RESIZE); - } catch (NotFoundException) { - throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); - } catch (LimitException) { - throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); - } catch (IndexException $e) { - throw new Exception(Exception::INDEX_INVALID, $e->getMessage()); - } - } - - if (!empty($newKey) && $key !== $newKey) { - $originalUid = $column->getId(); - - $column - ->setAttribute('$id', ID::custom($db->getInternalId() . '_' . $table->getInternalId() . '_' . $newKey)) - ->setAttribute('key', $newKey); - - $dbForProject->updateDocument('attributes', $originalUid, $column); - - /** - * @var Document $index - */ - foreach ($table->getAttribute('indexes') as $index) { - /** - * @var string[] $columns - */ - $columns = $index->getAttribute('attributes', []); - $found = \array_search($key, $columns); - - if ($found !== false) { - $columns[$found] = $newKey; - $index->setAttribute('attributes', $columns); - $dbForProject->updateDocument('indexes', $index->getId(), $index); - } - } - } else { - $column = $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key, $column); - } - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $table->getId()); - - $queueForEvents - ->setContext('table', $table) - ->setContext('database', $db) - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('columnId', $column->getId()); - - return $column; -} - App::init() ->groups(['api', 'database']) ->inject('request') @@ -1209,11 +814,11 @@ App::put('/v1/databases/:databaseId/tables/:tableId') 'database_' . $database->getInternalId(), $tableId, $table - ->setAttribute('name', $name) - ->setAttribute('$permissions', $permissions) - ->setAttribute('documentSecurity', $documentSecurity) - ->setAttribute('enabled', $enabled) - ->setAttribute('search', \implode(' ', [$tableId, $name])) + ->setAttribute('name', $name) + ->setAttribute('$permissions', $permissions) + ->setAttribute('documentSecurity', $documentSecurity) + ->setAttribute('enabled', $enabled) + ->setAttribute('search', \implode(' ', [$tableId, $name])) ); $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $permissions, $documentSecurity); @@ -1290,1509 +895,6 @@ App::delete('/v1/databases/:databaseId/tables/:tableId') $response->noContent(); }); -App::post('/v1/databases/:databaseId/tables/:tableId/columns/string') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/string') - ->desc('Create string column') - ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'column.create') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'createStringColumn', - description: '/docs/references/databases/create-string-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_ACCEPTED, - model: Response::MODEL_ATTRIBUTE_STRING - ) - ] - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('size', null, new Range(1, APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH, Range::TYPE_INTEGER), 'Attribute size for text attributes, in number of characters.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, new Text(0, 0), 'Default value for column when not provided. Cannot be set when column is required.', true) - ->param('array', false, new Boolean(), 'Is column an array?', true) - ->param('encrypt', false, new Boolean(), 'Toggle encryption for the column. Encryption enhances security by not storing any plain text values in the database. However, encrypted columns cannot be queried.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - - // Ensure attribute default is within required size - $validator = new Text($size, 0); - if (!is_null($default) && !$validator->isValid($default)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); - } - - $filters = []; - - if ($encrypt) { - $filters[] = 'encrypt'; - } - - $column = createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_STRING, - 'size' => $size, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'filters' => $filters, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($column, Response::MODEL_ATTRIBUTE_STRING); - }); - -App::post('/v1/databases/:databaseId/tables/:tableId/columns/email') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/email') - ->desc('Create email column') - ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'column.create') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'createEmailColumn', - description: '/docs/references/databases/create-email-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_ACCEPTED, - model: Response::MODEL_ATTRIBUTE_EMAIL, - ) - ] - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, new Email(), 'Default value for column when not provided. Cannot be set when column is required.', true) - ->param('array', false, new Boolean(), 'Is column an array?', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - - $column = createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_STRING, - 'size' => 254, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'format' => APP_DATABASE_ATTRIBUTE_EMAIL, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($column, Response::MODEL_ATTRIBUTE_EMAIL); - }); - -App::post('/v1/databases/:databaseId/collections/:tableId/attributes/enum') - ->alias('/v1/database/collections/:tableId/attributes/enum') - ->desc('Create enum column') - ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'column.create') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'createEnumColumn', - description: '/docs/references/databases/create-attribute-enum.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_ACCEPTED, - model: Response::MODEL_ATTRIBUTE_ENUM, - ) - ] - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('elements', [], new ArrayList(new Text(DATABASE::LENGTH_KEY), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' elements are allowed, each ' . DATABASE::LENGTH_KEY . ' characters long.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, new Text(0), 'Default value for column when not provided. Cannot be set when column is required.', true) - ->param('array', false, new Boolean(), 'Is column an array?', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, array $elements, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - if (!is_null($default) && !in_array($default, $elements)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements'); - } - - $column = createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_STRING, - 'size' => Database::LENGTH_KEY, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'format' => APP_DATABASE_ATTRIBUTE_ENUM, - 'formatOptions' => ['elements' => $elements], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($column, Response::MODEL_ATTRIBUTE_ENUM); - }); - -App::post('/v1/databases/:databaseId/tables/:tableId/columns/ip') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/ip') - ->desc('Create IP address column') - ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'column.create') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'createIpColumn', - description: '/docs/references/databases/create-ip-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_ACCEPTED, - model: Response::MODEL_ATTRIBUTE_IP, - ) - ] - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, new IP(), 'Default value for column when not provided. Cannot be set when column is required.', true) - ->param('array', false, new Boolean(), 'Is column an array?', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - - $column = createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_STRING, - 'size' => 39, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'format' => APP_DATABASE_ATTRIBUTE_IP, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($column, Response::MODEL_ATTRIBUTE_IP); - }); - -App::post('/v1/databases/:databaseId/tables/:tableId/columns/url') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/url') - ->desc('Create URL column') - ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'column.create') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'createUrlColumn', - description: '/docs/references/databases/create-url-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_ACCEPTED, - model: Response::MODEL_ATTRIBUTE_URL, - ) - ] - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, new URL(), 'Default value for column when not provided. Cannot be set when column is required.', true) - ->param('array', false, new Boolean(), 'Is column an array?', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - - $column = createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_STRING, - 'size' => 2000, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'format' => APP_DATABASE_ATTRIBUTE_URL, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($column, Response::MODEL_ATTRIBUTE_URL); - }); - -App::post('/v1/databases/:databaseId/tables/:tableId/columns/integer') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/integer') - ->desc('Create integer column') - ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'column.create') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'createIntegerColumn', - description: '/docs/references/databases/create-integer-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_ACCEPTED, - model: Response::MODEL_ATTRIBUTE_INTEGER, - ) - ] - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('min', null, new Integer(), 'Minimum value to enforce on new documents', true) - ->param('max', null, new Integer(), 'Maximum value to enforce on new documents', true) - ->param('default', null, new Integer(), 'Default value for column when not provided. Cannot be set when column is required.', true) - ->param('array', false, new Boolean(), 'Is column an array?', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - - // Ensure attribute default is within range - $min ??= PHP_INT_MIN; - $max ??= PHP_INT_MAX; - - if ($min > $max) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); - } - - $validator = new Range($min, $max, Database::VAR_INTEGER); - - if (!is_null($default) && !$validator->isValid($default)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); - } - - $size = $max > 2147483647 ? 8 : 4; // Automatically create BigInt depending on max value - - $column = createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_INTEGER, - 'size' => $size, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'format' => APP_DATABASE_ATTRIBUTE_INT_RANGE, - 'formatOptions' => [ - 'min' => $min, - 'max' => $max, - ], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $formatOptions = $column->getAttribute('formatOptions', []); - - if (!empty($formatOptions)) { - $column->setAttribute('min', \intval($formatOptions['min'])); - $column->setAttribute('max', \intval($formatOptions['max'])); - } - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($column, Response::MODEL_ATTRIBUTE_INTEGER); - }); - -App::post('/v1/databases/:databaseId/tables/:tableId/columns/float') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/float') - ->desc('Create float column') - ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'column.create') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'createFloatColumn', - description: '/docs/references/databases/create-float-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_ACCEPTED, - model: Response::MODEL_ATTRIBUTE_FLOAT, - ) - ] - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('min', null, new FloatValidator(), 'Minimum value to enforce on new documents', true) - ->param('max', null, new FloatValidator(), 'Maximum value to enforce on new documents', true) - ->param('default', null, new FloatValidator(), 'Default value for column when not provided. Cannot be set when column is required.', true) - ->param('array', false, new Boolean(), 'Is column an array?', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - - // Ensure attribute default is within range - $min ??= -PHP_FLOAT_MAX; - $max ??= PHP_FLOAT_MAX; - - if ($min > $max) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); - } - - $validator = new Range($min, $max, Database::VAR_FLOAT); - - if (!\is_null($default) && !$validator->isValid($default)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); - } - - $column = createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_FLOAT, - 'required' => $required, - 'size' => 0, - 'default' => $default, - 'array' => $array, - 'format' => APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, - 'formatOptions' => [ - 'min' => $min, - 'max' => $max, - ], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $formatOptions = $column->getAttribute('formatOptions', []); - - if (!empty($formatOptions)) { - $column->setAttribute('min', \floatval($formatOptions['min'])); - $column->setAttribute('max', \floatval($formatOptions['max'])); - } - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($column, Response::MODEL_ATTRIBUTE_FLOAT); - }); - -App::post('/v1/databases/:databaseId/tables/:tableId/columns/boolean') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/boolean') - ->desc('Create boolean column') - ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'column.create') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'createBooleanColumn', - description: '/docs/references/databases/create-boolean-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_ACCEPTED, - model: Response::MODEL_ATTRIBUTE_BOOLEAN, - ) - ] - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, new Boolean(), 'Default value for column when not provided. Cannot be set when column is required.', true) - ->param('array', false, new Boolean(), 'Is column an array?', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - - $column = createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_BOOLEAN, - 'size' => 0, - 'required' => $required, - 'default' => $default, - 'array' => $array, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($column, Response::MODEL_ATTRIBUTE_BOOLEAN); - }); - -App::post('/v1/databases/:databaseId/tables/:tableId/columns/datetime') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/datetime') - ->desc('Create datetime column') - ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'column.create') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'createDatetimeColumn', - description: '/docs/references/databases/create-datetime-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_ACCEPTED, - model: Response::MODEL_ATTRIBUTE_DATETIME, - ) - ] - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, fn (Database $dbForProject) => new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime()), 'Default value for the attribute in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Cannot be set when column is required.', true, ['dbForProject']) - ->param('array', false, new Boolean(), 'Is column an array?', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - - $filters[] = 'datetime'; - - $column = createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_DATETIME, - 'size' => 0, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'filters' => $filters, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($column, Response::MODEL_ATTRIBUTE_DATETIME); - }); - -App::post('/v1/databases/:databaseId/tables/:tableId/columns/relationship') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/relationship') - ->desc('Create relationship column') - ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'column.create') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'createRelationshipColumn', - description: '/docs/references/databases/create-relationship-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_ACCEPTED, - model: Response::MODEL_ATTRIBUTE_RELATIONSHIP, - ) - ] - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('relatedTableId', '', new UID(), 'Related Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('type', '', new WhiteList([Database::RELATION_ONE_TO_ONE, Database::RELATION_MANY_TO_ONE, Database::RELATION_MANY_TO_MANY, Database::RELATION_ONE_TO_MANY], true), 'Relation type') - ->param('twoWay', false, new Boolean(), 'Is Two Way?', true) - ->param('key', null, new Key(), 'Column Key.', true) - ->param('twoWayKey', null, new Key(), 'Two Way Column Key.', true) - ->param('onDelete', Database::RELATION_MUTATE_RESTRICT, new WhiteList([Database::RELATION_MUTATE_CASCADE, Database::RELATION_MUTATE_RESTRICT, Database::RELATION_MUTATE_SET_NULL], true), 'Constraints option', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->action(function ( - string $databaseId, - string $tableId, - string $relatedTableId, - string $type, - bool $twoWay, - ?string $key, - ?string $twoWayKey, - string $onDelete, - Response $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ) { - $key ??= $relatedTableId; - $twoWayKey ??= $tableId; - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId()); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $relatedTableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId); - $relatedTable = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $relatedTableDocument->getInternalId()); - - if ($relatedTable->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $columns = $table->getAttribute('attributes', []); - /** @var Document[] $columns */ - foreach ($columns as $column) { - if ($column->getAttribute('type') !== Database::VAR_RELATIONSHIP) { - continue; - } - - if (\strtolower($column->getId()) === \strtolower($key)) { - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); - } - - if ( - \strtolower($column->getAttribute('options')['twoWayKey']) === \strtolower($twoWayKey) && - $column->getAttribute('options')['relatedCollection'] === $relatedTable->getId() - ) { - // Console should provide a unique twoWayKey input! - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.'); - } - - if ( - $type === Database::RELATION_MANY_TO_MANY && - $column->getAttribute('options')['relationType'] === Database::RELATION_MANY_TO_MANY && - $column->getAttribute('options')['relatedCollection'] === $relatedTable->getId() - ) { - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Creating more than one "manyToMany" relationship on the same table is currently not permitted.'); - } - } - - $column = createColumn( - $databaseId, - $tableId, - new Document([ - 'key' => $key, - 'type' => Database::VAR_RELATIONSHIP, - 'size' => 0, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - 'options' => [ - 'relatedCollection' => $relatedTableId, - 'relationType' => $type, - 'twoWay' => $twoWay, - 'twoWayKey' => $twoWayKey, - 'onDelete' => $onDelete, - ] - ]), - $response, - $dbForProject, - $queueForDatabase, - $queueForEvents - ); - - $options = $column->getAttribute('options', []); - - foreach ($options as $key => $option) { - $column->setAttribute($key, $option); - } - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($column, Response::MODEL_ATTRIBUTE_RELATIONSHIP); - }); - -App::get('/v1/databases/:databaseId/tables/:tableId/columns') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes') - ->desc('List columns') - ->groups(['api', 'database']) - ->label('scope', 'collections.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'listColumns', - description: '/docs/references/databases/list-attributes.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_ATTRIBUTE_LIST - ) - ] - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) - ->inject('response') - ->inject('dbForProject') - ->action(function (string $databaseId, string $tableId, array $queries, Response $response, Database $dbForProject) { - /** @var Document $database */ - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $queries = Query::parseQueries($queries); - - \array_push( - $queries, - Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$table->getInternalId()]), - ); - - /** - * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries - */ - $cursor = \array_filter($queries, function ($query) { - return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); - }); - - $cursor = \reset($cursor); - - if ($cursor) { - $validator = new Cursor(); - if (!$validator->isValid($cursor)) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); - } - - $columnId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->find('attributes', [ - Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$table->getInternalId()]), - Query::equal('key', [$columnId]), - Query::limit(1), - ])); - - if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Column '{$columnId}' for the 'cursor' value not found."); - } - - $cursor->setValue($cursorDocument[0]); - } - - $filters = Query::groupByType($queries)['filters']; - try { - $columns = $dbForProject->find('attributes', $queries); - $total = $dbForProject->count('attributes', $filters, APP_LIMIT_COUNT); - } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); - } - - $response->dynamic(new Document([ - 'attributes' => $columns, - 'total' => $total, - ]), Response::MODEL_ATTRIBUTE_LIST); - }); - -App::get('/v1/databases/:databaseId/tables/:tableId/columns/:key') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/:key') - ->desc('Get column') - ->groups(['api', 'database']) - ->label('scope', 'collections.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'getColumn', - description: '/docs/references/databases/get-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: [ - Response::MODEL_ATTRIBUTE_BOOLEAN, - Response::MODEL_ATTRIBUTE_INTEGER, - Response::MODEL_ATTRIBUTE_FLOAT, - Response::MODEL_ATTRIBUTE_EMAIL, - Response::MODEL_ATTRIBUTE_ENUM, - Response::MODEL_ATTRIBUTE_URL, - Response::MODEL_ATTRIBUTE_IP, - Response::MODEL_ATTRIBUTE_DATETIME, - Response::MODEL_ATTRIBUTE_RELATIONSHIP, - Response::MODEL_ATTRIBUTE_STRING - ] - ), - ] - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->inject('response') - ->inject('dbForProject') - ->action(function (string $databaseId, string $tableId, string $key, Response $response, Database $dbForProject) { - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $column = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $table->getInternalId() . '_' . $key); - - if ($column->isEmpty()) { - throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); - } - - // Select response model based on type and format - $type = $column->getAttribute('type'); - $format = $column->getAttribute('format'); - $options = $column->getAttribute('options', []); - - foreach ($options as $key => $option) { - $column->setAttribute($key, $option); - } - - $model = match ($type) { - Database::VAR_BOOLEAN => Response::MODEL_ATTRIBUTE_BOOLEAN, - Database::VAR_INTEGER => Response::MODEL_ATTRIBUTE_INTEGER, - Database::VAR_FLOAT => Response::MODEL_ATTRIBUTE_FLOAT, - Database::VAR_DATETIME => Response::MODEL_ATTRIBUTE_DATETIME, - Database::VAR_RELATIONSHIP => Response::MODEL_ATTRIBUTE_RELATIONSHIP, - Database::VAR_STRING => match ($format) { - APP_DATABASE_ATTRIBUTE_EMAIL => Response::MODEL_ATTRIBUTE_EMAIL, - APP_DATABASE_ATTRIBUTE_ENUM => Response::MODEL_ATTRIBUTE_ENUM, - APP_DATABASE_ATTRIBUTE_IP => Response::MODEL_ATTRIBUTE_IP, - APP_DATABASE_ATTRIBUTE_URL => Response::MODEL_ATTRIBUTE_URL, - default => Response::MODEL_ATTRIBUTE_STRING, - }, - default => Response::MODEL_ATTRIBUTE, - }; - - $response->dynamic($column, $model); - }); - -App::patch('/v1/databases/:databaseId/tables/:tableId/columns/string/:key') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/string/:key') - ->desc('Update string column') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') - ->label('audits.event', 'column.update') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'updateStringColumn', - description: '/docs/references/databases/update-string-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_ATTRIBUTE_STRING, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, new Nullable(new Text(0, 0)), 'Default value for column when not provided. Cannot be set when column is required.') - ->param('size', null, new Range(1, APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH, Range::TYPE_INTEGER), 'Maximum size of the string attribute.', true) - ->param('newKey', null, new Key(), 'New Column Key.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?int $size, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - - $column = updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_STRING, - size: $size, - default: $default, - required: $required, - newKey: $newKey - ); - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($column, Response::MODEL_ATTRIBUTE_STRING); - }); - -App::patch('/v1/databases/:databaseId/tables/:tableId/columns/email/:key') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/email/:key') - ->desc('Update email column') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') - ->label('audits.event', 'column.update') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'updateEmailColumn', - description: '/docs/references/databases/update-email-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_ATTRIBUTE_EMAIL, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, new Nullable(new Email()), 'Default value for column when not provided. Cannot be set when column is required.') - ->param('newKey', null, new Key(), 'New Column Key.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $column = updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_STRING, - filter: APP_DATABASE_ATTRIBUTE_EMAIL, - default: $default, - required: $required, - newKey: $newKey - ); - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($column, Response::MODEL_ATTRIBUTE_EMAIL); - }); - -App::patch('/v1/databases/:databaseId/tables/:tableId/columns/enum/:key') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/enum/:key') - ->desc('Update enum column') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') - ->label('audits.event', 'column.update') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'updateEnumColumn', - description: '/docs/references/databases/update-enum-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_ATTRIBUTE_ENUM, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('elements', null, new ArrayList(new Text(DATABASE::LENGTH_KEY), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' elements are allowed, each ' . DATABASE::LENGTH_KEY . ' characters long.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, new Nullable(new Text(0)), 'Default value for column when not provided. Cannot be set when column is required.') - ->param('newKey', null, new Key(), 'New Column Key.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $column = updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_STRING, - filter: APP_DATABASE_ATTRIBUTE_ENUM, - default: $default, - required: $required, - elements: $elements, - newKey: $newKey - ); - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($column, Response::MODEL_ATTRIBUTE_ENUM); - }); - -App::patch('/v1/databases/:databaseId/tables/:tableId/columns/ip/:key') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/ip/:key') - ->desc('Update IP address column') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') - ->label('audits.event', 'column.update') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'updateIpColumn', - description: '/docs/references/databases/update-ip-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_ATTRIBUTE_IP, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, new Nullable(new IP()), 'Default value for column when not provided. Cannot be set when column is required.') - ->param('newKey', null, new Key(), 'New Column Key.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $column = updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_STRING, - filter: APP_DATABASE_ATTRIBUTE_IP, - default: $default, - required: $required, - newKey: $newKey - ); - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($column, Response::MODEL_ATTRIBUTE_IP); - }); - -App::patch('/v1/databases/:databaseId/tables/:tableId/columns/url/:key') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/url/:key') - ->desc('Update URL column') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') - ->label('audits.event', 'column.update') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'updateUrlColumn', - description: '/docs/references/databases/update-url-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_ATTRIBUTE_URL, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, new Nullable(new URL()), 'Default value for column when not provided. Cannot be set when column is required.') - ->param('newKey', null, new Key(), 'New Column Key.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $column = updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_STRING, - filter: APP_DATABASE_ATTRIBUTE_URL, - default: $default, - required: $required, - newKey: $newKey - ); - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($column, Response::MODEL_ATTRIBUTE_URL); - }); - -App::patch('/v1/databases/:databaseId/tables/:tableId/columns/integer/:key') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/integer/:key') - ->desc('Update integer column') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') - ->label('audits.event', 'column.update') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'updateIntegerColumn', - description: '/docs/references/databases/update-integer-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_ATTRIBUTE_INTEGER, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('min', null, new Integer(), 'Minimum value to enforce on new documents', true) - ->param('max', null, new Integer(), 'Maximum value to enforce on new documents', true) - ->param('default', null, new Nullable(new Integer()), 'Default value for column when not provided. Cannot be set when column is required.') - ->param('newKey', null, new Key(), 'New Column Key.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $column = updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_INTEGER, - default: $default, - required: $required, - min: $min, - max: $max, - newKey: $newKey - ); - - $formatOptions = $column->getAttribute('formatOptions', []); - - if (!empty($formatOptions)) { - $column->setAttribute('min', \intval($formatOptions['min'])); - $column->setAttribute('max', \intval($formatOptions['max'])); - } - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($column, Response::MODEL_ATTRIBUTE_INTEGER); - }); - -App::patch('/v1/databases/:databaseId/tables/:tableId/columns/float/:key') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/float/:key') - ->desc('Update float column') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') - ->label('audits.event', 'column.update') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'updateFloatColumn', - description: '/docs/references/databases/update-float-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_ATTRIBUTE_FLOAT, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('min', null, new FloatValidator(), 'Minimum value to enforce on new documents', true) - ->param('max', null, new FloatValidator(), 'Maximum value to enforce on new documents', true) - ->param('default', null, new Nullable(new FloatValidator()), 'Default value for column when not provided. Cannot be set when column is required.') - ->param('newKey', null, new Key(), 'New Column Key.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $column = updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_FLOAT, - default: $default, - required: $required, - min: $min, - max: $max, - newKey: $newKey - ); - - $formatOptions = $column->getAttribute('formatOptions', []); - - if (!empty($formatOptions)) { - $column->setAttribute('min', \floatval($formatOptions['min'])); - $column->setAttribute('max', \floatval($formatOptions['max'])); - } - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($column, Response::MODEL_ATTRIBUTE_FLOAT); - }); - -App::patch('/v1/databases/:databaseId/tables/:tableId/columns/boolean/:key') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/boolean/:key') - ->desc('Update boolean column') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') - ->label('audits.event', 'column.update') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'updateBooleanColumn', - description: '/docs/references/databases/update-boolean-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_ATTRIBUTE_BOOLEAN, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, new Nullable(new Boolean()), 'Default value for column when not provided. Cannot be set when column is required.') - ->param('newKey', null, new Key(), 'New Column Key.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $column = updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_BOOLEAN, - default: $default, - required: $required, - newKey: $newKey - ); - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($column, Response::MODEL_ATTRIBUTE_BOOLEAN); - }); - -App::patch('/v1/databases/:databaseId/tables/:tableId/columns/datetime/:key') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/datetime/:key') - ->desc('Update dateTime column') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') - ->label('audits.event', 'column.update') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'updateDatetimeColumn', - description: '/docs/references/databases/update-datetime-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_ATTRIBUTE_DATETIME, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, fn (Database $dbForProject) => new Nullable(new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime())), 'Default value for column when not provided. Cannot be set when column is required.', injections: ['dbForProject']) - ->param('newKey', null, new Key(), 'New Column Key.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?string $newKey, Response $response, Database $dbForProject, Event $queueForEvents) { - $column = updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_DATETIME, - default: $default, - required: $required, - newKey: $newKey - ); - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($column, Response::MODEL_ATTRIBUTE_DATETIME); - }); - -App::patch('/v1/databases/:databaseId/tables/:tableId/columns/:key/relationship') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/:key/relationship') - ->desc('Update relationship column') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') - ->label('audits.event', 'column.update') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'updateRelationshipColumn', - description: '/docs/references/databases/update-relationship-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_ATTRIBUTE_RELATIONSHIP, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->param('onDelete', null, new WhiteList([Database::RELATION_MUTATE_CASCADE, Database::RELATION_MUTATE_RESTRICT, Database::RELATION_MUTATE_SET_NULL], true), 'Constraints option', true) - ->param('newKey', null, new Key(), 'New Column Key.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->action(function ( - string $databaseId, - string $tableId, - string $key, - ?string $onDelete, - ?string $newKey, - Response $response, - Database $dbForProject, - Event $queueForEvents - ) { - $column = updateColumn( - $databaseId, - $tableId, - $key, - $dbForProject, - $queueForEvents, - type: Database::VAR_RELATIONSHIP, - required: false, - options: [ - 'onDelete' => $onDelete - ], - newKey: $newKey - ); - - $options = $column->getAttribute('options', []); - - foreach ($options as $key => $option) { - $column->setAttribute($key, $option); - } - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic($column, Response::MODEL_ATTRIBUTE_RELATIONSHIP); - }); - -App::delete('/v1/databases/:databaseId/tables/:tableId/columns/:key') - ->alias('/v1/databases/:databaseId/collections/:tableId/attributes/:key') - ->desc('Delete column') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') - ->label('audits.event', 'column.delete') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'columns', - name: 'deleteColumn', - description: '/docs/references/databases/delete-attribute.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_NOCONTENT, - model: Response::MODEL_NONE, - ) - ], - contentType: ContentType::NONE - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Column Key.') - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->inject('queueForStatsUsage') - ->action(function (string $databaseId, string $tableId, string $key, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, StatsUsage $queueForStatsUsage) { - - $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($db->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $column = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); - - if ($column->isEmpty()) { - throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); - } - - /** - * Check index dependency - */ - $validator = new IndexDependencyValidator( - $table->getAttribute('indexes'), - $dbForProject->getAdapter()->getSupportForCastIndexArray(), - ); - - if (! $validator->isValid($column)) { - throw new Exception(Exception::INDEX_DEPENDENCY); - } - - // Only update status if removing available attribute - if ($column->getAttribute('status') === 'available') { - $column = $dbForProject->updateDocument('attributes', $column->getId(), $column->setAttribute('status', 'deleting')); - } - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $table->getInternalId()); - - if ($column->getAttribute('type') === Database::VAR_RELATIONSHIP) { - $options = $column->getAttribute('options'); - if ($options['twoWay']) { - $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection']); - - if ($relatedTable->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $relatedColumn = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $options['twoWayKey']); - - if ($relatedColumn->isEmpty()) { - throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); - } - - if ($relatedColumn->getAttribute('status') === 'available') { - $dbForProject->updateDocument('attributes', $relatedColumn->getId(), $relatedColumn->setAttribute('status', 'deleting')); - } - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); - } - } - - $queueForDatabase - ->setType(DATABASE_TYPE_DELETE_ATTRIBUTE) - ->setTable($table) - ->setDatabase($db) - ->setRow($column); - - // Select response model based on type and format - $type = $column->getAttribute('type'); - $format = $column->getAttribute('format'); - - $model = match ($type) { - Database::VAR_BOOLEAN => Response::MODEL_ATTRIBUTE_BOOLEAN, - Database::VAR_INTEGER => Response::MODEL_ATTRIBUTE_INTEGER, - Database::VAR_FLOAT => Response::MODEL_ATTRIBUTE_FLOAT, - Database::VAR_DATETIME => Response::MODEL_ATTRIBUTE_DATETIME, - Database::VAR_RELATIONSHIP => Response::MODEL_ATTRIBUTE_RELATIONSHIP, - Database::VAR_STRING => match ($format) { - APP_DATABASE_ATTRIBUTE_EMAIL => Response::MODEL_ATTRIBUTE_EMAIL, - APP_DATABASE_ATTRIBUTE_ENUM => Response::MODEL_ATTRIBUTE_ENUM, - APP_DATABASE_ATTRIBUTE_IP => Response::MODEL_ATTRIBUTE_IP, - APP_DATABASE_ATTRIBUTE_URL => Response::MODEL_ATTRIBUTE_URL, - default => Response::MODEL_ATTRIBUTE_STRING, - }, - default => Response::MODEL_ATTRIBUTE, - }; - - $queueForEvents - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('columnId', $column->getId()) - ->setContext('table', $table) - ->setContext('database', $db) - ->setPayload($response->output($column, $model)); - - $response->noContent(); - }); - App::post('/v1/databases/:databaseId/tables/:tableId/indexes') ->alias('/v1/databases/:databaseId/collections/:tableId/indexes') ->desc('Create index') @@ -4276,7 +2378,7 @@ App::get('/v1/databases/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ + $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -4305,7 +2407,7 @@ App::get('/v1/databases/usage') }; foreach ($metrics as $metric) { - $usage[$metric]['total'] = $stats[$metric]['total']; + $usage[$metric]['total'] = $stats[$metric]['total']; $usage[$metric]['data'] = []; $leap = time() - ($days['limit'] * $days['factor']); while ($leap < time()) { @@ -4319,16 +2421,16 @@ App::get('/v1/databases/usage') } $response->dynamic(new Document([ 'range' => $range, - 'databasesTotal' => $usage[$metrics[0]]['total'], + 'databasesTotal' => $usage[$metrics[0]]['total'], 'collectionsTotal' => $usage[$metrics[1]]['total'], - 'documentsTotal' => $usage[$metrics[2]]['total'], - 'storageTotal' => $usage[$metrics[3]]['total'], + 'documentsTotal' => $usage[$metrics[2]]['total'], + 'storageTotal' => $usage[$metrics[3]]['total'], 'databasesReadsTotal' => $usage[$metrics[4]]['total'], 'databasesWritesTotal' => $usage[$metrics[5]]['total'], - 'databases' => $usage[$metrics[0]]['data'], + 'databases' => $usage[$metrics[0]]['data'], 'collections' => $usage[$metrics[1]]['data'], - 'documents' => $usage[$metrics[2]]['data'], - 'storage' => $usage[$metrics[3]]['data'], + 'documents' => $usage[$metrics[2]]['data'], + 'storage' => $usage[$metrics[3]]['data'], 'databasesReads' => $usage[$metrics[4]]['data'], 'databasesWrites' => $usage[$metrics[5]]['data'], ]), Response::MODEL_USAGE_DATABASES); @@ -4359,7 +2461,7 @@ App::get('/v1/databases/:databaseId/usage') ->inject('dbForProject') ->action(function (string $databaseId, string $range, Response $response, Database $dbForProject) { - $database = $dbForProject->getDocument('databases', $databaseId); + $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); @@ -4378,7 +2480,7 @@ App::get('/v1/databases/:databaseId/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ + $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -4407,7 +2509,7 @@ App::get('/v1/databases/:databaseId/usage') }; foreach ($metrics as $metric) { - $usage[$metric]['total'] = $stats[$metric]['total']; + $usage[$metric]['total'] = $stats[$metric]['total']; $usage[$metric]['data'] = []; $leap = time() - ($days['limit'] * $days['factor']); while ($leap < time()) { @@ -4422,16 +2524,16 @@ App::get('/v1/databases/:databaseId/usage') $response->dynamic(new Document([ 'range' => $range, - 'collectionsTotal' => $usage[$metrics[0]]['total'], - 'documentsTotal' => $usage[$metrics[1]]['total'], - 'storageTotal' => $usage[$metrics[2]]['total'], + 'collectionsTotal' => $usage[$metrics[0]]['total'], + 'documentsTotal' => $usage[$metrics[1]]['total'], + 'storageTotal' => $usage[$metrics[2]]['total'], 'databaseReadsTotal' => $usage[$metrics[3]]['total'], 'databaseWritesTotal' => $usage[$metrics[4]]['total'], - 'collections' => $usage[$metrics[0]]['data'], - 'documents' => $usage[$metrics[1]]['data'], - 'storage' => $usage[$metrics[2]]['data'], - 'databaseReads' => $usage[$metrics[3]]['data'], - 'databaseWrites' => $usage[$metrics[4]]['data'], + 'collections' => $usage[$metrics[0]]['data'], + 'documents' => $usage[$metrics[1]]['data'], + 'storage' => $usage[$metrics[2]]['data'], + 'databaseReads' => $usage[$metrics[3]]['data'], + 'databaseWrites' => $usage[$metrics[4]]['data'], ]), Response::MODEL_USAGE_DATABASE); }); @@ -4479,7 +2581,7 @@ App::get('/v1/databases/:databaseId/tables/:tableId/usage') Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ + $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -4496,7 +2598,7 @@ App::get('/v1/databases/:databaseId/tables/:tableId/usage') $stats[$metric]['data'] = []; foreach ($results as $result) { $stats[$metric]['data'][$result->getAttribute('time')] = [ - 'value' => $result->getAttribute('value'), + 'value' => $result->getAttribute('value'), ]; } } @@ -4508,7 +2610,7 @@ App::get('/v1/databases/:databaseId/tables/:tableId/usage') }; foreach ($metrics as $metric) { - $usage[$metric]['total'] = $stats[$metric]['total']; + $usage[$metric]['total'] = $stats[$metric]['total']; $usage[$metric]['data'] = []; $leap = time() - ($days['limit'] * $days['factor']); while ($leap < time()) { @@ -4523,7 +2625,7 @@ App::get('/v1/databases/:databaseId/tables/:tableId/usage') $response->dynamic(new Document([ 'range' => $range, - 'documentsTotal' => $usage[$metrics[0]]['total'], - 'documents' => $usage[$metrics[0]]['data'], + 'documentsTotal' => $usage[$metrics[0]]['total'], + 'documents' => $usage[$metrics[0]]['data'], ]), Response::MODEL_USAGE_COLLECTION); }); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php new file mode 100644 index 0000000000..70c26594a3 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php @@ -0,0 +1,417 @@ +getAttribute('key'); + $type = $column->getAttribute('type', ''); + $size = $column->getAttribute('size', 0); + $required = $column->getAttribute('required', true); + $signed = $column->getAttribute('signed', true); // integers are signed by default + $array = $column->getAttribute('array', false); + $format = $column->getAttribute('format', ''); + $formatOptions = $column->getAttribute('formatOptions', []); + $filters = $column->getAttribute('filters', []); // filters are hidden from the endpoint + $default = $column->getAttribute('default'); + $options = $column->getAttribute('options', []); + + $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($db->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); + + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + if (!empty($format)) { + if (!Structure::hasFormat($format, $type)) { + throw new Exception(Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, "Format {$format} not available for {$type} columns."); + } + } + + // Must throw here since dbForProject->createAttribute is performed by db worker + if ($required && isset($default)) { + throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for required column'); + } + + if ($array && isset($default)) { + throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array columns'); + } + + if ($type === Database::VAR_RELATIONSHIP) { + $options['side'] = Database::RELATION_SIDE_PARENT; + $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection'] ?? ''); + if ($relatedTable->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND, 'The related table was not found.'); + } + } + + try { + $column = new Document([ + '$id' => ID::custom($db->getInternalId() . '_' . $table->getInternalId() . '_' . $key), + 'key' => $key, + 'databaseInternalId' => $db->getInternalId(), + 'databaseId' => $db->getId(), + 'collectionInternalId' => $table->getInternalId(), + 'collectionId' => $tableId, + 'type' => $type, + 'status' => 'processing', // processing, available, failed, deleting, stuck + 'size' => $size, + 'required' => $required, + 'signed' => $signed, + 'default' => $default, + 'array' => $array, + 'format' => $format, + 'formatOptions' => $formatOptions, + 'filters' => $filters, + 'options' => $options, + ]); + + $dbForProject->checkAttribute($table, $column); + $column = $dbForProject->createDocument('attributes', $column); + } catch (DuplicateException) { + throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); + } catch (LimitException) { + throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); + } catch (Throwable $e) { + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $table->getInternalId()); + throw $e; + } + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $table->getInternalId()); + + if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { + $twoWayKey = $options['twoWayKey']; + $options['relatedCollection'] = $table->getId(); + $options['twoWayKey'] = $key; + $options['side'] = Database::RELATION_SIDE_CHILD; + + try { + $twoWayAttribute = new Document([ + '$id' => ID::custom($db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $twoWayKey), + 'key' => $twoWayKey, + 'databaseInternalId' => $db->getInternalId(), + 'databaseId' => $db->getId(), + 'collectionInternalId' => $relatedTable->getInternalId(), + 'collectionId' => $relatedTable->getId(), + 'type' => $type, + 'status' => 'processing', // processing, available, failed, deleting, stuck + 'size' => $size, + 'required' => $required, + 'signed' => $signed, + 'default' => $default, + 'array' => $array, + 'format' => $format, + 'formatOptions' => $formatOptions, + 'filters' => $filters, + 'options' => $options, + ]); + + $dbForProject->checkAttribute($relatedTable, $twoWayAttribute); + $dbForProject->createDocument('attributes', $twoWayAttribute); + } catch (DuplicateException) { + $dbForProject->deleteDocument('attributes', $column->getId()); + throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); + } catch (LimitException) { + $dbForProject->deleteDocument('attributes', $column->getId()); + throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); + } catch (Throwable $e) { + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); + throw $e; + } + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); + } + + $queueForDatabase + ->setType(DATABASE_TYPE_CREATE_ATTRIBUTE) + ->setDatabase($db) + ->setTable($table) + ->setRow($column); + + $queueForEvents + ->setContext('table', $table) + ->setContext('database', $db) + ->setParam('databaseId', $databaseId) + ->setParam('tableId', $table->getId()) + ->setParam('columnId', $column->getId()); + + $response->setStatusCode(SwooleResponse::STATUS_CODE_CREATED); + + return $column; + } + + protected function updateColumn( + string $databaseId, + string $tableId, + string $key, + Database $dbForProject, + Event $queueForEvents, + string $type, + int $size = null, + string $filter = null, + string|bool|int|float $default = null, + bool $required = null, + int|float|null $min = null, + int|float|null $max = null, + array $elements = null, + array $options = [], + string $newKey = null, + ): Document { + $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($db->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); + + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $column = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); + + if ($column->isEmpty()) { + throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + } + + if ($column->getAttribute('status') !== 'available') { + throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE); + } + + if ($column->getAttribute(('type') !== $type)) { + throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID); + } + + if ($column->getAttribute('type') === Database::VAR_STRING && $column->getAttribute(('filter') !== $filter)) { + throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID); + } + + if ($required && isset($default)) { + throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for required column'); + } + + if ($column->getAttribute('array', false) && isset($default)) { + throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array columns'); + } + + $tableId = 'database_' . $db->getInternalId() . '_collection_' . $table->getInternalId(); + + $column + ->setAttribute('default', $default) + ->setAttribute('required', $required); + + if (!empty($size)) { + $column->setAttribute('size', $size); + } + + switch ($column->getAttribute('format')) { + case APP_DATABASE_ATTRIBUTE_INT_RANGE: + case APP_DATABASE_ATTRIBUTE_FLOAT_RANGE: + $min ??= $column->getAttribute('formatOptions')['min']; + $max ??= $column->getAttribute('formatOptions')['max']; + + if ($min > $max) { + throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); + } + + if ($column->getAttribute('format') === APP_DATABASE_ATTRIBUTE_INT_RANGE) { + $validator = new Range($min, $max, Database::VAR_INTEGER); + } else { + $validator = new Range($min, $max, Database::VAR_FLOAT); + + if (!is_null($default)) { + $default = \floatval($default); + } + } + + if (!is_null($default) && !$validator->isValid($default)) { + throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); + } + + $options = [ + 'min' => $min, + 'max' => $max + ]; + $column->setAttribute('formatOptions', $options); + + break; + case APP_DATABASE_ATTRIBUTE_ENUM: + if (empty($elements)) { + throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Enum elements must not be empty'); + } + + foreach ($elements as $element) { + if (\strlen($element) === 0) { + throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Each enum element must not be empty'); + } + } + + if (!is_null($default) && !in_array($default, $elements)) { + throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements'); + } + + $options = [ + 'elements' => $elements + ]; + + $column->setAttribute('formatOptions', $options); + + break; + } + + if ($type === Database::VAR_RELATIONSHIP) { + $primaryRowOptions = \array_merge($column->getAttribute('options', []), $options); + $column->setAttribute('options', $primaryRowOptions); + try { + $dbForProject->updateRelationship( + collection: $tableId, + id: $key, + newKey: $newKey, + onDelete: $primaryRowOptions['onDelete'], + ); + } catch (NotFoundException) { + throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + } + + if ($primaryRowOptions['twoWay']) { + $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $primaryRowOptions['relatedCollection']); + + $relatedColumn = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $primaryRowOptions['twoWayKey']); + + if (!empty($newKey) && $newKey !== $key) { + $options['twoWayKey'] = $newKey; + } + + $relatedOptions = \array_merge($relatedColumn->getAttribute('options'), $options); + $relatedColumn->setAttribute('options', $relatedOptions); + $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $primaryRowOptions['twoWayKey'], $relatedColumn); + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); + } + } else { + try { + $dbForProject->updateAttribute( + collection: $tableId, + id: $key, + size: $size, + required: $required, + default: $default, + formatOptions: $options, + newKey: $newKey ?? null + ); + } catch (TruncateException) { + throw new Exception(Exception::ATTRIBUTE_INVALID_RESIZE); + } catch (NotFoundException) { + throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + } catch (LimitException) { + throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); + } catch (IndexException $e) { + throw new Exception(Exception::INDEX_INVALID, $e->getMessage()); + } + } + + if (!empty($newKey) && $key !== $newKey) { + $originalUid = $column->getId(); + + $column + ->setAttribute('$id', ID::custom($db->getInternalId() . '_' . $table->getInternalId() . '_' . $newKey)) + ->setAttribute('key', $newKey); + + $dbForProject->updateDocument('attributes', $originalUid, $column); + + /** + * @var Document $index + */ + foreach ($table->getAttribute('indexes') as $index) { + /** + * @var string[] $columns + */ + $columns = $index->getAttribute('attributes', []); + $found = \array_search($key, $columns); + + if ($found !== false) { + $columns[$found] = $newKey; + $index->setAttribute('attributes', $columns); + $dbForProject->updateDocument('indexes', $index->getId(), $index); + } + } + } else { + $column = $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key, $column); + } + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $table->getId()); + + $queueForEvents + ->setContext('table', $table) + ->setContext('database', $db) + ->setParam('databaseId', $databaseId) + ->setParam('tableId', $table->getId()) + ->setParam('columnId', $column->getId()); + + return $column; + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php new file mode 100644 index 0000000000..dab0527fa7 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php @@ -0,0 +1,84 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/boolean') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/boolean') + ->desc('Create boolean column') + ->groups(['api', 'database', 'schema']) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'createBooleanColumn', + description: '/docs/references/databases/create-boolean-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN, + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Boolean(), 'Default value for column when not provided. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { + + $column = $this->createColumn($databaseId, $tableId, new Document([ + 'key' => $key, + 'type' => Database::VAR_BOOLEAN, + 'size' => 0, + 'required' => $required, + 'default' => $default, + 'array' => $array, + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php new file mode 100644 index 0000000000..35148fc174 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php @@ -0,0 +1,86 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/boolean/:key') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/boolean/:key') + ->desc('Update boolean column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'updateBooleanColumn', + description: '/docs/references/databases/update-boolean-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Nullable(new Boolean()), 'Default value for column when not provided. Cannot be set when column is required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { + $column = $this->updateColumn( + databaseId: $databaseId, + tableId: $tableId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_BOOLEAN, + default: $default, + required: $required, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php new file mode 100644 index 0000000000..36ddfb4dfa --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php @@ -0,0 +1,106 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/datetime') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/datetime') + ->desc('Create datetime column') + ->groups(['api', 'database']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'createDatetimeColumn', + description: '/docs/references/databases/create-datetime-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: UtopiaResponse::MODEL_ATTRIBUTE_DATETIME, + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, fn (Database $dbForProject) => new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime()), 'Default value for the attribute in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Cannot be set when column is required.', true, ['dbForProject']) + ->param('array', false, new Boolean(), 'Is column an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?string $default, + bool $array, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $filters = ['datetime']; + + $column = $this->createColumn( + $databaseId, + $tableId, + new Document([ + 'key' => $key, + 'type' => Database::VAR_DATETIME, + 'size' => 0, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'filters' => $filters, + ]), + $response, + $dbForProject, + $queueForDatabase, + $queueForEvents + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_DATETIME); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php new file mode 100644 index 0000000000..d323ed4fd0 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php @@ -0,0 +1,97 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/datetime/:key') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/datetime/:key') + ->desc('Update dateTime column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'updateDatetimeColumn', + description: '/docs/references/databases/update-datetime-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_ATTRIBUTE_DATETIME, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, fn (Database $dbForProject) => new Nullable(new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime())), 'Default value for column when not provided. Cannot be set when column is required.', injections: ['dbForProject']) + ->param('newKey', null, new Key(), 'New Column Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?string $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $column = $this->updateColumn( + databaseId: $databaseId, + tableId: $tableId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_DATETIME, + default: $default, + required: $required, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_DATETIME); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php new file mode 100644 index 0000000000..9baa857fec --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php @@ -0,0 +1,164 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/:key') + ->desc('Delete column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.delete') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'deleteColumn', + description: '/docs/references/databases/delete-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_NOCONTENT, + model: UtopiaResponse::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents, + ): void { + $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($db->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $column = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); + if ($column->isEmpty()) { + throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + } + + $validator = new IndexDependencyValidator( + $table->getAttribute('indexes'), + $dbForProject->getAdapter()->getSupportForCastIndexArray(), + ); + if (!$validator->isValid($column)) { + throw new Exception(Exception::INDEX_DEPENDENCY); + } + + if ($column->getAttribute('status') === 'available') { + $column = $dbForProject->updateDocument('attributes', $column->getId(), $column->setAttribute('status', 'deleting')); + } + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $table->getInternalId()); + + if ($column->getAttribute('type') === Database::VAR_RELATIONSHIP) { + $options = $column->getAttribute('options'); + if ($options['twoWay']) { + $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection']); + if ($relatedTable->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $relatedColumn = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $options['twoWayKey']); + if ($relatedColumn->isEmpty()) { + throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + } + + if ($relatedColumn->getAttribute('status') === 'available') { + $dbForProject->updateDocument('attributes', $relatedColumn->getId(), $relatedColumn->setAttribute('status', 'deleting')); + } + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); + } + } + + $queueForDatabase + ->setType(DATABASE_TYPE_DELETE_ATTRIBUTE) + ->setTable($table) + ->setDatabase($db) + ->setRow($column); + + $type = $column->getAttribute('type'); + $format = $column->getAttribute('format'); + + $model = match ($type) { + Database::VAR_BOOLEAN => UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN, + Database::VAR_INTEGER => UtopiaResponse::MODEL_ATTRIBUTE_INTEGER, + Database::VAR_FLOAT => UtopiaResponse::MODEL_ATTRIBUTE_FLOAT, + Database::VAR_DATETIME => UtopiaResponse::MODEL_ATTRIBUTE_DATETIME, + Database::VAR_RELATIONSHIP => UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP, + Database::VAR_STRING => match ($format) { + APP_DATABASE_ATTRIBUTE_EMAIL => UtopiaResponse::MODEL_ATTRIBUTE_EMAIL, + APP_DATABASE_ATTRIBUTE_ENUM => UtopiaResponse::MODEL_ATTRIBUTE_ENUM, + APP_DATABASE_ATTRIBUTE_IP => UtopiaResponse::MODEL_ATTRIBUTE_IP, + APP_DATABASE_ATTRIBUTE_URL => UtopiaResponse::MODEL_ATTRIBUTE_URL, + default => UtopiaResponse::MODEL_ATTRIBUTE_STRING, + }, + default => UtopiaResponse::MODEL_ATTRIBUTE, + }; + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setParam('tableId', $table->getId()) + ->setParam('columnId', $column->getId()) + ->setContext('table', $table) + ->setContext('database', $db) + ->setPayload($response->output($column, $model)); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php new file mode 100644 index 0000000000..1d51e26efc --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php @@ -0,0 +1,104 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/email') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/email') + ->desc('Create email column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'createEmailColumn', + description: '/docs/references/databases/create-email-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: UtopiaResponse::MODEL_ATTRIBUTE_EMAIL, + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Email(), 'Default value for column when not provided. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?string $default, + bool $array, + \Appwrite\Utopia\Response $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $column = $this->createColumn( + $databaseId, + $tableId, + new Document([ + 'key' => $key, + 'type' => Database::VAR_STRING, + 'size' => 254, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'format' => APP_DATABASE_ATTRIBUTE_EMAIL, + ]), + $response, + $dbForProject, + $queueForDatabase, + $queueForEvents + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_EMAIL); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php new file mode 100644 index 0000000000..53e03c93a2 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php @@ -0,0 +1,98 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/email/:key') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/email/:key') + ->desc('Update email column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'updateEmailColumn', + description: '/docs/references/databases/update-email-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_ATTRIBUTE_EMAIL, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Nullable(new Email()), 'Default value for column when not provided. Cannot be set when column is required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?string $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $column = $this->updateColumn( + databaseId: $databaseId, + tableId: $tableId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_STRING, + filter: APP_DATABASE_ATTRIBUTE_EMAIL, + default: $default, + required: $required, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_EMAIL); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php new file mode 100644 index 0000000000..95ed0b0630 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php @@ -0,0 +1,113 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/enum') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/enum') + ->desc('Create enum column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'createEnumColumn', + description: '/docs/references/databases/create-attribute-enum.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: UtopiaResponse::MODEL_ATTRIBUTE_ENUM, + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('elements', [], new ArrayList(new Text(Database::LENGTH_KEY), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of enum values.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Text(0), 'Default value for column when not provided. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + array $elements, + ?bool $required, + ?string $default, + bool $array, + \Appwrite\Utopia\Response $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + if (!is_null($default) && !in_array($default, $elements, true)) { + throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements'); + } + + $column = $this->createColumn( + $databaseId, + $tableId, + new Document([ + 'key' => $key, + 'type' => Database::VAR_STRING, + 'size' => Database::LENGTH_KEY, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'format' => APP_DATABASE_ATTRIBUTE_ENUM, + 'formatOptions' => ['elements' => $elements], + ]), + $response, + $dbForProject, + $queueForDatabase, + $queueForEvents + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_ENUM); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php new file mode 100644 index 0000000000..d52dd161e4 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php @@ -0,0 +1,102 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/enum/:key') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/enum/:key') + ->desc('Update enum column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'updateEnumColumn', + description: '/docs/references/databases/update-enum-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_ATTRIBUTE_ENUM, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('elements', null, new ArrayList(new Text(Database::LENGTH_KEY), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Updated list of enum values.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Nullable(new Text(0)), 'Default value for column when not provided. Cannot be set when column is required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?array $elements, + ?bool $required, + ?string $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $column = $this->updateColumn( + databaseId: $databaseId, + tableId: $tableId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_STRING, + filter: APP_DATABASE_ATTRIBUTE_ENUM, + default: $default, + required: $required, + elements: $elements, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_ENUM); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php new file mode 100644 index 0000000000..0782f8eb29 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php @@ -0,0 +1,123 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/float') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/float') + ->desc('Create float column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'createFloatColumn', + description: '/docs/references/databases/create-float-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: UtopiaResponse::MODEL_ATTRIBUTE_FLOAT, + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('min', null, new FloatValidator(), 'Minimum value', true) + ->param('max', null, new FloatValidator(), 'Maximum value', true) + ->param('default', null, new FloatValidator(), 'Default value. Cannot be set when required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?float $min, + ?float $max, + ?float $default, + bool $array, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $min ??= -INF; + $max ??= INF; + + if ($min > $max) { + throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum must be less than or equal to maximum'); + } + + $validator = new Range($min, $max, Database::VAR_FLOAT); + if (!\is_null($default) && !$validator->isValid($default)) { + throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); + } + + $column = $this->createColumn($databaseId, $tableId, new Document([ + 'key' => $key, + 'type' => Database::VAR_FLOAT, + 'size' => 0, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'format' => APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, + 'formatOptions' => ['min' => $min, 'max' => $max], + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + + $formatOptions = $column->getAttribute('formatOptions', []); + if (!empty($formatOptions)) { + $column->setAttribute('min', \floatval($formatOptions['min'])); + $column->setAttribute('max', \floatval($formatOptions['max'])); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_FLOAT); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php new file mode 100644 index 0000000000..c585205388 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php @@ -0,0 +1,109 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/float/:key') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/float/:key') + ->desc('Update float column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'updateFloatColumn', + description: '/docs/references/databases/update-float-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_ATTRIBUTE_FLOAT, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('min', null, new FloatValidator(), 'Minimum value', true) + ->param('max', null, new FloatValidator(), 'Maximum value', true) + ->param('default', null, new Nullable(new FloatValidator()), 'Default value. Cannot be set when required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?float $min, + ?float $max, + ?float $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $column = $this->updateColumn( + databaseId: $databaseId, + tableId: $tableId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_FLOAT, + default: $default, + required: $required, + min: $min, + max: $max, + newKey: $newKey + ); + + $formatOptions = $column->getAttribute('formatOptions', []); + if (!empty($formatOptions)) { + $column->setAttribute('min', \floatval($formatOptions['min'])); + $column->setAttribute('max', \floatval($formatOptions['max'])); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_FLOAT); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php new file mode 100644 index 0000000000..14744f0442 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php @@ -0,0 +1,112 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/:key') + ->desc('Get column') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'getColumn', + description: '/docs/references/databases/get-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: [ + UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN, + UtopiaResponse::MODEL_ATTRIBUTE_INTEGER, + UtopiaResponse::MODEL_ATTRIBUTE_FLOAT, + UtopiaResponse::MODEL_ATTRIBUTE_EMAIL, + UtopiaResponse::MODEL_ATTRIBUTE_ENUM, + UtopiaResponse::MODEL_ATTRIBUTE_URL, + UtopiaResponse::MODEL_ATTRIBUTE_IP, + UtopiaResponse::MODEL_ATTRIBUTE_DATETIME, + UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP, + UtopiaResponse::MODEL_ATTRIBUTE_STRING, + ] + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $column = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $table->getInternalId() . '_' . $key); + if ($column->isEmpty()) { + throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + } + + $type = $column->getAttribute('type'); + $format = $column->getAttribute('format'); + $options = $column->getAttribute('options', []); + + foreach ($options as $optKey => $optValue) { + $column->setAttribute($optKey, $optValue); + } + + $model = match ($type) { + Database::VAR_BOOLEAN => UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN, + Database::VAR_INTEGER => UtopiaResponse::MODEL_ATTRIBUTE_INTEGER, + Database::VAR_FLOAT => UtopiaResponse::MODEL_ATTRIBUTE_FLOAT, + Database::VAR_DATETIME => UtopiaResponse::MODEL_ATTRIBUTE_DATETIME, + Database::VAR_RELATIONSHIP => UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP, + Database::VAR_STRING => match ($format) { + APP_DATABASE_ATTRIBUTE_EMAIL => UtopiaResponse::MODEL_ATTRIBUTE_EMAIL, + APP_DATABASE_ATTRIBUTE_ENUM => UtopiaResponse::MODEL_ATTRIBUTE_ENUM, + APP_DATABASE_ATTRIBUTE_IP => UtopiaResponse::MODEL_ATTRIBUTE_IP, + APP_DATABASE_ATTRIBUTE_URL => UtopiaResponse::MODEL_ATTRIBUTE_URL, + default => UtopiaResponse::MODEL_ATTRIBUTE_STRING, + }, + default => UtopiaResponse::MODEL_ATTRIBUTE, + }; + + $response->dynamic($column, $model); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php new file mode 100644 index 0000000000..b3916a5fad --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php @@ -0,0 +1,96 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/ip') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/ip') + ->desc('Create IP address column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'createIpColumn', + description: '/docs/references/databases/create-ip-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: UtopiaResponse::MODEL_ATTRIBUTE_IP, + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new IP(), 'Default value. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?string $default, + bool $array, + \Appwrite\Utopia\Response $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $column = $this->createColumn($databaseId, $tableId, new Document([ + 'key' => $key, + 'type' => Database::VAR_STRING, + 'size' => 39, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'format' => APP_DATABASE_ATTRIBUTE_IP, + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_IP); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php new file mode 100644 index 0000000000..6da08a2c9f --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php @@ -0,0 +1,98 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/ip/:key') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/ip/:key') + ->desc('Update IP address column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'updateIpColumn', + description: '/docs/references/databases/update-ip-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_ATTRIBUTE_IP, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Nullable(new IP()), 'Default value. Cannot be set when column is required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?string $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $column = $this->updateColumn( + databaseId: $databaseId, + tableId: $tableId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_STRING, + filter: APP_DATABASE_ATTRIBUTE_IP, + default: $default, + required: $required, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_IP); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php new file mode 100644 index 0000000000..7a26d10bc8 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php @@ -0,0 +1,123 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/integer') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/integer') + ->desc('Create integer column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'createIntegerColumn', + description: '/docs/references/databases/create-integer-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: UtopiaResponse::MODEL_ATTRIBUTE_INTEGER, + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('min', null, new Integer(), 'Minimum value', true) + ->param('max', null, new Integer(), 'Maximum value', true) + ->param('default', null, new Integer(), 'Default value. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?int $min, + ?int $max, + ?int $default, + bool $array, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $min ??= \PHP_INT_MIN; + $max ??= \PHP_INT_MAX; + + if ($min > $max) { + throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); + } + + $validator = new Range($min, $max, Database::VAR_INTEGER); + if (!\is_null($default) && !$validator->isValid($default)) { + throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); + } + + $size = $max > 2147483647 ? 8 : 4; + + $column = $this->createColumn($databaseId, $tableId, new Document([ + 'key' => $key, + 'type' => Database::VAR_INTEGER, + 'size' => $size, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'format' => APP_DATABASE_ATTRIBUTE_INT_RANGE, + 'formatOptions' => ['min' => $min, 'max' => $max], + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + + $formatOptions = $column->getAttribute('formatOptions', []); + if (!empty($formatOptions)) { + $column->setAttribute('min', \intval($formatOptions['min'])); + $column->setAttribute('max', \intval($formatOptions['max'])); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_INTEGER); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php new file mode 100644 index 0000000000..27616c07c9 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php @@ -0,0 +1,109 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/integer/:key') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/integer/:key') + ->desc('Update integer column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'updateIntegerColumn', + description: '/docs/references/databases/update-integer-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_ATTRIBUTE_INTEGER, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('min', null, new Integer(), 'Minimum value', true) + ->param('max', null, new Integer(), 'Maximum value', true) + ->param('default', null, new Nullable(new Integer()), 'Default value. Cannot be set when column is required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?int $min, + ?int $max, + ?int $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $column = $this->updateColumn( + databaseId: $databaseId, + tableId: $tableId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_INTEGER, + default: $default, + required: $required, + min: $min, + max: $max, + newKey: $newKey + ); + + $formatOptions = $column->getAttribute('formatOptions', []); + if (!empty($formatOptions)) { + $column->setAttribute('min', \intval($formatOptions['min'])); + $column->setAttribute('max', \intval($formatOptions['max'])); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_INTEGER); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php new file mode 100644 index 0000000000..32cb235b62 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php @@ -0,0 +1,168 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/relationship') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/relationship') + ->desc('Create relationship column') + ->groups(['api', 'database']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'createRelationshipColumn', + description: '/docs/references/databases/create-relationship-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('relatedTableId', '', new UID(), 'Related Table ID.') + ->param('type', '', new WhiteList([ + Database::RELATION_ONE_TO_ONE, + Database::RELATION_MANY_TO_ONE, + Database::RELATION_MANY_TO_MANY, + Database::RELATION_ONE_TO_MANY + ], true), 'Relation type') + ->param('twoWay', false, new Boolean(), 'Is Two Way?', true) + ->param('key', null, new Key(), 'Column Key.', true) + ->param('twoWayKey', null, new Key(), 'Two Way Column Key.', true) + ->param('onDelete', Database::RELATION_MUTATE_RESTRICT, new WhiteList([ + Database::RELATION_MUTATE_CASCADE, + Database::RELATION_MUTATE_RESTRICT, + Database::RELATION_MUTATE_SET_NULL + ], true), 'Constraints option', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $relatedTableId, + string $type, + bool $twoWay, + ?string $key, + ?string $twoWayKey, + string $onDelete, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $key ??= $relatedTableId; + $twoWayKey ??= $tableId; + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId()); + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $relatedTableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId); + $relatedTable = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $relatedTableDocument->getInternalId()); + if ($relatedTable->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $columns = $table->getAttribute('attributes', []); + foreach ($columns as $column) { + if ($column->getAttribute('type') !== Database::VAR_RELATIONSHIP) { + continue; + } + + if (\strtolower($column->getId()) === \strtolower($key)) { + throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); + } + + if ( + \strtolower($column->getAttribute('options')['twoWayKey']) === \strtolower($twoWayKey) && + $column->getAttribute('options')['relatedCollection'] === $relatedTable->getId() + ) { + throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Attribute with the requested key already exists. Attribute keys must be unique.'); + } + + if ( + $type === Database::RELATION_MANY_TO_MANY && + $column->getAttribute('options')['relationType'] === Database::RELATION_MANY_TO_MANY && + $column->getAttribute('options')['relatedCollection'] === $relatedTable->getId() + ) { + throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Only one "manyToMany" relationship per table is allowed.'); + } + } + + $column = $this->createColumn($databaseId, $tableId, new Document([ + 'key' => $key, + 'type' => Database::VAR_RELATIONSHIP, + 'size' => 0, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + 'options' => [ + 'relatedCollection' => $relatedTableId, + 'relationType' => $type, + 'twoWay' => $twoWay, + 'twoWayKey' => $twoWayKey, + 'onDelete' => $onDelete, + ] + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + + foreach ($column->getAttribute('options', []) as $k => $option) { + $column->setAttribute($k, $option); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php new file mode 100644 index 0000000000..34231ad611 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php @@ -0,0 +1,103 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key/relationship') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/:key/relationship') + ->desc('Update relationship column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'updateRelationshipColumn', + description: '/docs/references/databases/update-relationship-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('onDelete', null, new WhiteList([ + Database::RELATION_MUTATE_CASCADE, + Database::RELATION_MUTATE_RESTRICT, + Database::RELATION_MUTATE_SET_NULL + ], true), 'Constraints option', true) + ->param('newKey', null, new Key(), 'New Column Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?string $onDelete, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $column = $this->updateColumn( + $databaseId, + $tableId, + $key, + $dbForProject, + $queueForEvents, + type: Database::VAR_RELATIONSHIP, + required: false, + options: [ + 'onDelete' => $onDelete + ], + newKey: $newKey + ); + + foreach ($column->getAttribute('options', []) as $k => $option) { + $column->setAttribute($k, $option); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php new file mode 100644 index 0000000000..1987f5fdbe --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php @@ -0,0 +1,122 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/string') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/string') + ->desc('Create string column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'createStringColumn', + description: '/docs/references/databases/create-string-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: UtopiaResponse::MODEL_ATTRIBUTE_STRING + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('size', null, new Range(1, APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH, Validator::TYPE_INTEGER), 'Attribute size for text attributes, in number of characters.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Text(0, 0), 'Default value for column when not provided. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) + ->param('encrypt', false, new Boolean(), 'Toggle encryption for the column. Encryption enhances security by not storing any plain text values in the database. However, encrypted columns cannot be queried.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?int $size, + ?bool $required, + ?string $default, + bool $array, + bool $encrypt, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + // Ensure default fits in the given size + $validator = new Text($size, 0); + if (!is_null($default) && !$validator->isValid($default)) { + throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); + } + + $filters = []; + if ($encrypt) { + $filters[] = 'encrypt'; + } + + $column = $this->createColumn( + $databaseId, + $tableId, + new Document([ + 'key' => $key, + 'type' => Database::VAR_STRING, + 'size' => $size, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'filters' => $filters, + ]), + $response, + $dbForProject, + $queueForDatabase, + $queueForEvents + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_STRING); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php new file mode 100644 index 0000000000..a73ae0f9b1 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php @@ -0,0 +1,101 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/string/:key') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/string/:key') + ->desc('Update string column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'updateStringColumn', + description: '/docs/references/databases/update-string-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_ATTRIBUTE_STRING, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Nullable(new Text(0, 0)), 'Default value for column when not provided. Cannot be set when column is required.') + ->param('size', null, new Range(1, APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH, Validator::TYPE_INTEGER), 'Maximum size of the string attribute.', true) + ->param('newKey', null, new Key(), 'New Column Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?string $default, + ?int $size, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $column = $this->updateColumn( + databaseId: $databaseId, + tableId: $tableId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_STRING, + size: $size, + default: $default, + required: $required, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_STRING); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php new file mode 100644 index 0000000000..74eedfa98b --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php @@ -0,0 +1,96 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/url') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/url') + ->desc('Create URL column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') + ->label('audits.event', 'column.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'createUrlColumn', + description: '/docs/references/databases/create-url-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: UtopiaResponse::MODEL_ATTRIBUTE_URL, + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new URL(), 'Default value for column when not provided. Cannot be set when column is required.', true) + ->param('array', false, new Boolean(), 'Is column an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?string $default, + bool $array, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $column = $this->createColumn($databaseId, $tableId, new Document([ + 'key' => $key, + 'type' => Database::VAR_STRING, + 'size' => 2000, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'format' => APP_DATABASE_ATTRIBUTE_URL, + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_URL); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php new file mode 100644 index 0000000000..109b9c575b --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php @@ -0,0 +1,98 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/url/:key') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/url/:key') + ->desc('Update URL column') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') + ->label('audits.event', 'column.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'updateUrlColumn', + description: '/docs/references/databases/update-url-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_ATTRIBUTE_URL, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->param('required', null, new Boolean(), 'Is column required?') + ->param('default', null, new Nullable(new URL()), 'Default value for column when not provided. Cannot be set when column is required.') + ->param('newKey', null, new Key(), 'New Column Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?string $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $column = $this->updateColumn( + $databaseId, + $tableId, + $key, + $dbForProject, + $queueForEvents, + type: Database::VAR_STRING, + filter: APP_DATABASE_ATTRIBUTE_URL, + default: $default, + required: $required, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_URL); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php new file mode 100644 index 0000000000..f2343e927b --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php @@ -0,0 +1,125 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes') + ->desc('List columns') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'listColumns', + description: '/docs/references/databases/list-attributes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_ATTRIBUTE_LIST + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $queries = Query::parseQueries($queries); + + \array_push( + $queries, + Query::equal('databaseInternalId', [$database->getInternalId()]), + Query::equal('collectionInternalId', [$table->getInternalId()]) + ); + + $cursor = \array_filter( + $queries, + fn ($query) => \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]) + ); + $cursor = \reset($cursor); + + if ($cursor) { + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $columnId = $cursor->getValue(); + $cursorDocument = Authorization::skip( + fn () => $dbForProject->find('attributes', [ + Query::equal('databaseInternalId', [$database->getInternalId()]), + Query::equal('collectionInternalId', [$table->getInternalId()]), + Query::equal('key', [$columnId]), + Query::limit(1), + ]) + ); + + if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Column '{$columnId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument[0]); + } + + $filters = Query::groupByType($queries)['filters']; + + try { + $columns = $dbForProject->find('attributes', $queries); + $total = $dbForProject->count('attributes', $filters, APP_LIMIT_COUNT); + } catch (OrderException $e) { + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); + } + + $response->dynamic(new Document([ + 'attributes' => $columns, + 'total' => $total, + ]), UtopiaResponse::MODEL_ATTRIBUTE_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Module.php b/src/Appwrite/Platform/Modules/Databases/Module.php new file mode 100644 index 0000000000..f8686999dd --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Module.php @@ -0,0 +1,16 @@ +addService('http', new Http()); + $this->addService('workers', new Workers()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Http.php b/src/Appwrite/Platform/Modules/Databases/Services/Http.php new file mode 100644 index 0000000000..1cd482d61a --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Services/Http.php @@ -0,0 +1,110 @@ +type = Service::TYPE_HTTP; + + $this->registerDatabaseActions(); + $this->registerTableActions(); + $this->registerColumnActions(); + $this->registerIndexActions(); + $this->registerRowActions(); + } + + private function registerDatabaseActions() + { + + } + + private function registerTableActions() + { + + } + + private function registerColumnActions(): void + { + // Column top level actions + $this->addAction(GetColumn::getName(), new GetColumn()); + $this->addAction(DeleteColumn::getName(), new DeleteColumn()); + $this->addAction(ListColumns::getName(), new ListColumns()); + + // Column: Boolean + $this->addAction(CreateBoolean::getName(), new CreateBoolean()); + $this->addAction(UpdateBoolean::getName(), new UpdateBoolean()); + + // Column: Datetime + $this->addAction(CreateDatetime::getName(), new CreateDatetime()); + $this->addAction(UpdateDatetime::getName(), new UpdateDatetime()); + + // Column: Email + $this->addAction(CreateEmail::getName(), new CreateEmail()); + $this->addAction(UpdateEmail::getName(), new UpdateEmail()); + + // Column: Enum + $this->addAction(CreateEnum::getName(), new CreateEnum()); + $this->addAction(UpdateEnum::getName(), new UpdateEnum()); + + // Column: Float + $this->addAction(CreateFloat::getName(), new CreateFloat()); + $this->addAction(UpdateFloat::getName(), new UpdateFloat()); + + // Column: Integer + $this->addAction(CreateInteger::getName(), new CreateInteger()); + $this->addAction(UpdateInteger::getName(), new UpdateInteger()); + + // Column: IP + $this->addAction(CreateIP::getName(), new CreateIP()); + $this->addAction(UpdateIP::getName(), new UpdateIP()); + + // Column: Relationship + $this->addAction(CreateRelationship::getName(), new CreateRelationship()); + $this->addAction(UpdateRelationship::getName(), new UpdateRelationship()); + + // Column: String + $this->addAction(CreateString::getName(), new CreateString()); + $this->addAction(UpdateString::getName(), new UpdateString()); + + // Column: URL + $this->addAction(CreateURL::getName(), new CreateURL()); + $this->addAction(UpdateURL::getName(), new UpdateURL()); + } + + private function registerIndexActions() + { + + } + + private function registerRowActions() + { + + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Workers.php b/src/Appwrite/Platform/Modules/Databases/Services/Workers.php new file mode 100644 index 0000000000..55388ea7ff --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Services/Workers.php @@ -0,0 +1,15 @@ +type = Service::TYPE_WORKER; + $this->addAction(Databases::getName(), new Databases()); + } +} diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php similarity index 99% rename from src/Appwrite/Platform/Workers/Databases.php rename to src/Appwrite/Platform/Modules/Databases/Workers/Databases.php index 1f3b76d6eb..6564239630 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php @@ -1,6 +1,6 @@ addAction(Audits::getName(), new Audits()) ->addAction(Certificates::getName(), new Certificates()) - ->addAction(Databases::getName(), new Databases()) ->addAction(Deletes::getName(), new Deletes()) ->addAction(Functions::getName(), new Functions()) ->addAction(Mails::getName(), new Mails()) From 9c1ec6fe029497803854509b3bf4351c74ad2893 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 13:37:25 +0530 Subject: [PATCH 028/343] update: move the init hook. --- app/controllers/api/databases.php | 12 ------------ app/controllers/general.php | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 33b839fc41..6b19c96be6 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -50,18 +50,6 @@ use Utopia\Validator\JSON; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; -App::init() - ->groups(['api', 'database']) - ->inject('request') - ->inject('dbForProject') - ->action(function (Request $request, Database $dbForProject) { - $timeout = \intval($request->getHeader('x-appwrite-timeout')); - - if (!empty($timeout) && App::isDevelopment()) { - $dbForProject->setTimeout($timeout); - } - }); - App::post('/v1/databases') ->desc('Create database') ->groups(['api', 'database']) diff --git a/app/controllers/general.php b/app/controllers/general.php index fdef1e9cee..32323d6e05 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1576,6 +1576,20 @@ foreach (Config::getParam('services', []) as $service) { } } +// legacy controller init hooks as the endpoint controller logic is now moved to a module structure. +// 1. databases +App::init() + ->groups(['api', 'database']) + ->inject('request') + ->inject('dbForProject') + ->action(function (Request $request, Database $dbForProject) { + $timeout = \intval($request->getHeader('x-appwrite-timeout')); + + if (!empty($timeout) && App::isDevelopment()) { + $dbForProject->setTimeout($timeout); + } + }); + // Check for any errors found while we were initialising the SDK Methods. if (!empty(Method::getErrors())) { throw new \Exception('Errors found during SDK initialization:' . PHP_EOL . implode(PHP_EOL, Method::getErrors())); From 1945a64083bd9fc261ad3fb3e1f006180a927ff2 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 14:08:10 +0530 Subject: [PATCH 029/343] update: move DB ops to module. --- app/controllers/api/databases.php | 389 ------------------ .../Databases/Http/Databases/Create.php | 123 ++++++ .../Databases/Http/Databases/Delete.php | 88 ++++ .../Modules/Databases/Http/Databases/Get.php | 65 +++ .../Databases/Http/Databases/Logs/XList.php | 143 +++++++ .../Databases/Http/Databases/Update.php | 81 ++++ .../Databases/Http/Databases/XList.php | 107 +++++ .../Modules/Databases/Services/Http.php | 21 +- 8 files changed, 623 insertions(+), 394 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Get.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 6b19c96be6..dd181f8894 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -12,9 +12,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Collections; -use Appwrite\Utopia\Database\Validator\Queries\Databases; use Appwrite\Utopia\Database\Validator\Queries\Indexes; -use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use MaxMind\Db\Reader; use Utopia\App; @@ -50,393 +48,6 @@ use Utopia\Validator\JSON; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; -App::post('/v1/databases') - ->desc('Create database') - ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].create') - ->label('scope', 'databases.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'database.create') - ->label('audits.resource', 'database/{response.$id}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'databases', - name: 'create', - description: '/docs/references/databases/create.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_CREATED, - model: Response::MODEL_DATABASE, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('name', '', new Text(128), 'Database name. Max length: 128 chars.') - ->param('enabled', true, new Boolean(), 'Is the database enabled? When set to \'disabled\', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $name, bool $enabled, Response $response, Database $dbForProject, Event $queueForEvents) { - - $databaseId = $databaseId == 'unique()' ? ID::unique() : $databaseId; - - try { - $dbForProject->createDocument('databases', new Document([ - '$id' => $databaseId, - 'name' => $name, - 'enabled' => $enabled, - 'search' => implode(' ', [$databaseId, $name]), - ])); - $database = $dbForProject->getDocument('databases', $databaseId); - - $collections = (Config::getParam('collections', [])['databases'] ?? [])['collections'] ?? []; - if (empty($collections)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'The "collections" collection is not configured.'); - } - - $attributes = []; - $indexes = []; - - foreach ($collections['attributes'] as $attribute) { - $attributes[] = new Document([ - '$id' => $attribute['$id'], - 'type' => $attribute['type'], - 'size' => $attribute['size'], - 'required' => $attribute['required'], - 'signed' => $attribute['signed'], - 'array' => $attribute['array'], - 'filters' => $attribute['filters'], - 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '' - ]); - } - - foreach ($collections['indexes'] as $index) { - $indexes[] = new Document([ - '$id' => $index['$id'], - 'type' => $index['type'], - 'attributes' => $index['attributes'], - 'lengths' => $index['lengths'], - 'orders' => $index['orders'], - ]); - } - $dbForProject->createCollection('database_' . $database->getInternalId(), $attributes, $indexes); - } catch (DuplicateException) { - throw new Exception(Exception::DATABASE_ALREADY_EXISTS); - } - - $queueForEvents->setParam('databaseId', $database->getId()); - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($database, Response::MODEL_DATABASE); - }); - -App::get('/v1/databases') - ->desc('List databases') - ->groups(['api', 'database']) - ->label('scope', 'databases.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: 'databases', - name: 'list', - description: '/docs/references/databases/list.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_DATABASE_LIST, - ) - ], - contentType: ContentType::JSON - )) - ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Databases::ALLOWED_ATTRIBUTES), true) - ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->inject('response') - ->inject('dbForProject') - ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { - $queries = Query::parseQueries($queries); - - if (!empty($search)) { - $queries[] = Query::search('search', $search); - } - - /** - * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries - */ - $cursor = \array_filter($queries, function ($query) { - return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); - }); - $cursor = reset($cursor); - if ($cursor) { - /** @var Query $cursor */ - - $validator = new Cursor(); - if (!$validator->isValid($cursor)) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); - } - - $databaseId = $cursor->getValue(); - $cursorDocument = $dbForProject->getDocument('databases', $databaseId); - - if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Database '{$databaseId}' for the 'cursor' value not found."); - } - - $cursor->setValue($cursorDocument); - } - - $filterQueries = Query::groupByType($queries)['filters']; - - try { - $databases = $dbForProject->find('databases', $queries); - $total = $dbForProject->count('databases', $filterQueries, APP_LIMIT_COUNT); - } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); - } - $response->dynamic(new Document([ - 'databases' => $databases, - 'total' => $total, - ]), Response::MODEL_DATABASE_LIST); - }); - -App::get('/v1/databases/:databaseId') - ->desc('Get database') - ->groups(['api', 'database']) - ->label('scope', 'databases.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: 'databases', - name: 'get', - description: '/docs/references/databases/get.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_DATABASE, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->inject('response') - ->inject('dbForProject') - ->action(function (string $databaseId, Response $response, Database $dbForProject) { - - $database = $dbForProject->getDocument('databases', $databaseId); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $response->dynamic($database, Response::MODEL_DATABASE); - }); - -App::get('/v1/databases/:databaseId/logs') - ->desc('List database logs') - ->groups(['api', 'database']) - ->label('scope', 'databases.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: 'logs', - name: 'listLogs', - description: '/docs/references/databases/get-logs.md', - auth: [AuthType::ADMIN], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_LOG_LIST, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->inject('response') - ->inject('dbForProject') - ->inject('locale') - ->inject('geodb') - ->action(function (string $databaseId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { - - $database = $dbForProject->getDocument('databases', $databaseId); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } - - // Temp fix for logs - $queries[] = Query::or([ - Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), - Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), - ]); - - $audit = new Audit($dbForProject); - $resource = 'database/' . $databaseId; - $logs = $audit->getLogsByResource($resource, $queries); - - $output = []; - - foreach ($logs as $i => &$log) { - $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; - - $detector = new Detector($log['userAgent']); - $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) - - $os = $detector->getOS(); - $client = $detector->getClient(); - $device = $detector->getDevice(); - - $output[$i] = new Document([ - 'event' => $log['event'], - 'userId' => ID::custom($log['data']['userId']), - 'userEmail' => $log['data']['userEmail'] ?? null, - 'userName' => $log['data']['userName'] ?? null, - 'mode' => $log['data']['mode'] ?? null, - 'ip' => $log['ip'], - 'time' => $log['time'], - 'osCode' => $os['osCode'], - 'osName' => $os['osName'], - 'osVersion' => $os['osVersion'], - 'clientType' => $client['clientType'], - 'clientCode' => $client['clientCode'], - 'clientName' => $client['clientName'], - 'clientVersion' => $client['clientVersion'], - 'clientEngine' => $client['clientEngine'], - 'clientEngineVersion' => $client['clientEngineVersion'], - 'deviceName' => $device['deviceName'], - 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'] - ]); - - $record = $geodb->get($log['ip']); - - if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); - } else { - $output[$i]['countryCode'] = '--'; - $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); - } - } - - $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource, $queries), - 'logs' => $output, - ]), Response::MODEL_LOG_LIST); - }); - - -App::put('/v1/databases/:databaseId') - ->desc('Update database') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'databases.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].update') - ->label('audits.event', 'database.update') - ->label('audits.resource', 'database/{response.$id}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'databases', - name: 'update', - description: '/docs/references/databases/update.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_DATABASE, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('name', null, new Text(128), 'Database name. Max length: 128 chars.') - ->param('enabled', true, new Boolean(), 'Is database enabled? When set to \'disabled\', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $name, bool $enabled, Response $response, Database $dbForProject, Event $queueForEvents) { - - $database = $dbForProject->getDocument('databases', $databaseId); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $database = $dbForProject->updateDocument('databases', $databaseId, $database - ->setAttribute('name', $name) - ->setAttribute('enabled', $enabled) - ->setAttribute('search', implode(' ', [$databaseId, $name]))); - - $queueForEvents->setParam('databaseId', $database->getId()); - - $response->dynamic($database, Response::MODEL_DATABASE); - }); - -App::delete('/v1/databases/:databaseId') - ->desc('Delete database') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'databases.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].delete') - ->label('audits.event', 'database.delete') - ->label('audits.resource', 'database/{request.databaseId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'databases', - name: 'delete', - description: '/docs/references/databases/delete.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_NOCONTENT, - model: Response::MODEL_NONE, - ) - ], - contentType: ContentType::NONE - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->inject('queueForStatsUsage') - ->action(function (string $databaseId, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, StatsUsage $queueForStatsUsage) { - - $database = $dbForProject->getDocument('databases', $databaseId); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - if (!$dbForProject->deleteDocument('databases', $databaseId)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); - } - - $dbForProject->purgeCachedDocument('databases', $database->getId()); - $dbForProject->purgeCachedCollection('databases_' . $database->getInternalId()); - - $queueForDatabase - ->setType(DATABASE_TYPE_DELETE_DATABASE) - ->setDatabase($database); - - $queueForEvents - ->setParam('databaseId', $database->getId()) - ->setPayload($response->output($database, Response::MODEL_DATABASE)); - - $response->noContent(); - }); - App::post('/v1/databases/:databaseId/tables') ->alias('/v1/databases/:databaseId/collections') ->desc('Create table') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php new file mode 100644 index 0000000000..a734cbdd22 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php @@ -0,0 +1,123 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases') + ->desc('Create database') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].create') + ->label('scope', 'databases.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'database.create') + ->label('audits.resource', 'database/{response.$id}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'databases', + name: 'create', + description: '/docs/references/databases/create.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_CREATED, + model: UtopiaResponse::MODEL_DATABASE, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('name', '', new Text(128), 'Database name. Max length: 128 chars.') + ->param('enabled', true, new Boolean(), 'Is the database enabled? When set to \'disabled\', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $name, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { + $databaseId = $databaseId == 'unique()' ? ID::unique() : $databaseId; + + try { + $dbForProject->createDocument('databases', new Document([ + '$id' => $databaseId, + 'name' => $name, + 'enabled' => $enabled, + 'search' => implode(' ', [$databaseId, $name]), + ])); + $database = $dbForProject->getDocument('databases', $databaseId); + + $collections = (Config::getParam('collections', [])['databases'] ?? [])['collections'] ?? []; + if (empty($collections)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'The "collections" collection is not configured.'); + } + + $attributes = []; + $indexes = []; + + foreach ($collections['attributes'] as $attribute) { + $attributes[] = new Document([ + '$id' => $attribute['$id'], + 'type' => $attribute['type'], + 'size' => $attribute['size'], + 'required' => $attribute['required'], + 'signed' => $attribute['signed'], + 'array' => $attribute['array'], + 'filters' => $attribute['filters'], + 'default' => $attribute['default'] ?? null, + 'format' => $attribute['format'] ?? '' + ]); + } + + foreach ($collections['indexes'] as $index) { + $indexes[] = new Document([ + '$id' => $index['$id'], + 'type' => $index['type'], + 'attributes' => $index['attributes'], + 'lengths' => $index['lengths'], + 'orders' => $index['orders'], + ]); + } + $dbForProject->createCollection('database_' . $database->getInternalId(), $attributes, $indexes); + } catch (DuplicateException) { + throw new Exception(Exception::DATABASE_ALREADY_EXISTS); + } + + $queueForEvents->setParam('databaseId', $database->getId()); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) + ->dynamic($database, UtopiaResponse::MODEL_DATABASE); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php new file mode 100644 index 0000000000..e0651b5e5b --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php @@ -0,0 +1,88 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/databases/:databaseId') + ->desc('Delete database') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'databases.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].delete') + ->label('audits.event', 'database.delete') + ->label('audits.resource', 'database/{request.databaseId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'databases', + name: 'delete', + description: '/docs/references/databases/delete.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_NOCONTENT, + model: UtopiaResponse::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { + $database = $dbForProject->getDocument('databases', $databaseId); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + if (!$dbForProject->deleteDocument('databases', $databaseId)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); + } + + $dbForProject->purgeCachedDocument('databases', $database->getId()); + $dbForProject->purgeCachedCollection('databases_' . $database->getInternalId()); + + $queueForDatabase + ->setType(DATABASE_TYPE_DELETE_DATABASE) + ->setDatabase($database); + + $queueForEvents + ->setParam('databaseId', $database->getId()) + ->setPayload($response->output($database, UtopiaResponse::MODEL_DATABASE)); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Get.php new file mode 100644 index 0000000000..67b61bceb2 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Get.php @@ -0,0 +1,65 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId') + ->desc('Get database') + ->groups(['api', 'database']) + ->label('scope', 'databases.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'databases', + name: 'get', + description: '/docs/references/databases/get.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_DATABASE, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, UtopiaResponse $response, Database $dbForProject): void + { + $database = $dbForProject->getDocument('databases', $databaseId); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $response->dynamic($database, UtopiaResponse::MODEL_DATABASE); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php new file mode 100644 index 0000000000..56358aa723 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php @@ -0,0 +1,143 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/logs') + ->desc('List database logs') + ->groups(['api', 'database']) + ->label('scope', 'databases.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'logs', + name: 'listLogs', + description: '/docs/references/databases/get-logs.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_LOG_LIST, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) + ->inject('response') + ->inject('dbForProject') + ->inject('locale') + ->inject('geodb') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void + { + $database = $dbForProject->getDocument('databases', $databaseId); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); + + $audit = new Audit($dbForProject); + $resource = 'database/' . $databaseId; + $logs = $audit->getLogsByResource($resource, $queries); + + $output = []; + + foreach ($logs as $i => &$log) { + $log['userAgent'] = $log['userAgent'] ?: 'UNKNOWN'; + $detector = new Detector($log['userAgent']); + $detector->skipBotDetection(); + + $os = $detector->getOS(); + $client = $detector->getClient(); + $device = $detector->getDevice(); + + $output[$i] = new Document([ + 'event' => $log['event'], + 'userId' => ID::custom($log['data']['userId']), + 'userEmail' => $log['data']['userEmail'] ?? null, + 'userName' => $log['data']['userName'] ?? null, + 'mode' => $log['data']['mode'] ?? null, + 'ip' => $log['ip'], + 'time' => $log['time'], + 'osCode' => $os['osCode'], + 'osName' => $os['osName'], + 'osVersion' => $os['osVersion'], + 'clientType' => $client['clientType'], + 'clientCode' => $client['clientCode'], + 'clientName' => $client['clientName'], + 'clientVersion' => $client['clientVersion'], + 'clientEngine' => $client['clientEngine'], + 'clientEngineVersion' => $client['clientEngineVersion'], + 'deviceName' => $device['deviceName'], + 'deviceBrand' => $device['deviceBrand'], + 'deviceModel' => $device['deviceModel'], + ]); + + $record = $geodb->get($log['ip']); + if ($record) { + $countryCode = strtolower($record['country']['iso_code']); + $output[$i]['countryCode'] = $locale->getText("countries.{$countryCode}", false) ? $countryCode : '--'; + $output[$i]['countryName'] = $locale->getText("countries.{$countryCode}", $locale->getText('locale.country.unknown')); + } else { + $output[$i]['countryCode'] = '--'; + $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); + } + } + + $response->dynamic(new Document([ + 'total' => $audit->countLogsByResource($resource, $queries), + 'logs' => $output, + ]), UtopiaResponse::MODEL_LOG_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Update.php new file mode 100644 index 0000000000..49c92a65a2 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Update.php @@ -0,0 +1,81 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) + ->setHttpPath('/v1/databases/:databaseId') + ->desc('Update database') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'databases.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].update') + ->label('audits.event', 'database.update') + ->label('audits.resource', 'database/{response.$id}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'databases', + name: 'update', + description: '/docs/references/databases/update.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_DATABASE, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('name', null, new Text(128), 'Database name. Max length: 128 chars.') + ->param('enabled', true, new Boolean(), 'Is database enabled? When set to \'disabled\', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $name, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { + $database = $dbForProject->getDocument('databases', $databaseId); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $database = $dbForProject->updateDocument('databases', $databaseId, $database + ->setAttribute('name', $name) + ->setAttribute('enabled', $enabled) + ->setAttribute('search', implode(' ', [$databaseId, $name]))); + + $queueForEvents->setParam('databaseId', $database->getId()); + + $response->dynamic($database, UtopiaResponse::MODEL_DATABASE); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php new file mode 100644 index 0000000000..7453fb39f4 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php @@ -0,0 +1,107 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases') + ->desc('List databases') + ->groups(['api', 'database']) + ->label('scope', 'databases.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'databases', + name: 'list', + description: '/docs/references/databases/list.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_DATABASE_LIST, + ) + ], + contentType: ContentType::JSON + )) + ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Databases::ALLOWED_ATTRIBUTES), true) + ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(array $queries, string $search, UtopiaResponse $response, Database $dbForProject): void + { + $queries = Query::parseQueries($queries); + + if (!empty($search)) { + $queries[] = Query::search('search', $search); + } + + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + $cursor = reset($cursor); + if ($cursor) { + /** @var Query $cursor */ + + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $databaseId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('databases', $databaseId); + + if ($cursorDocument->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Database '{$databaseId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + + $filterQueries = Query::groupByType($queries)['filters']; + + try { + $databases = $dbForProject->find('databases', $queries); + $total = $dbForProject->count('databases', $filterQueries, APP_LIMIT_COUNT); + } catch (OrderException $e) { + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); + } + $response->dynamic(new Document([ + 'databases' => $databases, + 'total' => $total, + ]), UtopiaResponse::MODEL_DATABASE_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Http.php b/src/Appwrite/Platform/Modules/Databases/Services/Http.php index 1cd482d61a..de0de71e05 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Http.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Http.php @@ -25,6 +25,12 @@ use Appwrite\Platform\Modules\Databases\Http\Columns\String\Update as UpdateStri use Appwrite\Platform\Modules\Databases\Http\Columns\URL\Create as CreateURL; use Appwrite\Platform\Modules\Databases\Http\Columns\URL\Update as UpdateURL; use Appwrite\Platform\Modules\Databases\Http\Columns\XList as ListColumns; +use Appwrite\Platform\Modules\Databases\Http\Databases\Create as CreateDatabase; +use Appwrite\Platform\Modules\Databases\Http\Databases\Delete as DeleteDatabase; +use Appwrite\Platform\Modules\Databases\Http\Databases\Get as GetDatabase; +use Appwrite\Platform\Modules\Databases\Http\Databases\Logs\XList as ListDatabaseLogs; +use Appwrite\Platform\Modules\Databases\Http\Databases\Update as UpdateDatabase; +use Appwrite\Platform\Modules\Databases\Http\Databases\XList as ListDatabases; use Utopia\Platform\Service; class Http extends Service @@ -40,12 +46,17 @@ class Http extends Service $this->registerRowActions(); } - private function registerDatabaseActions() + private function registerDatabaseActions(): void { - + $this->addAction(CreateDatabase::getName(), new CreateDatabase()); + $this->addAction(GetDatabase::getName(), new GetDatabase()); + $this->addAction(UpdateDatabase::getName(), new UpdateDatabase()); + $this->addAction(DeleteDatabase::getName(), new DeleteDatabase()); + $this->addAction(ListDatabases::getName(), new ListDatabases()); + $this->addAction(ListDatabaseLogs::getName(), new ListDatabaseLogs()); } - private function registerTableActions() + private function registerTableActions(): void { } @@ -98,12 +109,12 @@ class Http extends Service $this->addAction(UpdateURL::getName(), new UpdateURL()); } - private function registerIndexActions() + private function registerIndexActions(): void { } - private function registerRowActions() + private function registerRowActions(): void { } From 8efc1543e9c0889621cdf2ae5011358b464ef8d0 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 17:05:14 +0530 Subject: [PATCH 030/343] update: move Table ops to module. --- app/controllers/api/databases.php | 448 ------------------ .../Modules/Databases/Http/Tables/Create.php | 116 +++++ .../Modules/Databases/Http/Tables/Delete.php | 95 ++++ .../Modules/Databases/Http/Tables/Get.php | 74 +++ .../Databases/Http/Tables/Logs/XList.php | 153 ++++++ .../Modules/Databases/Http/Tables/Update.php | 110 +++++ .../Modules/Databases/Http/Tables/XList.php | 117 +++++ 7 files changed, 665 insertions(+), 448 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index dd181f8894..bc80502521 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -11,7 +11,6 @@ use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; -use Appwrite\Utopia\Database\Validator\Queries\Collections; use Appwrite\Utopia\Database\Validator\Queries\Indexes; use Appwrite\Utopia\Response; use MaxMind\Db\Reader; @@ -23,7 +22,6 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Duplicate as DuplicateException; -use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Exception\Order as OrderException; use Utopia\Database\Exception\Query as QueryException; @@ -48,452 +46,6 @@ use Utopia\Validator\JSON; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; -App::post('/v1/databases/:databaseId/tables') - ->alias('/v1/databases/:databaseId/collections') - ->desc('Create table') - ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].tables.[tableId].create') - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'table.create') - ->label('audits.resource', 'database/{request.databaseId}/table/{response.$id}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'tables', - name: 'createTable', - description: '/docs/references/databases/create-collection.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_CREATED, - model: Response::MODEL_COLLECTION, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('name', '', new Text(128), 'Table name. Max length: 128 chars.') - ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) - ->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) - ->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('mode') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $queueForEvents) { - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $tableId = $tableId == 'unique()' ? ID::unique() : $tableId; - - // Map aggregate permissions into the multiple permissions they represent. - $permissions = Permission::aggregate($permissions) ?? []; - - try { - $table = $dbForProject->createDocument('database_' . $database->getInternalId(), new Document([ - '$id' => $tableId, - 'databaseInternalId' => $database->getInternalId(), - 'databaseId' => $databaseId, - '$permissions' => $permissions, - 'documentSecurity' => $documentSecurity, - 'enabled' => $enabled, - 'name' => $name, - 'search' => implode(' ', [$tableId, $name]), - ])); - - $dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), permissions: $permissions, documentSecurity: $documentSecurity); - } catch (DuplicateException) { - throw new Exception(Exception::COLLECTION_ALREADY_EXISTS); - } catch (LimitException) { - throw new Exception(Exception::COLLECTION_LIMIT_EXCEEDED); - } - - $queueForEvents - ->setContext('database', $database) - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()); - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($table, Response::MODEL_COLLECTION); - }); - -App::get('/v1/databases/:databaseId/tables') - ->alias('/v1/databases/:databaseId/collections') - ->desc('List tables') - ->groups(['api', 'database']) - ->label('scope', 'collections.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: 'tables', - name: 'listTables', - description: '/docs/references/databases/list-collections.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_COLLECTION_LIST, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('queries', [], new Collections(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Collections::ALLOWED_ATTRIBUTES), true) - ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('mode') - ->action(function (string $databaseId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) { - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $queries = Query::parseQueries($queries); - - if (!empty($search)) { - $queries[] = Query::search('search', $search); - } - - /** - * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries - */ - $cursor = \array_filter($queries, function ($query) { - return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); - }); - $cursor = reset($cursor); - if ($cursor) { - /** @var Query $cursor */ - - $validator = new Cursor(); - if (!$validator->isValid($cursor)) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); - } - - $tableId = $cursor->getValue(); - $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - - if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Table '{$tableId}' for the 'cursor' value not found."); - } - - $cursor->setValue($cursorDocument); - } - - $filterQueries = Query::groupByType($queries)['filters']; - - try { - $tables = $dbForProject->find('database_' . $database->getInternalId(), $queries); - $total = $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT); - } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); - } - - // TODO: collections > tables - $response->dynamic(new Document([ - 'collections' => $tables, - 'total' => $total, - ]), Response::MODEL_COLLECTION_LIST); - }); - -App::get('/v1/databases/:databaseId/tables/:tableId') - ->alias('/v1/databases/:databaseId/collections/:tableId') - ->desc('Get table') - ->groups(['api', 'database']) - ->label('scope', 'collections.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: 'tables', - name: 'getTable', - description: '/docs/references/databases/get-collection.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_COLLECTION, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID.') - ->inject('response') - ->inject('dbForProject') - ->action(function (string $databaseId, string $tableId, Response $response, Database $dbForProject) { - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $response->dynamic($table, Response::MODEL_COLLECTION); - }); - -App::get('/v1/databases/:databaseId/tables/:tableId/logs') - ->alias('/v1/databases/:databaseId/collections/:tableId/logs') - ->desc('List table logs') - ->groups(['api', 'database']) - ->label('scope', 'collections.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: 'tables', - name: 'listTableLogs', - description: '/docs/references/databases/get-collection-logs.md', - auth: [AuthType::ADMIN], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_LOG_LIST, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID.') - ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->inject('response') - ->inject('dbForProject') - ->inject('locale') - ->inject('geodb') - ->action(function (string $databaseId, string $tableId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $tableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $tableDocument->getInternalId()); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } - - // Temp fix for logs - $queries[] = Query::or([ - Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), - Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), - ]); - - $audit = new Audit($dbForProject); - $resource = 'database/' . $databaseId . '/table/' . $tableId; - $logs = $audit->getLogsByResource($resource, $queries); - - $output = []; - - foreach ($logs as $i => &$log) { - $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; - - $detector = new Detector($log['userAgent']); - $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) - - $os = $detector->getOS(); - $client = $detector->getClient(); - $device = $detector->getDevice(); - - $output[$i] = new Document([ - 'event' => $log['event'], - 'userId' => $log['data']['userId'], - 'userEmail' => $log['data']['userEmail'] ?? null, - 'userName' => $log['data']['userName'] ?? null, - 'mode' => $log['data']['mode'] ?? null, - 'ip' => $log['ip'], - 'time' => $log['time'], - 'osCode' => $os['osCode'], - 'osName' => $os['osName'], - 'osVersion' => $os['osVersion'], - 'clientType' => $client['clientType'], - 'clientCode' => $client['clientCode'], - 'clientName' => $client['clientName'], - 'clientVersion' => $client['clientVersion'], - 'clientEngine' => $client['clientEngine'], - 'clientEngineVersion' => $client['clientEngineVersion'], - 'deviceName' => $device['deviceName'], - 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'] - ]); - - $record = $geodb->get($log['ip']); - - if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); - } else { - $output[$i]['countryCode'] = '--'; - $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); - } - } - - $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource, $queries), - 'logs' => $output, - ]), Response::MODEL_LOG_LIST); - }); - - -App::put('/v1/databases/:databaseId/tables/:tableId') - ->alias('/v1/databases/:databaseId/collections/:tableId') - ->desc('Update table') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].update') - ->label('audits.event', 'table.update') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'tables', - name: 'updateTable', - description: '/docs/references/databases/update-collection.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_COLLECTION, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID.') - ->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.') - ->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('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) - ->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('mode') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $queueForEvents) { - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $permissions ??= $table->getPermissions() ?? []; - - // Map aggregate permissions into the multiple permissions they represent. - $permissions = Permission::aggregate($permissions); - - $enabled ??= $table->getAttribute('enabled', true); - - $table = $dbForProject->updateDocument( - 'database_' . $database->getInternalId(), - $tableId, - $table - ->setAttribute('name', $name) - ->setAttribute('$permissions', $permissions) - ->setAttribute('documentSecurity', $documentSecurity) - ->setAttribute('enabled', $enabled) - ->setAttribute('search', \implode(' ', [$tableId, $name])) - ); - - $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $permissions, $documentSecurity); - - $queueForEvents - ->setContext('database', $database) - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()); - - $response->dynamic($table, Response::MODEL_COLLECTION); - }); - -App::delete('/v1/databases/:databaseId/tables/:tableId') - ->alias('/v1/databases/:databaseId/collections/:tableId') - ->desc('Delete table') - ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].delete') - ->label('audits.event', 'table.delete') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'tables', - name: 'deleteTable', - description: '/docs/references/databases/delete-collection.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_NOCONTENT, - model: Response::MODEL_NONE, - ) - ], - contentType: ContentType::NONE - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID.') - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->inject('mode') - ->action(function (string $databaseId, string $tableId, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, string $mode) { - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $tableId)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); - } - - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId()); - - $queueForDatabase - ->setType(DATABASE_TYPE_DELETE_COLLECTION) - ->setDatabase($database) - ->setTable($table); - - $queueForEvents - ->setContext('database', $database) - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setPayload($response->output($table, Response::MODEL_COLLECTION)); - - $response->noContent(); - }); - App::post('/v1/databases/:databaseId/tables/:tableId/indexes') ->alias('/v1/databases/:databaseId/collections/:tableId/indexes') ->desc('Create index') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php new file mode 100644 index 0000000000..ead5a64f88 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php @@ -0,0 +1,116 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables') + ->httpAlias('/v1/databases/:databaseId/collections') + ->desc('Create table') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].tables.[tableId].create') + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'table.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{response.$id}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'tables', + name: 'createTable', + description: '/docs/references/databases/create-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_CREATED, + model: UtopiaResponse::MODEL_COLLECTION, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('name', '', new Text(128), 'Table name. Max length: 128 chars.') + ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $tableId = $tableId === 'unique()' ? ID::unique() : $tableId; + + $permissions = Permission::aggregate($permissions) ?? []; + + try { + $table = $dbForProject->createDocument('database_' . $database->getInternalId(), new Document([ + '$id' => $tableId, + 'databaseInternalId' => $database->getInternalId(), + 'databaseId' => $databaseId, + '$permissions' => $permissions, + 'documentSecurity' => $documentSecurity, + 'enabled' => $enabled, + 'name' => $name, + 'search' => \implode(' ', [$tableId, $name]), + ])); + + $dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), permissions: $permissions, documentSecurity: $documentSecurity); + } catch (DuplicateException) { + throw new Exception(Exception::COLLECTION_ALREADY_EXISTS); + } catch (LimitException) { + throw new Exception(Exception::COLLECTION_LIMIT_EXCEEDED); + } + + $queueForEvents + ->setContext('database', $database) + ->setParam('databaseId', $databaseId) + ->setParam('tableId', $table->getId()); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) + ->dynamic($table, UtopiaResponse::MODEL_COLLECTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php new file mode 100644 index 0000000000..b3120ef36d --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php @@ -0,0 +1,95 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId') + ->desc('Delete table') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].delete') + ->label('audits.event', 'table.delete') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'tables', + name: 'deleteTable', + description: '/docs/references/databases/delete-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_NOCONTENT, + model: UtopiaResponse::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$thiss, 'action']); + } + + public function action(string $databaseId, string $tableId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { + $database = \Utopia\Database\Validator\Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $tableId)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); + } + + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId()); + + $queueForDatabase + ->setType(DATABASE_TYPE_DELETE_COLLECTION) + ->setDatabase($database) + ->setTable($table); + + $queueForEvents + ->setContext('database', $database) + ->setParam('databaseId', $databaseId) + ->setParam('tableId', $table->getId()) + ->setPayload($response->output($table, UtopiaResponse::MODEL_COLLECTION)); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php new file mode 100644 index 0000000000..2b0f77fc81 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php @@ -0,0 +1,74 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId') + ->desc('Get table') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'tables', + name: 'getTable', + description: '/docs/references/databases/get-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_COLLECTION, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, UtopiaResponse $response, Database $dbForProject): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $response->dynamic($table, UtopiaResponse::MODEL_COLLECTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php new file mode 100644 index 0000000000..44a850424f --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php @@ -0,0 +1,153 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/logs') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/logs') + ->desc('List table logs') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'tables', + name: 'listTableLogs', + description: '/docs/references/databases/get-collection-logs.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_LOG_LIST, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) + ->inject('response') + ->inject('dbForProject') + ->inject('locale') + ->inject('geodb') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $tableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $tableDocument->getInternalId()); + + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); + + $audit = new Audit($dbForProject); + $resource = 'database/' . $databaseId . '/table/' . $tableId; + $logs = $audit->getLogsByResource($resource, $queries); + + $output = []; + + foreach ($logs as $i => &$log) { + $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + + $detector = new Detector($log['userAgent']); + $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) + + $os = $detector->getOS(); + $client = $detector->getClient(); + $device = $detector->getDevice(); + + $output[$i] = new Document([ + 'event' => $log['event'], + 'userId' => $log['data']['userId'], + 'userEmail' => $log['data']['userEmail'] ?? null, + 'userName' => $log['data']['userName'] ?? null, + 'mode' => $log['data']['mode'] ?? null, + 'ip' => $log['ip'], + 'time' => $log['time'], + 'osCode' => $os['osCode'], + 'osName' => $os['osName'], + 'osVersion' => $os['osVersion'], + 'clientType' => $client['clientType'], + 'clientCode' => $client['clientCode'], + 'clientName' => $client['clientName'], + 'clientVersion' => $client['clientVersion'], + 'clientEngine' => $client['clientEngine'], + 'clientEngineVersion' => $client['clientEngineVersion'], + 'deviceName' => $device['deviceName'], + 'deviceBrand' => $device['deviceBrand'], + 'deviceModel' => $device['deviceModel'] + ]); + + $record = $geodb->get($log['ip']); + + if ($record) { + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + } else { + $output[$i]['countryCode'] = '--'; + $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); + } + } + + $response->dynamic(new Document([ + 'total' => $audit->countLogsByResource($resource, $queries), + 'logs' => $output, + ]), UtopiaResponse::MODEL_LOG_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php new file mode 100644 index 0000000000..2db6c5d328 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php @@ -0,0 +1,110 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId') + ->desc('Update table') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].update') + ->label('audits.event', 'table.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'tables', + name: 'updateTable', + description: '/docs/references/databases/update-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_COLLECTION, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.') + ->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('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $permissions ??= $table->getPermissions() ?? []; + + // Map aggregate permissions into the multiple permissions they represent. + $permissions = Permission::aggregate($permissions); + + $enabled ??= $table->getAttribute('enabled', true); + + $table = $dbForProject->updateDocument( + 'database_' . $database->getInternalId(), + $tableId, + $table + ->setAttribute('name', $name) + ->setAttribute('$permissions', $permissions) + ->setAttribute('documentSecurity', $documentSecurity) + ->setAttribute('enabled', $enabled) + ->setAttribute('search', \implode(' ', [$tableId, $name])) + ); + + $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $permissions, $documentSecurity); + + $queueForEvents + ->setContext('database', $database) + ->setParam('databaseId', $databaseId) + ->setParam('tableId', $table->getId()); + + $response->dynamic($table, UtopiaResponse::MODEL_COLLECTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php new file mode 100644 index 0000000000..d75150f2bb --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php @@ -0,0 +1,117 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/tables') + ->httpAlias('/v1/databases/:databaseId/collections') + ->desc('List tables') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'tables', + name: 'listTables', + description: '/docs/references/databases/list-collections.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_COLLECTION_LIST, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('queries', [], new Collections(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Collections::ALLOWED_ATTRIBUTES), true) + ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $queries = Query::parseQueries($queries); + + if (!empty($search)) { + $queries[] = Query::search('search', $search); + } + + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + $cursor = reset($cursor); + + if ($cursor) { + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $tableId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + + if ($cursorDocument->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Table '{$tableId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + + $filterQueries = Query::groupByType($queries)['filters']; + + try { + $tables = $dbForProject->find('database_' . $database->getInternalId(), $queries); + $total = $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT); + } catch (OrderException $e) { + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); + } + + $response->dynamic(new Document([ + 'collections' => $tables, // TODO: consider renaming to 'tables' + 'total' => $total, + ]), UtopiaResponse::MODEL_COLLECTION_LIST); + } +} From 3271ef57695f56b2a3e0dfa4d229167dad7eb576 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 17:16:37 +0530 Subject: [PATCH 031/343] update: move Index ops to module. --- app/controllers/api/databases.php | 389 ------------------ .../Modules/Databases/Http/Indexes/Create.php | 217 ++++++++++ .../Modules/Databases/Http/Indexes/Delete.php | 109 +++++ .../Modules/Databases/Http/Indexes/Get.php | 80 ++++ .../Modules/Databases/Http/Indexes/XList.php | 129 ++++++ 5 files changed, 535 insertions(+), 389 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Indexes/Delete.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Indexes/Get.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Indexes/XList.php diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index bc80502521..63a4e3fbb7 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2,7 +2,6 @@ use Appwrite\Auth\Auth; use Appwrite\Detector\Detector; -use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; @@ -11,7 +10,6 @@ use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; -use Appwrite\Utopia\Database\Validator\Queries\Indexes; use Appwrite\Utopia\Response; use MaxMind\Db\Reader; use Utopia\App; @@ -31,8 +29,6 @@ use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Index as IndexValidator; -use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Cursor; @@ -41,395 +37,10 @@ use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; use Utopia\Validator\ArrayList; -use Utopia\Validator\Boolean; use Utopia\Validator\JSON; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; -App::post('/v1/databases/:databaseId/tables/:tableId/indexes') - ->alias('/v1/databases/:databaseId/collections/:tableId/indexes') - ->desc('Create index') - ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].create') - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'index.create') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'tables', - name: 'createIndex', - description: '/docs/references/databases/create-index.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_ACCEPTED, - model: Response::MODEL_INDEX, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', null, new Key(), 'Index Key.') - ->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE]), 'Index type.') - ->param('columns', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of columns to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' columns are allowed, each 32 characters long.') - ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, string $type, array $columns, array $orders, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - - $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($db->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $count = $dbForProject->count('indexes', [ - Query::equal('collectionInternalId', [$table->getInternalId()]), - Query::equal('databaseInternalId', [$db->getInternalId()]) - ], 61); - - $limit = $dbForProject->getLimitForIndexes(); - - if ($count >= $limit) { - throw new Exception(Exception::INDEX_LIMIT_EXCEEDED, 'Index limit exceeded'); - } - - // Convert Document[] to array of attribute metadata - $oldColumns = \array_map(fn ($a) => $a->getArrayCopy(), $table->getAttribute('attributes')); - - $oldColumns[] = [ - 'key' => '$id', - 'type' => Database::VAR_STRING, - 'status' => 'available', - 'required' => true, - 'array' => false, - 'default' => null, - 'size' => Database::LENGTH_KEY - ]; - - $oldColumns[] = [ - 'key' => '$createdAt', - 'type' => Database::VAR_DATETIME, - 'status' => 'available', - 'signed' => false, - 'required' => false, - 'array' => false, - 'default' => null, - 'size' => 0 - ]; - - $oldColumns[] = [ - 'key' => '$updatedAt', - 'type' => Database::VAR_DATETIME, - 'status' => 'available', - 'signed' => false, - 'required' => false, - 'array' => false, - 'default' => null, - 'size' => 0 - ]; - - // lengths hidden by default - $lengths = []; - - foreach ($columns as $i => $column) { - // find attribute metadata in collection document - $columnIndex = \array_search($column, array_column($oldColumns, 'key')); - - if ($columnIndex === false) { - throw new Exception(Exception::ATTRIBUTE_UNKNOWN, 'Unknown column: ' . $column . '. Verify the column name or create the column.'); - } - - $columnStatus = $oldColumns[$columnIndex]['status']; - $columnType = $oldColumns[$columnIndex]['type']; - $columnArray = $oldColumns[$columnIndex]['array'] ?? false; - - if ($columnType === Database::VAR_RELATIONSHIP) { - throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Cannot create an index for a relationship column: ' . $oldColumns[$columnIndex]['key']); - } - - // ensure attribute is available - if ($columnStatus !== 'available') { - throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Column not available: ' . $oldColumns[$columnIndex]['key']); - } - - $lengths[$i] = null; - - if ($columnArray === true) { - $lengths[$i] = Database::ARRAY_INDEX_LENGTH; - $orders[$i] = null; - } - } - - $index = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $table->getInternalId() . '_' . $key), - 'key' => $key, - 'status' => 'processing', // processing, available, failed, deleting, stuck - 'databaseInternalId' => $db->getInternalId(), - 'databaseId' => $databaseId, - 'collectionInternalId' => $table->getInternalId(), - 'collectionId' => $tableId, - 'type' => $type, - 'attributes' => $columns, - 'lengths' => $lengths, - 'orders' => $orders, - ]); - - $validator = new IndexValidator( - $table->getAttribute('attributes'), - $dbForProject->getAdapter()->getMaxIndexLength(), - $dbForProject->getAdapter()->getInternalIndexesKeys(), - ); - if (!$validator->isValid($index)) { - throw new Exception(Exception::INDEX_INVALID, $validator->getDescription()); - } - - try { - $index = $dbForProject->createDocument('indexes', $index); - } catch (DuplicateException) { - throw new Exception(Exception::INDEX_ALREADY_EXISTS); - } - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); - - $queueForDatabase - ->setType(DATABASE_TYPE_CREATE_INDEX) - ->setDatabase($db) - ->setTable($table) - ->setRow($index); - - $queueForEvents - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('indexId', $index->getId()) - ->setContext('table', $table) - ->setContext('database', $db); - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($index, Response::MODEL_INDEX); - }); - -App::get('/v1/databases/:databaseId/tables/:tableId/indexes') - ->alias('/v1/databases/:databaseId/collections/:tableId/indexes') - ->desc('List indexes') - ->groups(['api', 'database']) - ->label('scope', 'collections.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: 'indexes', - name: 'listIndexes', - description: '/docs/references/databases/list-indexes.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_INDEX_LIST, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) - ->inject('response') - ->inject('dbForProject') - ->action(function (string $databaseId, string $tableId, array $queries, Response $response, Database $dbForProject) { - /** @var Document $database */ - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $queries = Query::parseQueries($queries); - - \array_push( - $queries, - Query::equal('databaseId', [$databaseId]), - Query::equal('collectionId', [$tableId]), - ); - - /** - * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries - */ - $cursor = \array_filter($queries, function ($query) { - return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); - }); - $cursor = reset($cursor); - - if ($cursor) { - $validator = new Cursor(); - if (!$validator->isValid($cursor)) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); - } - - $indexId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ - Query::equal('collectionInternalId', [$table->getInternalId()]), - Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('key', [$indexId]), - Query::limit(1) - ])); - - if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Index '{$indexId}' for the 'cursor' value not found."); - } - - $cursor->setValue($cursorDocument[0]); - } - - $filterQueries = Query::groupByType($queries)['filters']; - try { - $total = $dbForProject->count('indexes', $filterQueries, APP_LIMIT_COUNT); - $indexes = $dbForProject->find('indexes', $queries); - } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); - } - - $response->dynamic(new Document([ - 'total' => $total, - 'indexes' => $indexes, - ]), Response::MODEL_INDEX_LIST); - }); - -App::get('/v1/databases/:databaseId/tables/:tableId/indexes/:key') - ->alias('/v1/databases/:databaseId/collections/:tableId/indexes/:key') - ->desc('Get index') - ->groups(['api', 'database']) - ->label('scope', 'collections.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: 'indexes', - name: 'getIndex', - description: '/docs/references/databases/get-index.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_INDEX, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', null, new Key(), 'Index Key.') - ->inject('response') - ->inject('dbForProject') - ->action(function (string $databaseId, string $tableId, string $key, Response $response, Database $dbForProject) { - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $index = $table->find('key', $key, 'indexes'); - if (empty($index)) { - throw new Exception(Exception::INDEX_NOT_FOUND); - } - - $response->dynamic($index, Response::MODEL_INDEX); - }); - - -App::delete('/v1/databases/:databaseId/tables/:tableId/indexes/:key') - ->alias('/v1/databases/:databaseId/collections/:tableId/indexes/:key') - ->desc('Delete index') - ->groups(['api', 'database']) - ->label('scope', 'collections.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].update') - ->label('audits.event', 'index.delete') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('sdk', new Method( - namespace: 'databases', - group: 'indexes', - name: 'deleteIndex', - description: '/docs/references/databases/delete-index.md', - auth: [AuthType::KEY], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_NOCONTENT, - model: Response::MODEL_NONE, - ) - ], - contentType: ContentType::NONE - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('key', '', new Key(), 'Index Key.') - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDatabase') - ->inject('queueForEvents') - ->action(function (string $databaseId, string $tableId, string $key, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - - $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($db->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $index = $dbForProject->getDocument('indexes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); - - if (empty($index->getId())) { - throw new Exception(Exception::INDEX_NOT_FOUND); - } - - // Only update status if removing available index - if ($index->getAttribute('status') === 'available') { - $index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting')); - } - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); - - $queueForDatabase - ->setType(DATABASE_TYPE_DELETE_INDEX) - ->setDatabase($db) - ->setTable($table) - ->setRow($index); - - $queueForEvents - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('indexId', $index->getId()) - ->setContext('table', $table) - ->setContext('database', $db) - ->setPayload($response->output($index, Response::MODEL_INDEX)); - - $response->noContent(); - }); - App::post('/v1/databases/:databaseId/tables/:tableId/rows') ->alias('/v1/databases/:databaseId/collections/:tableId/documents') ->desc('Create row') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php new file mode 100644 index 0000000000..49cb7157b0 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php @@ -0,0 +1,217 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/indexes') + ->desc('Create index') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].create') + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'index.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'tables', + name: 'createIndex', + description: '/docs/references/databases/create-index.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: UtopiaResponse::MODEL_INDEX, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', null, new Key(), 'Index Key.') + ->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE]), 'Index type.') + ->param('columns', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of columns to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' columns are allowed, each 32 characters long.') + ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, string $key, string $type, array $columns, array $orders, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { + $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($db->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); + + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $count = $dbForProject->count('indexes', [ + Query::equal('collectionInternalId', [$table->getInternalId()]), + Query::equal('databaseInternalId', [$db->getInternalId()]) + ], 61); + + $limit = $dbForProject->getLimitForIndexes(); + + if ($count >= $limit) { + throw new Exception(Exception::INDEX_LIMIT_EXCEEDED, 'Index limit exceeded'); + } + + // Convert Document[] to array of attribute metadata + $oldColumns = \array_map(fn ($a) => $a->getArrayCopy(), $table->getAttribute('attributes')); + + $oldColumns[] = [ + 'key' => '$id', + 'type' => Database::VAR_STRING, + 'status' => 'available', + 'required' => true, + 'array' => false, + 'default' => null, + 'size' => Database::LENGTH_KEY + ]; + + $oldColumns[] = [ + 'key' => '$createdAt', + 'type' => Database::VAR_DATETIME, + 'status' => 'available', + 'signed' => false, + 'required' => false, + 'array' => false, + 'default' => null, + 'size' => 0 + ]; + + $oldColumns[] = [ + 'key' => '$updatedAt', + 'type' => Database::VAR_DATETIME, + 'status' => 'available', + 'signed' => false, + 'required' => false, + 'array' => false, + 'default' => null, + 'size' => 0 + ]; + + // lengths hidden by default + $lengths = []; + + foreach ($columns as $i => $column) { + // find attribute metadata in collection document + $columnIndex = \array_search($column, array_column($oldColumns, 'key')); + + if ($columnIndex === false) { + throw new Exception(Exception::ATTRIBUTE_UNKNOWN, 'Unknown column: ' . $column . '. Verify the column name or create the column.'); + } + + $columnStatus = $oldColumns[$columnIndex]['status']; + $columnType = $oldColumns[$columnIndex]['type']; + $columnArray = $oldColumns[$columnIndex]['array'] ?? false; + + if ($columnType === Database::VAR_RELATIONSHIP) { + throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Cannot create an index for a relationship column: ' . $oldColumns[$columnIndex]['key']); + } + + // ensure attribute is available + if ($columnStatus !== 'available') { + throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Column not available: ' . $oldColumns[$columnIndex]['key']); + } + + $lengths[$i] = null; + + if ($columnArray === true) { + $lengths[$i] = Database::ARRAY_INDEX_LENGTH; + $orders[$i] = null; + } + } + + $index = new Document([ + '$id' => ID::custom($db->getInternalId() . '_' . $table->getInternalId() . '_' . $key), + 'key' => $key, + 'status' => 'processing', // processing, available, failed, deleting, stuck + 'databaseInternalId' => $db->getInternalId(), + 'databaseId' => $databaseId, + 'collectionInternalId' => $table->getInternalId(), + 'collectionId' => $tableId, + 'type' => $type, + 'attributes' => $columns, + 'lengths' => $lengths, + 'orders' => $orders, + ]); + + $validator = new IndexValidator( + $table->getAttribute('attributes'), + $dbForProject->getAdapter()->getMaxIndexLength(), + $dbForProject->getAdapter()->getInternalIndexesKeys(), + ); + if (!$validator->isValid($index)) { + throw new Exception(Exception::INDEX_INVALID, $validator->getDescription()); + } + + try { + $index = $dbForProject->createDocument('indexes', $index); + } catch (DuplicateException) { + throw new Exception(Exception::INDEX_ALREADY_EXISTS); + } + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); + + $queueForDatabase + ->setType(DATABASE_TYPE_CREATE_INDEX) + ->setDatabase($db) + ->setTable($table) + ->setRow($index); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setParam('tableId', $table->getId()) + ->setParam('indexId', $index->getId()) + ->setContext('table', $table) + ->setContext('database', $db); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($index, UtopiaResponse::MODEL_INDEX); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Delete.php new file mode 100644 index 0000000000..eeb772e0c3 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Delete.php @@ -0,0 +1,109 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes/:key') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/indexes/:key') + ->desc('Delete index') + ->groups(['api', 'database']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].update') + ->label('audits.event', 'index.delete') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'indexes', + name: 'deleteIndex', + description: '/docs/references/databases/delete-index.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_NOCONTENT, + model: UtopiaResponse::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Index Key.') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { + $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($db->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); + + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $index = $dbForProject->getDocument('indexes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); + + if (empty($index->getId())) { + throw new Exception(Exception::INDEX_NOT_FOUND); + } + + // Only update status if removing available index + if ($index->getAttribute('status') === 'available') { + $index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting')); + } + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); + + $queueForDatabase + ->setType(DATABASE_TYPE_DELETE_INDEX) + ->setDatabase($db) + ->setTable($table) + ->setRow($index); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setParam('tableId', $table->getId()) + ->setParam('indexId', $index->getId()) + ->setContext('table', $table) + ->setContext('database', $db) + ->setPayload($response->output($index, UtopiaResponse::MODEL_INDEX)); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Get.php new file mode 100644 index 0000000000..72ab1a02b1 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Get.php @@ -0,0 +1,80 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes/:key') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/indexes/:key') + ->desc('Get index') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'indexes', + name: 'getIndex', + description: '/docs/references/databases/get-index.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_INDEX, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', null, new Key(), 'Index Key.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $index = $table->find('key', $key, 'indexes'); + if (empty($index)) { + throw new Exception(Exception::INDEX_NOT_FOUND); + } + + $response->dynamic($index, UtopiaResponse::MODEL_INDEX); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/XList.php new file mode 100644 index 0000000000..4920b679c1 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/XList.php @@ -0,0 +1,129 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/indexes') + ->desc('List indexes') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'indexes', + name: 'listIndexes', + description: '/docs/references/databases/list-indexes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_INDEX_LIST, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject): void + { + /** @var Document $database */ + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $queries = Query::parseQueries($queries); + + \array_push( + $queries, + Query::equal('databaseId', [$databaseId]), + Query::equal('collectionId', [$tableId]), + ); + + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + $cursor = reset($cursor); + + if ($cursor) { + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $indexId = $cursor->getValue(); + $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ + Query::equal('collectionInternalId', [$table->getInternalId()]), + Query::equal('databaseInternalId', [$database->getInternalId()]), + Query::equal('key', [$indexId]), + Query::limit(1) + ])); + + if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Index '{$indexId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument[0]); + } + + $filterQueries = Query::groupByType($queries)['filters']; + try { + $total = $dbForProject->count('indexes', $filterQueries, APP_LIMIT_COUNT); + $indexes = $dbForProject->find('indexes', $queries); + } catch (OrderException $e) { + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); + } + + $response->dynamic(new Document([ + 'total' => $total, + 'indexes' => $indexes, + ]), UtopiaResponse::MODEL_INDEX_LIST); + } +} From 76785d58c63420eadd82a9a2afbef44ddf18a958 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 17:16:52 +0530 Subject: [PATCH 032/343] fix: imports, lint. --- .../Platform/Modules/Databases/Http/Tables/Delete.php | 5 +++-- .../Platform/Modules/Databases/Http/Tables/Update.php | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php index b3120ef36d..92003f3eeb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php @@ -11,6 +11,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -58,12 +59,12 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$thiss, 'action']); + ->callback([$this, 'action']); } public function action(string $databaseId, string $tableId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { - $database = \Utopia\Database\Validator\Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php index 2db6c5d328..dc302ce47f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php @@ -70,7 +70,7 @@ class Update extends Action public function action(string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } From fd7801fe26ff95aba9ba5d94a05e94f310151ceb Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 17:24:38 +0530 Subject: [PATCH 033/343] add: register index and table modules. --- .../Modules/Databases/Services/Http.php | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Http.php b/src/Appwrite/Platform/Modules/Databases/Services/Http.php index de0de71e05..045dc6ff42 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Http.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Http.php @@ -31,6 +31,16 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Get as GetDatabase; use Appwrite\Platform\Modules\Databases\Http\Databases\Logs\XList as ListDatabaseLogs; use Appwrite\Platform\Modules\Databases\Http\Databases\Update as UpdateDatabase; use Appwrite\Platform\Modules\Databases\Http\Databases\XList as ListDatabases; +use Appwrite\Platform\Modules\Databases\Http\Indexes\Create as CreateIndex; +use Appwrite\Platform\Modules\Databases\Http\Indexes\Delete as DeleteIndex; +use Appwrite\Platform\Modules\Databases\Http\Indexes\Get as GetIndex; +use Appwrite\Platform\Modules\Databases\Http\Indexes\XList as ListIndexes; +use Appwrite\Platform\Modules\Databases\Http\Tables\Create as CreateTable; +use Appwrite\Platform\Modules\Databases\Http\Tables\Delete as DeleteTable; +use Appwrite\Platform\Modules\Databases\Http\Tables\Get as GetTable; +use Appwrite\Platform\Modules\Databases\Http\Tables\Logs\XList as ListTableLogs; +use Appwrite\Platform\Modules\Databases\Http\Tables\Update as UpdateTable; +use Appwrite\Platform\Modules\Databases\Http\Tables\XList as ListTables; use Utopia\Platform\Service; class Http extends Service @@ -58,7 +68,12 @@ class Http extends Service private function registerTableActions(): void { - + $this->addAction(CreateTable::getName(), new CreateTable()); + $this->addAction(GetTable::getName(), new GetTable()); + $this->addAction(UpdateTable::getName(), new UpdateTable()); + $this->addAction(DeleteTable::getName(), new DeleteTable()); + $this->addAction(ListTables::getName(), new ListTables()); + $this->addAction(ListTableLogs::getName(), new ListTableLogs()); } private function registerColumnActions(): void @@ -111,7 +126,10 @@ class Http extends Service private function registerIndexActions(): void { - + $this->addAction(CreateIndex::getName(), new CreateIndex()); + $this->addAction(GetIndex::getName(), new GetIndex()); + $this->addAction(DeleteIndex::getName(), new DeleteIndex()); + $this->addAction(ListIndexes::getName(), new ListIndexes()); } private function registerRowActions(): void From 286c695b47c51a6608fe8723d431e8865b9c2069 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 17:52:29 +0530 Subject: [PATCH 034/343] add: move and register row modules. --- app/controllers/api/databases.php | 1087 ----------------- .../Modules/Databases/Http/Rows/Create.php | 314 +++++ .../Modules/Databases/Http/Rows/Delete.php | 167 +++ .../Modules/Databases/Http/Rows/Get.php | 154 +++ .../Databases/Http/Rows/Logs/XList.php | 159 +++ .../Modules/Databases/Http/Rows/Update.php | 302 +++++ .../Modules/Databases/Http/Rows/XList.php | 223 ++++ .../Modules/Databases/Services/Http.php | 13 +- 8 files changed, 1331 insertions(+), 1088 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 63a4e3fbb7..1f18d2fa1e 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1,1107 +1,20 @@ alias('/v1/databases/:databaseId/collections/:tableId/documents') - ->desc('Create row') - ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].create') - ->label('scope', 'documents.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'row.create') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') - ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') - ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) - ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) - ->label( - 'sdk', - [ - new Method( - namespace: 'databases', - group: 'rows', - name: 'createRow', - description: '/docs/references/databases/create-document.md', - auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_CREATED, - model: Response::MODEL_DOCUMENT, - ) - ], - contentType: ContentType::JSON - ) - ] - ) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('rowId', '', new CustomId(), 'Row ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define columns before creating rows.') - ->param('data', [], new JSON(), 'Row data as JSON object.') - ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) - ->inject('response') - ->inject('dbForProject') - ->inject('user') - ->inject('queueForEvents') - ->inject('queueForStatsUsage') - ->action(function (string $databaseId, string $rowId, string $tableId, string|array $data, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage) { - - $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array - - if (empty($data)) { - throw new Exception(Exception::DOCUMENT_MISSING_DATA); - } - - if (isset($data['$id'])) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is not allowed for creating new documents, try update instead'); - } - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - - if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $allowedPermissions = [ - Database::PERMISSION_READ, - Database::PERMISSION_UPDATE, - Database::PERMISSION_DELETE, - ]; - - // Map aggregate permissions to into the set of individual permissions they represent. - $permissions = Permission::aggregate($permissions, $allowedPermissions); - - // Add permissions for current the user if none were provided. - if (\is_null($permissions)) { - $permissions = []; - if (!empty($user->getId())) { - foreach ($allowedPermissions as $permission) { - $permissions[] = (new Permission($permission, 'user', $user->getId()))->toString(); - } - } - } - - // Users can only manage their own roles, API keys and Admin users can manage any - if (!$isAPIKey && !$isPrivilegedUser) { - foreach (Database::PERMISSIONS as $type) { - foreach ($permissions as $permission) { - $permission = Permission::parse($permission); - if ($permission->getPermission() != $type) { - continue; - } - $role = (new Role( - $permission->getRole(), - $permission->getIdentifier(), - $permission->getDimension() - ))->toString(); - if (!Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')'); - } - } - } - } - - $data['$collection'] = $table->getId(); // Adding this param to make API easier for developers - $data['$id'] = $rowId == 'unique()' ? ID::unique() : $rowId; - $data['$permissions'] = $permissions; - $row = new Document($data); - - $operations = 0; - - $checkPermissions = function (Document $table, Document $row, string $permission) use (&$checkPermissions, $dbForProject, $database, &$operations) { - $operations++; - - $documentSecurity = $table->getAttribute('documentSecurity', false); - $validator = new Authorization($permission); - - $valid = $validator->isValid($table->getPermissionsByType($permission)); - if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); - } - - if ($permission === Database::PERMISSION_UPDATE) { - $valid = $valid || $validator->isValid($row->getUpdate()); - if ($documentSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); - } - } - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - - $isList = \is_array($related) && \array_values($related) === $related; - - if ($isList) { - $relations = $related; - } else { - $relations = [$related]; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - $relatedTable = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) - ); - - foreach ($relations as &$relation) { - if ( - \is_array($relation) - && \array_values($relation) !== $relation - && !isset($relation['$id']) - ) { - $relation['$id'] = ID::unique(); - $relation = new Document($relation); - } - if ($relation instanceof Document) { - $current = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(), $relation->getId()) - ); - - if ($current->isEmpty()) { - $type = Database::PERMISSION_CREATE; - - if (isset($relation['$id']) && $relation['$id'] === 'unique()') { - $relation['$id'] = ID::unique(); - } - } else { - $relation->removeAttribute('$collectionId'); - $relation->removeAttribute('$databaseId'); - $relation->setAttribute('$collection', $relatedTable->getId()); - $type = Database::PERMISSION_UPDATE; - } - - $checkPermissions($relatedTable, $relation, $type); - } - } - - if ($isList) { - $row->setAttribute($relationship->getAttribute('key'), \array_values($relations)); - } else { - $row->setAttribute($relationship->getAttribute('key'), \reset($relations)); - } - } - }; - - $checkPermissions($table, $row, Database::PERMISSION_CREATE); - - try { - $row = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $row); - } catch (StructureException $e) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); - } catch (DuplicateException $e) { - throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); - } catch (NotFoundException $e) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - - // Add $tableId and $databaseId for all rows - $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) { - $row->setAttribute('$databaseId', $database->getId()); - $row->setAttribute('$collectionId', $table->getId()); - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - $relatedTable = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processRow($relatedTable, $relation); - } - } - } - }; - - $processRow($table, $row); - - $queueForStatsUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); // per collection - - $response->addHeader('X-Debug-Operations', $operations); - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($row, Response::MODEL_DOCUMENT); - - $relationships = \array_map( - fn ($document) => $document->getAttribute('key'), - \array_filter( - $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ) - ); - - $queueForEvents - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('rowId', $row->getId()) - ->setContext('table', $table) - ->setContext('database', $database) - ->setPayload($response->getPayload(), sensitive: $relationships); - }); - -App::get('/v1/databases/:databaseId/tables/:tableId/rows') - ->alias('/v1/databases/:databaseId/collections/:tableId/documents') - ->desc('List rows') - ->groups(['api', 'database']) - ->label('scope', 'documents.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: 'rows', - name: 'listRows', - description: '/docs/references/databases/list-documents.md', - auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_DOCUMENT_LIST, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForStatsUsage') - ->action(function (string $databaseId, string $tableId, array $queries, Response $response, Database $dbForProject, StatsUsage $queueForStatsUsage) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - - if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } - - /** - * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries - */ - $cursor = \array_filter($queries, function ($query) { - return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); - }); - - $cursor = \reset($cursor); - - if ($cursor) { - $validator = new Cursor(); - if (!$validator->isValid($cursor)) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); - } - - $rowId = $cursor->getValue(); - - $cursorRow = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); - - if ($cursorRow->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Row '{$rowId}' for the 'cursor' value not found."); - } - - $cursor->setValue($cursorRow); - } - try { - $rows = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $queries); - $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $queries, APP_LIMIT_COUNT); - } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); - } - - $operations = 0; - - // Add $tableId and $databaseId for all rows - $processRow = (function (Document $table, Document $row) use (&$processRow, $dbForProject, $database, &$operations): bool { - if ($row->isEmpty()) { - return false; - } - - $operations++; - - $row->removeAttribute('$collection'); - $row->setAttribute('$databaseId', $database->getId()); - $row->setAttribute('$collectionId', $table->getId()); - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - if (\in_array(\gettype($related), ['array', 'object'])) { - $operations++; - } - - continue; - } - - if (!\is_array($related)) { - $relations = [$related]; - } else { - $relations = $related; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - // todo: Use local cache for this getDocument - $relatedTable = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId)); - - foreach ($relations as $index => $doc) { - if ($doc instanceof Document) { - if (!$processRow($relatedTable, $doc)) { - unset($relations[$index]); - } - } - } - - if (\is_array($related)) { - $row->setAttribute($relationship->getAttribute('key'), \array_values($relations)); - } elseif (empty($relations)) { - $row->setAttribute($relationship->getAttribute('key'), null); - } - } - - return true; - }); - - foreach ($rows as $row) { - $processRow($table, $row); - } - - $queueForStatsUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); - - $response->addHeader('X-Debug-Operations', $operations); - - $select = \array_reduce($queries, function ($result, $query) { - return $result || ($query->getMethod() === Query::TYPE_SELECT); - }, false); - - // Check if the SELECT query includes $databaseId and $collectionId - $hasDatabaseId = false; - $hasTableId = false; - if ($select) { - $hasDatabaseId = \array_reduce($queries, function ($result, $query) { - return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$databaseId', $query->getValues())); - }, false); - $hasTableId = \array_reduce($queries, function ($result, $query) { - return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$collectionId', $query->getValues())); - }, false); - } - - if ($select) { - foreach ($rows as $row) { - if (!$hasDatabaseId) { - $row->removeAttribute('$databaseId'); - } - if (!$hasTableId) { - $row->removeAttribute('$collectionId'); - } - } - } - - $response->dynamic(new Document([ - 'total' => $total, - 'documents' => $rows, - ]), Response::MODEL_DOCUMENT_LIST); - }); - -App::get('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') - ->alias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId') - ->desc('Get row') - ->groups(['api', 'database']) - ->label('scope', 'documents.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: 'rows', - name: 'getRow', - description: '/docs/references/databases/get-document.md', - auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_DOCUMENT, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('rowId', '', new UID(), 'Row ID.') - ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('queueForStatsUsage') - ->action(function (string $databaseId, string $tableId, string $rowId, array $queries, Response $response, Database $dbForProject, StatsUsage $queueForStatsUsage) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - - if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - try { - $queries = Query::parseQueries($queries); - $row = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId, $queries); - } catch (AuthorizationException) { - throw new Exception(Exception::USER_UNAUTHORIZED); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } - - if ($row->isEmpty()) { - throw new Exception(Exception::DOCUMENT_NOT_FOUND); - } - - $operations = 0; - - // Add $tableId and $databaseId for all rows - $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database, &$operations) { - if ($row->isEmpty()) { - return; - } - - $operations++; - - $row->setAttribute('$databaseId', $database->getId()); - $row->setAttribute('$collectionId', $table->getId()); - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - if (\in_array(\gettype($related), ['array', 'object'])) { - $operations++; - } - - continue; - } - - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - $relatedTable = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processRow($relatedTable, $relation); - } - } - } - }; - - $processRow($table, $row); - - $queueForStatsUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); - - $response->addHeader('X-Debug-Operations', $operations); - - $response->dynamic($row, Response::MODEL_DOCUMENT); - }); - -App::get('/v1/databases/:databaseId/tables/:tableId/rows/:rowId/logs') - ->alias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId/logs') - ->desc('List row logs') - ->groups(['api', 'database']) - ->label('scope', 'documents.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: 'logs', - name: 'listRowLogs', - description: '/docs/references/databases/get-document-logs.md', - auth: [AuthType::ADMIN], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_LOG_LIST, - ) - ], - contentType: ContentType::JSON, - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Collection ID.') - ->param('rowId', '', new UID(), 'Row ID.') - ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->inject('response') - ->inject('dbForProject') - ->inject('locale') - ->inject('geodb') - ->action(function (string $databaseId, string $tableId, string $rowId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $row = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId); - - if ($row->isEmpty()) { - throw new Exception(Exception::DOCUMENT_NOT_FOUND); - } - - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } - - // Temp fix for logs - $queries[] = Query::or([ - Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), - Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), - ]); - - $audit = new Audit($dbForProject); - $resource = 'database/' . $databaseId . '/table/' . $tableId . '/row/' . $row->getId(); - $logs = $audit->getLogsByResource($resource, $queries); - - $output = []; - - foreach ($logs as $i => &$log) { - $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; - - $detector = new Detector($log['userAgent']); - $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) - - $os = $detector->getOS(); - $client = $detector->getClient(); - $device = $detector->getDevice(); - - $output[$i] = new Document([ - 'event' => $log['event'], - 'userId' => $log['data']['userId'], - 'userEmail' => $log['data']['userEmail'] ?? null, - 'userName' => $log['data']['userName'] ?? null, - 'mode' => $log['data']['mode'] ?? null, - 'ip' => $log['ip'], - 'time' => $log['time'], - 'osCode' => $os['osCode'], - 'osName' => $os['osName'], - 'osVersion' => $os['osVersion'], - 'clientType' => $client['clientType'], - 'clientCode' => $client['clientCode'], - 'clientName' => $client['clientName'], - 'clientVersion' => $client['clientVersion'], - 'clientEngine' => $client['clientEngine'], - 'clientEngineVersion' => $client['clientEngineVersion'], - 'deviceName' => $device['deviceName'], - 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'] - ]); - - $record = $geodb->get($log['ip']); - - if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); - } else { - $output[$i]['countryCode'] = '--'; - $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); - } - } - - $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource, $queries), - 'logs' => $output, - ]), Response::MODEL_LOG_LIST); - }); - -App::patch('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') - ->alias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId') - ->desc('Update row') - ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].update') - ->label('scope', 'documents.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'row.update') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}/row/{response.$id}') - ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') - ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) - ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) - ->label('sdk', new Method( - namespace: 'databases', - group: 'rows', - name: 'updateRow', - description: '/docs/references/databases/update-document.md', - auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_DOCUMENT, - ) - ], - contentType: ContentType::JSON - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Collection ID.') - ->param('rowId', '', new UID(), 'Row ID.') - ->param('data', [], new JSON(), 'Row data as JSON object. Include only columns and value pairs to be updated.', true) - ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) - ->inject('requestTimestamp') - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->inject('queueForStatsUsage') - ->action(function (string $databaseId, string $tableId, string $rowId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { - - $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array - - if (empty($data) && \is_null($permissions)) { - throw new Exception(Exception::DOCUMENT_MISSING_PAYLOAD); - } - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - - if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - // Read permission should not be required for update - /** @var Document $row */ - $row = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); - - if ($row->isEmpty()) { - throw new Exception(Exception::DOCUMENT_NOT_FOUND); - } - - // Map aggregate permissions into the multiple permissions they represent. - $permissions = Permission::aggregate($permissions, [ - Database::PERMISSION_READ, - Database::PERMISSION_UPDATE, - Database::PERMISSION_DELETE, - ]); - - // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); - if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { - foreach (Database::PERMISSIONS as $type) { - foreach ($permissions as $permission) { - $permission = Permission::parse($permission); - if ($permission->getPermission() != $type) { - continue; - } - $role = (new Role( - $permission->getRole(), - $permission->getIdentifier(), - $permission->getDimension() - ))->toString(); - if (!Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); - } - } - } - } - - if (\is_null($permissions)) { - $permissions = $row->getPermissions() ?? []; - } - - $data['$id'] = $rowId; - $data['$permissions'] = $permissions; - $newRow = new Document($data); - - $operations = 0; - - $setTable = (function (Document $collection, Document $document) use (&$setTable, $dbForProject, $database, &$operations) { - - $operations++; - - $relationships = \array_filter( - $collection->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - - $isList = \is_array($related) && \array_values($related) === $related; - - if ($isList) { - $relations = $related; - } else { - $relations = [$related]; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - $relatedTable = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) - ); - - foreach ($relations as &$relation) { - // If the relation is an array it can be either update or create a child document. - if ( - \is_array($relation) - && \array_values($relation) !== $relation - && !isset($relation['$id']) - ) { - $relation['$id'] = ID::unique(); - $relation = new Document($relation); - } - if ($relation instanceof Document) { - $oldRow = Authorization::skip(fn () => $dbForProject->getDocument( - 'database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(), - $relation->getId() - )); - $relation->removeAttribute('$collectionId'); - $relation->removeAttribute('$databaseId'); - // Attribute $collection is required for Utopia. - $relation->setAttribute( - '$collection', - 'database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId() - ); - - if ($oldRow->isEmpty()) { - if (isset($relation['$id']) && $relation['$id'] === 'unique()') { - $relation['$id'] = ID::unique(); - } - } - $setTable($relatedTable, $relation); - } - } - - if ($isList) { - $document->setAttribute($relationship->getAttribute('key'), \array_values($relations)); - } else { - $document->setAttribute($relationship->getAttribute('key'), \reset($relations)); - } - } - }); - - $setTable($table, $newRow); - - $queueForStatsUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); - - $response->addHeader('X-Debug-Operations', $operations); - - try { - $row = $dbForProject->withRequestTimestamp( - $requestTimestamp, - fn () => $dbForProject->updateDocument( - 'database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), - $row->getId(), - $newRow - ) - ); - } catch (AuthorizationException) { - throw new Exception(Exception::USER_UNAUTHORIZED); - } catch (DuplicateException) { - throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); - } catch (StructureException $e) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); - } catch (NotFoundException $e) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - // Add $tableId and $databaseId for all rows - $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) { - $row->setAttribute('$databaseId', $database->getId()); - $row->setAttribute('$collectionId', $table->getId()); - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - $relatedTable = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processRow($relatedTable, $relation); - } - } - } - }; - - $processRow($table, $row); - - $response->dynamic($row, Response::MODEL_DOCUMENT); - - $relationships = \array_map( - fn ($document) => $document->getAttribute('key'), - \array_filter( - $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ) - ); - - $queueForEvents - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('rowId', $row->getId()) - ->setContext('table', $table) - ->setContext('database', $database) - ->setPayload($response->getPayload(), sensitive: $relationships); - }); - -App::delete('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') - ->alias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId') - ->desc('Delete row') - ->groups(['api', 'database']) - ->label('scope', 'documents.write') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].delete') - ->label('audits.event', 'row.delete') - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}/row/{request.rowId}') - ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') - ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) - ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) - ->label('sdk', new Method( - namespace: 'databases', - group: 'rows', - name: 'deleteRow', - description: '/docs/references/databases/delete-document.md', - auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_NOCONTENT, - model: Response::MODEL_NONE, - ) - ], - contentType: ContentType::NONE - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') - ->param('rowId', '', new UID(), 'Row ID.') - ->inject('requestTimestamp') - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->inject('queueForStatsUsage') - ->action(function (string $databaseId, string $tableId, string $rowId, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - - if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - // Read permission should not be required for delete - $row = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); - - if ($row->isEmpty()) { - throw new Exception(Exception::DOCUMENT_NOT_FOUND); - } - - try { - $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $table, $rowId) { - $dbForProject->deleteDocument( - 'database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), - $rowId - ); - }); - } catch (NotFoundException $e) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - // Add $tableId and $databaseId for all rows - $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) { - $row->setAttribute('$databaseId', $database->getId()); - $row->setAttribute('$collectionId', $table->getId()); - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - $relatedTable = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processRow($relatedTable, $relation); - } - } - } - }; - - $processRow($table, $row); - - $queueForStatsUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1); // per collection - - $response->addHeader('X-Debug-Operations', 1); - - $relationships = \array_map( - fn ($document) => $document->getAttribute('key'), - \array_filter( - $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ) - ); - - $queueForEvents - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('rowId', $row->getId()) - ->setContext('table', $table) - ->setContext('database', $database) - ->setPayload($response->output($row, Response::MODEL_DOCUMENT), sensitive: $relationships); - - $response->noContent(); - }); - App::get('/v1/databases/usage') ->desc('Get databases usage stats') ->groups(['api', 'database', 'usage']) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php new file mode 100644 index 0000000000..ab40f4d5e1 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php @@ -0,0 +1,314 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/documents') + ->desc('Create row') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].create') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'row.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', [ + new Method( + namespace: 'databases', + group: 'rows', + name: 'createRow', + description: '/docs/references/databases/create-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_CREATED, + model: UtopiaResponse::MODEL_DOCUMENT, + ) + ], + contentType: ContentType::JSON + ) + ]) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('rowId', '', new CustomId(), 'Row ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define columns before creating rows.') + ->param('data', [], new JSON(), 'Row data as JSON object.') + ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->inject('response') + ->inject('dbForProject') + ->inject('user') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $rowId, string $tableId, string|array $data, ?array $permissions, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage): void + { + $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array + + if (empty($data)) { + throw new Exception(Exception::DOCUMENT_MISSING_DATA); + } + + if (isset($data['$id'])) { + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is not allowed for creating new documents, try update instead'); + } + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); + + if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $allowedPermissions = [ + Database::PERMISSION_READ, + Database::PERMISSION_UPDATE, + Database::PERMISSION_DELETE, + ]; + + // Map aggregate permissions to into the set of individual permissions they represent. + $permissions = Permission::aggregate($permissions, $allowedPermissions); + + // Add permissions for current the user if none were provided. + if (\is_null($permissions)) { + $permissions = []; + if (!empty($user->getId())) { + foreach ($allowedPermissions as $permission) { + $permissions[] = (new Permission($permission, 'user', $user->getId()))->toString(); + } + } + } + + // Users can only manage their own roles, API keys and Admin users can manage any + if (!$isAPIKey && !$isPrivilegedUser) { + foreach (Database::PERMISSIONS as $type) { + foreach ($permissions as $permission) { + $permission = Permission::parse($permission); + if ($permission->getPermission() != $type) { + continue; + } + $role = (new Role( + $permission->getRole(), + $permission->getIdentifier(), + $permission->getDimension() + ))->toString(); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')'); + } + } + } + } + + $data['$collection'] = $table->getId(); // Adding this param to make API easier for developers + $data['$id'] = $rowId == 'unique()' ? ID::unique() : $rowId; + $data['$permissions'] = $permissions; + $row = new Document($data); + + $operations = 0; + + $checkPermissions = function (Document $table, Document $row, string $permission) use (&$checkPermissions, $dbForProject, $database, &$operations) { + $operations++; + + $documentSecurity = $table->getAttribute('documentSecurity', false); + $validator = new Authorization($permission); + + $valid = $validator->isValid($table->getPermissionsByType($permission)); + if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } + + if ($permission === Database::PERMISSION_UPDATE) { + $valid = $valid || $validator->isValid($row->getUpdate()); + if ($documentSecurity && !$valid) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } + } + + $relationships = \array_filter( + $table->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $row->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + + $isList = \is_array($related) && \array_values($related) === $related; + + if ($isList) { + $relations = $related; + } else { + $relations = [$related]; + } + + $relatedTableId = $relationship->getAttribute('relatedCollection'); + $relatedTable = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) + ); + + foreach ($relations as &$relation) { + if ( + \is_array($relation) + && \array_values($relation) !== $relation + && !isset($relation['$id']) + ) { + $relation['$id'] = ID::unique(); + $relation = new Document($relation); + } + if ($relation instanceof Document) { + $current = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(), $relation->getId()) + ); + + if ($current->isEmpty()) { + $type = Database::PERMISSION_CREATE; + + if (isset($relation['$id']) && $relation['$id'] === 'unique()') { + $relation['$id'] = ID::unique(); + } + } else { + $relation->removeAttribute('$collectionId'); + $relation->removeAttribute('$databaseId'); + $relation->setAttribute('$collection', $relatedTable->getId()); + $type = Database::PERMISSION_UPDATE; + } + + $checkPermissions($relatedTable, $relation, $type); + } + } + + if ($isList) { + $row->setAttribute($relationship->getAttribute('key'), \array_values($relations)); + } else { + $row->setAttribute($relationship->getAttribute('key'), \reset($relations)); + } + } + }; + + $checkPermissions($table, $row, Database::PERMISSION_CREATE); + + try { + $row = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $row); + } catch (StructureException $e) { + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); + } catch (DuplicateException) { + throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); + } catch (NotFoundException) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + + // Add $tableId and $databaseId for all rows + $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) { + $row->setAttribute('$databaseId', $database->getId()); + $row->setAttribute('$collectionId', $table->getId()); + + $relationships = \array_filter( + $table->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $row->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + if (!\is_array($related)) { + $related = [$related]; + } + + $relatedTableId = $relationship->getAttribute('relatedCollection'); + $relatedTable = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) + ); + + foreach ($related as $relation) { + if ($relation instanceof Document) { + $processRow($relatedTable, $relation); + } + } + } + }; + + $processRow($table, $row); + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); // per collection + + $response->addHeader('X-Debug-Operations', $operations); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) + ->dynamic($row, UtopiaResponse::MODEL_DOCUMENT); + + $relationships = \array_map( + fn ($document) => $document->getAttribute('key'), + \array_filter( + $table->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ) + ); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setParam('tableId', $table->getId()) + ->setParam('rowId', $row->getId()) + ->setContext('table', $table) + ->setContext('database', $database) + ->setPayload($response->getPayload(), sensitive: $relationships); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php new file mode 100644 index 0000000000..61ed961c64 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php @@ -0,0 +1,167 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId') + ->desc('Delete row') + ->groups(['api', 'database']) + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].delete') + ->label('audits.event', 'row.delete') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}/row/{request.rowId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: 'databases', + group: 'rows', + name: 'deleteRow', + description: '/docs/references/databases/delete-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_NOCONTENT, + model: UtopiaResponse::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('rowId', '', new UID(), 'Row ID.') + ->inject('requestTimestamp') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, string $rowId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); + + if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + // Read permission should not be required for delete + $row = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); + + if ($row->isEmpty()) { + throw new Exception(Exception::DOCUMENT_NOT_FOUND); + } + + try { + $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $table, $rowId) { + $dbForProject->deleteDocument( + 'database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), + $rowId + ); + }); + } catch (NotFoundException) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + // Add $tableId and $databaseId for all rows + $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) { + $row->setAttribute('$databaseId', $database->getId()); + $row->setAttribute('$collectionId', $table->getId()); + + $relationships = \array_filter( + $table->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $row->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + if (!\is_array($related)) { + $related = [$related]; + } + + $relatedTableId = $relationship->getAttribute('relatedCollection'); + $relatedTable = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) + ); + + foreach ($related as $relation) { + if ($relation instanceof Document) { + $processRow($relatedTable, $relation); + } + } + } + }; + + $processRow($table, $row); + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1); // per collection + + $response->addHeader('X-Debug-Operations', 1); + + $relationships = \array_map( + fn ($document) => $document->getAttribute('key'), + \array_filter( + $table->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ) + ); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setParam('tableId', $table->getId()) + ->setParam('rowId', $row->getId()) + ->setContext('table', $table) + ->setContext('database', $database) + ->setPayload($response->output($row, UtopiaResponse::MODEL_DOCUMENT), sensitive: $relationships); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php new file mode 100644 index 0000000000..a3a484be70 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php @@ -0,0 +1,154 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId') + ->desc('Get row') + ->groups(['api', 'database']) + ->label('scope', 'documents.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'rows', + name: 'getRow', + description: '/docs/references/databases/get-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_DOCUMENT, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('rowId', '', new UID(), 'Row ID.') + ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForStatsUsage') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, string $rowId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); + + if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + try { + $queries = Query::parseQueries($queries); + $row = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId, $queries); + } catch (AuthorizationException) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + if ($row->isEmpty()) { + throw new Exception(Exception::DOCUMENT_NOT_FOUND); + } + + $operations = 0; + + // Add $tableId and $databaseId for all rows + $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database, &$operations) { + if ($row->isEmpty()) { + return; + } + + $operations++; + + $row->setAttribute('$databaseId', $database->getId()); + $row->setAttribute('$collectionId', $table->getId()); + + $relationships = \array_filter( + $table->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $row->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + + continue; + } + + if (!\is_array($related)) { + $related = [$related]; + } + + $relatedTableId = $relationship->getAttribute('relatedCollection'); + $relatedTable = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) + ); + + foreach ($related as $relation) { + if ($relation instanceof Document) { + $processRow($relatedTable, $relation); + } + } + } + }; + + $processRow($table, $row); + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); + + $response->addHeader('X-Debug-Operations', $operations); + + $response->dynamic($row, UtopiaResponse::MODEL_DOCUMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php new file mode 100644 index 0000000000..02358be8f2 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php @@ -0,0 +1,159 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId/logs') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId/logs') + ->desc('List row logs') + ->groups(['api', 'database']) + ->label('scope', 'documents.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'logs', + name: 'listRowLogs', + description: '/docs/references/databases/get-document-logs.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_LOG_LIST, + ) + ], + contentType: ContentType::JSON, + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Collection ID.') + ->param('rowId', '', new UID(), 'Row ID.') + ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) + ->inject('response') + ->inject('dbForProject') + ->inject('locale') + ->inject('geodb') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, string $rowId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $row = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId); + + if ($row->isEmpty()) { + throw new Exception(Exception::DOCUMENT_NOT_FOUND); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); + + $audit = new Audit($dbForProject); + $resource = 'database/' . $databaseId . '/table/' . $tableId . '/row/' . $row->getId(); + $logs = $audit->getLogsByResource($resource, $queries); + + $output = []; + + foreach ($logs as $i => &$log) { + $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + + $detector = new Detector($log['userAgent']); + $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) + + $os = $detector->getOS(); + $client = $detector->getClient(); + $device = $detector->getDevice(); + + $output[$i] = new Document([ + 'event' => $log['event'], + 'userId' => $log['data']['userId'], + 'userEmail' => $log['data']['userEmail'] ?? null, + 'userName' => $log['data']['userName'] ?? null, + 'mode' => $log['data']['mode'] ?? null, + 'ip' => $log['ip'], + 'time' => $log['time'], + 'osCode' => $os['osCode'], + 'osName' => $os['osName'], + 'osVersion' => $os['osVersion'], + 'clientType' => $client['clientType'], + 'clientCode' => $client['clientCode'], + 'clientName' => $client['clientName'], + 'clientVersion' => $client['clientVersion'], + 'clientEngine' => $client['clientEngine'], + 'clientEngineVersion' => $client['clientEngineVersion'], + 'deviceName' => $device['deviceName'], + 'deviceBrand' => $device['deviceBrand'], + 'deviceModel' => $device['deviceModel'] + ]); + + $record = $geodb->get($log['ip']); + + if ($record) { + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + } else { + $output[$i]['countryCode'] = '--'; + $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); + } + } + + $response->dynamic(new Document([ + 'total' => $audit->countLogsByResource($resource, $queries), + 'logs' => $output, + ]), UtopiaResponse::MODEL_LOG_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php new file mode 100644 index 0000000000..bc41118206 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php @@ -0,0 +1,302 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId') + ->desc('Update row') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].update') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'row.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}/row/{response.$id}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: 'databases', + group: 'rows', + name: 'updateRow', + description: '/docs/references/databases/update-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_DOCUMENT, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Collection ID.') + ->param('rowId', '', new UID(), 'Row ID.') + ->param('data', [], new JSON(), 'Row data as JSON object. Include only columns and value pairs to be updated.', true) + ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->inject('requestTimestamp') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, string $rowId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): void + { + + $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array + + if (empty($data) && \is_null($permissions)) { + throw new Exception(Exception::DOCUMENT_MISSING_PAYLOAD); + } + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); + + if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + // Read permission should not be required for update + /** @var Document $row */ + $row = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); + + if ($row->isEmpty()) { + throw new Exception(Exception::DOCUMENT_NOT_FOUND); + } + + // Map aggregate permissions into the multiple permissions they represent. + $permissions = Permission::aggregate($permissions, [ + Database::PERMISSION_READ, + Database::PERMISSION_UPDATE, + Database::PERMISSION_DELETE, + ]); + + // Users can only manage their own roles, API keys and Admin users can manage any + $roles = Authorization::getRoles(); + if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { + foreach (Database::PERMISSIONS as $type) { + foreach ($permissions as $permission) { + $permission = Permission::parse($permission); + if ($permission->getPermission() != $type) { + continue; + } + $role = (new Role( + $permission->getRole(), + $permission->getIdentifier(), + $permission->getDimension() + ))->toString(); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); + } + } + } + } + + if (\is_null($permissions)) { + $permissions = $row->getPermissions() ?? []; + } + + $data['$id'] = $rowId; + $data['$permissions'] = $permissions; + $newRow = new Document($data); + + $operations = 0; + + $setTable = (function (Document $collection, Document $document) use (&$setTable, $dbForProject, $database, &$operations) { + + $operations++; + + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + + $isList = \is_array($related) && \array_values($related) === $related; + + if ($isList) { + $relations = $related; + } else { + $relations = [$related]; + } + + $relatedTableId = $relationship->getAttribute('relatedCollection'); + $relatedTable = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) + ); + + foreach ($relations as &$relation) { + // If the relation is an array it can be either update or create a child document. + if ( + \is_array($relation) + && \array_values($relation) !== $relation + && !isset($relation['$id']) + ) { + $relation['$id'] = ID::unique(); + $relation = new Document($relation); + } + if ($relation instanceof Document) { + $oldRow = Authorization::skip(fn () => $dbForProject->getDocument( + 'database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(), + $relation->getId() + )); + $relation->removeAttribute('$collectionId'); + $relation->removeAttribute('$databaseId'); + // Attribute $collection is required for Utopia. + $relation->setAttribute( + '$collection', + 'database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId() + ); + + if ($oldRow->isEmpty()) { + if (isset($relation['$id']) && $relation['$id'] === 'unique()') { + $relation['$id'] = ID::unique(); + } + } + $setTable($relatedTable, $relation); + } + } + + if ($isList) { + $document->setAttribute($relationship->getAttribute('key'), \array_values($relations)); + } else { + $document->setAttribute($relationship->getAttribute('key'), \reset($relations)); + } + } + }); + + $setTable($table, $newRow); + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); + + $response->addHeader('X-Debug-Operations', $operations); + + try { + $row = $dbForProject->withRequestTimestamp( + $requestTimestamp, + fn () => $dbForProject->updateDocument( + 'database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), + $row->getId(), + $newRow + ) + ); + } catch (AuthorizationException) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } catch (DuplicateException) { + throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); + } catch (StructureException $e) { + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); + } catch (NotFoundException) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + // Add $tableId and $databaseId for all rows + $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) { + $row->setAttribute('$databaseId', $database->getId()); + $row->setAttribute('$collectionId', $table->getId()); + + $relationships = \array_filter( + $table->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $row->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + if (!\is_array($related)) { + $related = [$related]; + } + + $relatedTableId = $relationship->getAttribute('relatedCollection'); + $relatedTable = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) + ); + + foreach ($related as $relation) { + if ($relation instanceof Document) { + $processRow($relatedTable, $relation); + } + } + } + }; + + $processRow($table, $row); + + $response->dynamic($row, UtopiaResponse::MODEL_DOCUMENT); + + $relationships = \array_map( + fn ($document) => $document->getAttribute('key'), + \array_filter( + $table->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ) + ); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setParam('tableId', $table->getId()) + ->setParam('rowId', $row->getId()) + ->setContext('table', $table) + ->setContext('database', $database) + ->setPayload($response->getPayload(), sensitive: $relationships); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php new file mode 100644 index 0000000000..b27930405f --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php @@ -0,0 +1,223 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/documents') + ->desc('List rows') + ->groups(['api', 'database']) + ->label('scope', 'documents.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'rows', + name: 'listRows', + description: '/docs/references/databases/list-documents.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_DOCUMENT_LIST, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForStatsUsage') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); + + if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + + $cursor = \reset($cursor); + + if ($cursor) { + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $rowId = $cursor->getValue(); + + $cursorRow = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); + + if ($cursorRow->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Row '{$rowId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorRow); + } + try { + $rows = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $queries); + $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $queries, APP_LIMIT_COUNT); + } catch (OrderException $e) { + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); + } + + $operations = 0; + + // Add $tableId and $databaseId for all rows + $processRow = (function (Document $table, Document $row) use (&$processRow, $dbForProject, $database, &$operations): bool { + if ($row->isEmpty()) { + return false; + } + + $operations++; + + $row->removeAttribute('$collection'); + $row->setAttribute('$databaseId', $database->getId()); + $row->setAttribute('$collectionId', $table->getId()); + + $relationships = \array_filter( + $table->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $row->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + + continue; + } + + if (!\is_array($related)) { + $relations = [$related]; + } else { + $relations = $related; + } + + $relatedTableId = $relationship->getAttribute('relatedCollection'); + // todo: Use local cache for this getDocument + $relatedTable = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId)); + + foreach ($relations as $index => $doc) { + if ($doc instanceof Document) { + if (!$processRow($relatedTable, $doc)) { + unset($relations[$index]); + } + } + } + + if (\is_array($related)) { + $row->setAttribute($relationship->getAttribute('key'), \array_values($relations)); + } elseif (empty($relations)) { + $row->setAttribute($relationship->getAttribute('key'), null); + } + } + + return true; + }); + + foreach ($rows as $row) { + $processRow($table, $row); + } + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); + + $response->addHeader('X-Debug-Operations', $operations); + + $select = \array_reduce($queries, function ($result, $query) { + return $result || ($query->getMethod() === Query::TYPE_SELECT); + }, false); + + // Check if the SELECT query includes $databaseId and $collectionId + $hasDatabaseId = false; + $hasTableId = false; + if ($select) { + $hasDatabaseId = \array_reduce($queries, function ($result, $query) { + return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$databaseId', $query->getValues())); + }, false); + $hasTableId = \array_reduce($queries, function ($result, $query) { + return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$collectionId', $query->getValues())); + }, false); + } + + if ($select) { + foreach ($rows as $row) { + if (!$hasDatabaseId) { + $row->removeAttribute('$databaseId'); + } + if (!$hasTableId) { + $row->removeAttribute('$collectionId'); + } + } + } + + $response->dynamic(new Document([ + 'total' => $total, + 'documents' => $rows, + ]), UtopiaResponse::MODEL_DOCUMENT_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Http.php b/src/Appwrite/Platform/Modules/Databases/Services/Http.php index 045dc6ff42..17dd715906 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Http.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Http.php @@ -35,6 +35,12 @@ use Appwrite\Platform\Modules\Databases\Http\Indexes\Create as CreateIndex; use Appwrite\Platform\Modules\Databases\Http\Indexes\Delete as DeleteIndex; use Appwrite\Platform\Modules\Databases\Http\Indexes\Get as GetIndex; use Appwrite\Platform\Modules\Databases\Http\Indexes\XList as ListIndexes; +use Appwrite\Platform\Modules\Databases\Http\Rows\Create as CreateRow; +use Appwrite\Platform\Modules\Databases\Http\Rows\Delete as DeleteRow; +use Appwrite\Platform\Modules\Databases\Http\Rows\Get as GetRow; +use Appwrite\Platform\Modules\Databases\Http\Rows\Logs\XList as ListRowLogs; +use Appwrite\Platform\Modules\Databases\Http\Rows\Update as UpdateRow; +use Appwrite\Platform\Modules\Databases\Http\Rows\XList as ListRows; use Appwrite\Platform\Modules\Databases\Http\Tables\Create as CreateTable; use Appwrite\Platform\Modules\Databases\Http\Tables\Delete as DeleteTable; use Appwrite\Platform\Modules\Databases\Http\Tables\Get as GetTable; @@ -134,6 +140,11 @@ class Http extends Service private function registerRowActions(): void { - + $this->addAction(CreateRow::getName(), new CreateRow()); + $this->addAction(GetRow::getName(), new GetRow()); + $this->addAction(UpdateRow::getName(), new UpdateRow()); + $this->addAction(DeleteRow::getName(), new DeleteRow()); + $this->addAction(ListRows::getName(), new ListRows()); + $this->addAction(ListRowLogs::getName(), new ListRowLogs()); } } From 4cd8f49f829aa2612ccfff40884f744f4fa2e078 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 18:09:39 +0530 Subject: [PATCH 035/343] add: usage. --- .../Databases/Http/Databases/Usage/Get.php | 138 ++++++++++++++++++ .../Databases/Http/Databases/Usage/XList.php | 132 +++++++++++++++++ .../Databases/Http/Tables/Usage/Get.php | 131 +++++++++++++++++ .../Modules/Databases/Services/Http.php | 6 + 4 files changed, 407 insertions(+) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php new file mode 100644 index 0000000000..c4105effa0 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -0,0 +1,138 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/usage') + ->desc('Get database usage stats') + ->groups(['api', 'database', 'usage']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: null, + name: 'getUsage', + description: '/docs/references/databases/get-database-usage.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_USAGE_DATABASE, + ) + ], + contentType: ContentType::JSON, + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $range, UtopiaResponse $response, Database $dbForProject): void + { + $database = $dbForProject->getDocument('databases', $databaseId); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $periods = Config::getParam('usage', []); + $stats = $usage = []; + $days = $periods[$range]; + $metrics = [ + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS), + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS), + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_STORAGE), + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASES_OPERATIONS_READS), + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASES_OPERATIONS_WRITES) + ]; + + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + foreach ($metrics as $metric) { + $result = $dbForProject->findOne('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', ['inf']) + ]); + + $stats[$metric]['total'] = $result['value'] ?? 0; + $limit = $days['limit']; + $period = $days['period']; + $results = $dbForProject->find('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', [$period]), + Query::limit($limit), + Query::orderDesc('time'), + ]); + $stats[$metric]['data'] = []; + foreach ($results as $result) { + $stats[$metric]['data'][$result->getAttribute('time')] = [ + 'value' => $result->getAttribute('value'), + ]; + } + } + }); + + $format = match ($days['period']) { + '1h' => 'Y-m-d\TH:00:00.000P', + '1d' => 'Y-m-d\T00:00:00.000P', + }; + + foreach ($metrics as $metric) { + $usage[$metric]['total'] = $stats[$metric]['total']; + $usage[$metric]['data'] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric]['data'][] = [ + 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } + } + + $response->dynamic(new Document([ + 'range' => $range, + 'collectionsTotal' => $usage[$metrics[0]]['total'], + 'documentsTotal' => $usage[$metrics[1]]['total'], + 'storageTotal' => $usage[$metrics[2]]['total'], + 'databaseReadsTotal' => $usage[$metrics[3]]['total'], + 'databaseWritesTotal' => $usage[$metrics[4]]['total'], + 'collections' => $usage[$metrics[0]]['data'], + 'documents' => $usage[$metrics[1]]['data'], + 'storage' => $usage[$metrics[2]]['data'], + 'databaseReads' => $usage[$metrics[3]]['data'], + 'databaseWrites' => $usage[$metrics[4]]['data'], + ]), UtopiaResponse::MODEL_USAGE_DATABASE); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php new file mode 100644 index 0000000000..0078d54a4b --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -0,0 +1,132 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/usage') + ->desc('Get databases usage stats') + ->groups(['api', 'database', 'usage']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: null, + name: 'listUsages', + description: '/docs/references/databases/get-usage.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_USAGE_DATABASES, + ) + ], + contentType: ContentType::JSON + )) + ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $range, UtopiaResponse $response, Database $dbForProject): void + { + + $periods = Config::getParam('usage', []); + $stats = $usage = []; + $days = $periods[$range]; + $metrics = [ + METRIC_DATABASES, + METRIC_COLLECTIONS, + METRIC_DOCUMENTS, + METRIC_DATABASES_STORAGE, + METRIC_DATABASES_OPERATIONS_READS, + METRIC_DATABASES_OPERATIONS_WRITES, + ]; + + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + foreach ($metrics as $metric) { + $result = $dbForProject->findOne('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', ['inf']) + ]); + + $stats[$metric]['total'] = $result['value'] ?? 0; + $limit = $days['limit']; + $period = $days['period']; + $results = $dbForProject->find('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', [$period]), + Query::limit($limit), + Query::orderDesc('time'), + ]); + $stats[$metric]['data'] = []; + foreach ($results as $result) { + $stats[$metric]['data'][$result->getAttribute('time')] = [ + 'value' => $result->getAttribute('value'), + ]; + } + } + }); + + $format = match ($days['period']) { + '1h' => 'Y-m-d\TH:00:00.000P', + '1d' => 'Y-m-d\T00:00:00.000P', + }; + + foreach ($metrics as $metric) { + $usage[$metric]['total'] = $stats[$metric]['total']; + $usage[$metric]['data'] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric]['data'][] = [ + 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } + } + $response->dynamic(new Document([ + 'range' => $range, + 'databasesTotal' => $usage[$metrics[0]]['total'], + 'collectionsTotal' => $usage[$metrics[1]]['total'], + 'documentsTotal' => $usage[$metrics[2]]['total'], + 'storageTotal' => $usage[$metrics[3]]['total'], + 'databasesReadsTotal' => $usage[$metrics[4]]['total'], + 'databasesWritesTotal' => $usage[$metrics[5]]['total'], + 'databases' => $usage[$metrics[0]]['data'], + 'collections' => $usage[$metrics[1]]['data'], + 'documents' => $usage[$metrics[2]]['data'], + 'storage' => $usage[$metrics[3]]['data'], + 'databasesReads' => $usage[$metrics[4]]['data'], + 'databasesWrites' => $usage[$metrics[5]]['data'], + ]), UtopiaResponse::MODEL_USAGE_DATABASES); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php new file mode 100644 index 0000000000..3943c27618 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php @@ -0,0 +1,131 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/usage') + ->httpAlias('/v1/databases/:databaseId/collections/:tableId/usage') + ->desc('Get table usage stats') + ->groups(['api', 'database', 'usage']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: null, + name: 'getTableUsage', + description: '/docs/references/databases/get-collection-usage.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: UtopiaResponse::MODEL_USAGE_COLLECTION, + ) + ], + contentType: ContentType::JSON, + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) + ->param('tableId', '', new UID(), 'Collection ID.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $range, string $tableId, UtopiaResponse $response, Database $dbForProject): void + { + + $database = $dbForProject->getDocument('databases', $databaseId); + $tableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $tableDocument->getInternalId()); + + if ($table->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + $periods = Config::getParam('usage', []); + $stats = $usage = []; + $days = $periods[$range]; + $metrics = [ + str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $tableDocument->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), + ]; + + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + foreach ($metrics as $metric) { + $result = $dbForProject->findOne('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', ['inf']) + ]); + + $stats[$metric]['total'] = $result['value'] ?? 0; + $limit = $days['limit']; + $period = $days['period']; + $results = $dbForProject->find('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', [$period]), + Query::limit($limit), + Query::orderDesc('time'), + ]); + $stats[$metric]['data'] = []; + foreach ($results as $result) { + $stats[$metric]['data'][$result->getAttribute('time')] = [ + 'value' => $result->getAttribute('value'), + ]; + } + } + }); + + $format = match ($days['period']) { + '1h' => 'Y-m-d\TH:00:00.000P', + '1d' => 'Y-m-d\T00:00:00.000P', + }; + + foreach ($metrics as $metric) { + $usage[$metric]['total'] = $stats[$metric]['total']; + $usage[$metric]['data'] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric]['data'][] = [ + 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } + } + + $response->dynamic(new Document([ + 'range' => $range, + 'documentsTotal' => $usage[$metrics[0]]['total'], + 'documents' => $usage[$metrics[0]]['data'], + ]), UtopiaResponse::MODEL_USAGE_COLLECTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Http.php b/src/Appwrite/Platform/Modules/Databases/Services/Http.php index 17dd715906..ffdd4f1903 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Http.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Http.php @@ -30,6 +30,8 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Delete as DeleteDatabase; use Appwrite\Platform\Modules\Databases\Http\Databases\Get as GetDatabase; use Appwrite\Platform\Modules\Databases\Http\Databases\Logs\XList as ListDatabaseLogs; use Appwrite\Platform\Modules\Databases\Http\Databases\Update as UpdateDatabase; +use Appwrite\Platform\Modules\Databases\Http\Databases\Usage\Get as GetDatabaseUsage; +use Appwrite\Platform\Modules\Databases\Http\Databases\Usage\XList as ListDatabaseUsage; use Appwrite\Platform\Modules\Databases\Http\Databases\XList as ListDatabases; use Appwrite\Platform\Modules\Databases\Http\Indexes\Create as CreateIndex; use Appwrite\Platform\Modules\Databases\Http\Indexes\Delete as DeleteIndex; @@ -46,6 +48,7 @@ use Appwrite\Platform\Modules\Databases\Http\Tables\Delete as DeleteTable; use Appwrite\Platform\Modules\Databases\Http\Tables\Get as GetTable; use Appwrite\Platform\Modules\Databases\Http\Tables\Logs\XList as ListTableLogs; use Appwrite\Platform\Modules\Databases\Http\Tables\Update as UpdateTable; +use Appwrite\Platform\Modules\Databases\Http\Tables\Usage\Get as GetTableUsage; use Appwrite\Platform\Modules\Databases\Http\Tables\XList as ListTables; use Utopia\Platform\Service; @@ -70,6 +73,8 @@ class Http extends Service $this->addAction(DeleteDatabase::getName(), new DeleteDatabase()); $this->addAction(ListDatabases::getName(), new ListDatabases()); $this->addAction(ListDatabaseLogs::getName(), new ListDatabaseLogs()); + $this->addAction(GetDatabaseUsage::getName(), new GetDatabaseUsage()); + $this->addAction(ListDatabaseUsage::getName(), new ListDatabaseUsage()); } private function registerTableActions(): void @@ -80,6 +85,7 @@ class Http extends Service $this->addAction(DeleteTable::getName(), new DeleteTable()); $this->addAction(ListTables::getName(), new ListTables()); $this->addAction(ListTableLogs::getName(), new ListTableLogs()); + $this->addAction(GetTableUsage::getName(), new GetTableUsage()); } private function registerColumnActions(): void From 57a9218649a3185581943e7f2e17c16a612fa5f4 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 18:10:09 +0530 Subject: [PATCH 036/343] =?UTF-8?q?remove:=20database=20controller=20?= =?UTF-8?q?=F0=9F=91=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/api/databases.php | 306 ------------------------------ 1 file changed, 306 deletions(-) delete mode 100644 app/controllers/api/databases.php diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php deleted file mode 100644 index 1f18d2fa1e..0000000000 --- a/app/controllers/api/databases.php +++ /dev/null @@ -1,306 +0,0 @@ -desc('Get databases usage stats') - ->groups(['api', 'database', 'usage']) - ->label('scope', 'collections.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: null, - name: 'getUsage', - description: '/docs/references/databases/get-usage.md', - auth: [AuthType::ADMIN], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_USAGE_DATABASES, - ) - ], - contentType: ContentType::JSON - )) - ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), '`Date range.', true) - ->inject('response') - ->inject('dbForProject') - ->action(function (string $range, Response $response, Database $dbForProject) { - - $periods = Config::getParam('usage', []); - $stats = $usage = []; - $days = $periods[$range]; - $metrics = [ - METRIC_DATABASES, - METRIC_COLLECTIONS, - METRIC_DOCUMENTS, - METRIC_DATABASES_STORAGE, - METRIC_DATABASES_OPERATIONS_READS, - METRIC_DATABASES_OPERATIONS_WRITES, - ]; - - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { - foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ - Query::equal('metric', [$metric]), - Query::equal('period', ['inf']) - ]); - - $stats[$metric]['total'] = $result['value'] ?? 0; - $limit = $days['limit']; - $period = $days['period']; - $results = $dbForProject->find('stats', [ - Query::equal('metric', [$metric]), - Query::equal('period', [$period]), - Query::limit($limit), - Query::orderDesc('time'), - ]); - $stats[$metric]['data'] = []; - foreach ($results as $result) { - $stats[$metric]['data'][$result->getAttribute('time')] = [ - 'value' => $result->getAttribute('value'), - ]; - } - } - }); - - $format = match ($days['period']) { - '1h' => 'Y-m-d\TH:00:00.000P', - '1d' => 'Y-m-d\T00:00:00.000P', - }; - - foreach ($metrics as $metric) { - $usage[$metric]['total'] = $stats[$metric]['total']; - $usage[$metric]['data'] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric]['data'][] = [ - 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } - } - $response->dynamic(new Document([ - 'range' => $range, - 'databasesTotal' => $usage[$metrics[0]]['total'], - 'collectionsTotal' => $usage[$metrics[1]]['total'], - 'documentsTotal' => $usage[$metrics[2]]['total'], - 'storageTotal' => $usage[$metrics[3]]['total'], - 'databasesReadsTotal' => $usage[$metrics[4]]['total'], - 'databasesWritesTotal' => $usage[$metrics[5]]['total'], - 'databases' => $usage[$metrics[0]]['data'], - 'collections' => $usage[$metrics[1]]['data'], - 'documents' => $usage[$metrics[2]]['data'], - 'storage' => $usage[$metrics[3]]['data'], - 'databasesReads' => $usage[$metrics[4]]['data'], - 'databasesWrites' => $usage[$metrics[5]]['data'], - ]), Response::MODEL_USAGE_DATABASES); - }); - -App::get('/v1/databases/:databaseId/usage') - ->desc('Get database usage stats') - ->groups(['api', 'database', 'usage']) - ->label('scope', 'collections.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: null, - name: 'getDatabaseUsage', - description: '/docs/references/databases/get-database-usage.md', - auth: [AuthType::ADMIN], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_USAGE_DATABASE, - ) - ], - contentType: ContentType::JSON, - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), '`Date range.', true) - ->inject('response') - ->inject('dbForProject') - ->action(function (string $databaseId, string $range, Response $response, Database $dbForProject) { - - $database = $dbForProject->getDocument('databases', $databaseId); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $periods = Config::getParam('usage', []); - $stats = $usage = []; - $days = $periods[$range]; - $metrics = [ - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_STORAGE), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASES_OPERATIONS_READS), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASES_OPERATIONS_WRITES) - ]; - - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { - foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ - Query::equal('metric', [$metric]), - Query::equal('period', ['inf']) - ]); - - $stats[$metric]['total'] = $result['value'] ?? 0; - $limit = $days['limit']; - $period = $days['period']; - $results = $dbForProject->find('stats', [ - Query::equal('metric', [$metric]), - Query::equal('period', [$period]), - Query::limit($limit), - Query::orderDesc('time'), - ]); - $stats[$metric]['data'] = []; - foreach ($results as $result) { - $stats[$metric]['data'][$result->getAttribute('time')] = [ - 'value' => $result->getAttribute('value'), - ]; - } - } - }); - - $format = match ($days['period']) { - '1h' => 'Y-m-d\TH:00:00.000P', - '1d' => 'Y-m-d\T00:00:00.000P', - }; - - foreach ($metrics as $metric) { - $usage[$metric]['total'] = $stats[$metric]['total']; - $usage[$metric]['data'] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric]['data'][] = [ - 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } - } - - $response->dynamic(new Document([ - 'range' => $range, - 'collectionsTotal' => $usage[$metrics[0]]['total'], - 'documentsTotal' => $usage[$metrics[1]]['total'], - 'storageTotal' => $usage[$metrics[2]]['total'], - 'databaseReadsTotal' => $usage[$metrics[3]]['total'], - 'databaseWritesTotal' => $usage[$metrics[4]]['total'], - 'collections' => $usage[$metrics[0]]['data'], - 'documents' => $usage[$metrics[1]]['data'], - 'storage' => $usage[$metrics[2]]['data'], - 'databaseReads' => $usage[$metrics[3]]['data'], - 'databaseWrites' => $usage[$metrics[4]]['data'], - ]), Response::MODEL_USAGE_DATABASE); - }); - -App::get('/v1/databases/:databaseId/tables/:tableId/usage') - ->alias('/v1/databases/:databaseId/collections/:tableId/usage') - ->desc('Get table usage stats') - ->groups(['api', 'database', 'usage']) - ->label('scope', 'collections.read') - ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk', new Method( - namespace: 'databases', - group: null, - name: 'getTableUsage', - description: '/docs/references/databases/get-collection-usage.md', - auth: [AuthType::ADMIN], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_USAGE_COLLECTION, - ) - ], - contentType: ContentType::JSON, - )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) - ->param('tableId', '', new UID(), 'Collection ID.') - ->inject('response') - ->inject('dbForProject') - ->action(function (string $databaseId, string $range, string $tableId, Response $response, Database $dbForProject) { - - $database = $dbForProject->getDocument('databases', $databaseId); - $tableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $tableDocument->getInternalId()); - - if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - - $periods = Config::getParam('usage', []); - $stats = $usage = []; - $days = $periods[$range]; - $metrics = [ - str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $tableDocument->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), - ]; - - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { - foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ - Query::equal('metric', [$metric]), - Query::equal('period', ['inf']) - ]); - - $stats[$metric]['total'] = $result['value'] ?? 0; - $limit = $days['limit']; - $period = $days['period']; - $results = $dbForProject->find('stats', [ - Query::equal('metric', [$metric]), - Query::equal('period', [$period]), - Query::limit($limit), - Query::orderDesc('time'), - ]); - $stats[$metric]['data'] = []; - foreach ($results as $result) { - $stats[$metric]['data'][$result->getAttribute('time')] = [ - 'value' => $result->getAttribute('value'), - ]; - } - } - }); - - $format = match ($days['period']) { - '1h' => 'Y-m-d\TH:00:00.000P', - '1d' => 'Y-m-d\T00:00:00.000P', - }; - - foreach ($metrics as $metric) { - $usage[$metric]['total'] = $stats[$metric]['total']; - $usage[$metric]['data'] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric]['data'][] = [ - 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } - } - - $response->dynamic(new Document([ - 'range' => $range, - 'documentsTotal' => $usage[$metrics[0]]['total'], - 'documents' => $usage[$metrics[0]]['data'], - ]), Response::MODEL_USAGE_COLLECTION); - }); From ad16bd281e18c0a767c53560b181a4cf0e5933c8 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 18:16:08 +0530 Subject: [PATCH 037/343] add: database module to platform registry. --- src/Appwrite/Platform/Appwrite.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Appwrite/Platform/Appwrite.php b/src/Appwrite/Platform/Appwrite.php index ae3d4d6646..b2a92fcc00 100644 --- a/src/Appwrite/Platform/Appwrite.php +++ b/src/Appwrite/Platform/Appwrite.php @@ -4,6 +4,7 @@ namespace Appwrite\Platform; use Appwrite\Platform\Modules\Console; use Appwrite\Platform\Modules\Core; +use Appwrite\Platform\Modules\Databases; use Appwrite\Platform\Modules\Functions; use Appwrite\Platform\Modules\Projects; use Appwrite\Platform\Modules\Proxy; @@ -16,6 +17,7 @@ class Appwrite extends Platform public function __construct() { parent::__construct(new Core()); + $this->addModule(new Databases\Module()); $this->addModule(new Projects\Module()); $this->addModule(new Functions\Module()); $this->addModule(new Sites\Module()); From 6fac164d4646e5e51c872412218ea1a1f29826df Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 18:18:28 +0530 Subject: [PATCH 038/343] update: keep message same. --- .../Modules/Databases/Http/Columns/Relationship/Create.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php index 32cb235b62..09efdd14f9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php @@ -128,7 +128,7 @@ class Create extends ColumnAction \strtolower($column->getAttribute('options')['twoWayKey']) === \strtolower($twoWayKey) && $column->getAttribute('options')['relatedCollection'] === $relatedTable->getId() ) { - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Attribute with the requested key already exists. Attribute keys must be unique.'); + throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.'); } if ( From 2554adb41e1eef549ee8abc1b5efd1a5127ca81b Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 18:29:11 +0530 Subject: [PATCH 039/343] update: error messages. --- .../Platform/Modules/Databases/Http/Columns/Float/Create.php | 2 +- .../Modules/Databases/Http/Columns/Relationship/Create.php | 2 +- .../Platform/Modules/Databases/Http/Databases/XList.php | 2 +- src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php | 2 +- src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php index 0782f8eb29..b8f13d481b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php @@ -91,7 +91,7 @@ class Create extends ColumnAction $max ??= INF; if ($min > $max) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum must be less than or equal to maximum'); + throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); } $validator = new Range($min, $max, Database::VAR_FLOAT); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php index 09efdd14f9..f5806b6d8c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php @@ -136,7 +136,7 @@ class Create extends ColumnAction $column->getAttribute('options')['relationType'] === Database::RELATION_MANY_TO_MANY && $column->getAttribute('options')['relatedCollection'] === $relatedTable->getId() ) { - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Only one "manyToMany" relationship per table is allowed.'); + throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Creating more than one "manyToMany" relationship on the same table is currently not permitted.'); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php index 7453fb39f4..1fd0967b37 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php @@ -97,7 +97,7 @@ class XList extends Action $databases = $dbForProject->find('databases', $queries); $total = $dbForProject->count('databases', $filterQueries, APP_LIMIT_COUNT); } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); } $response->dynamic(new Document([ 'databases' => $databases, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php index ab40f4d5e1..215ee94550 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php @@ -91,7 +91,7 @@ class Create extends Action } if (isset($data['$id'])) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is not allowed for creating new documents, try update instead'); + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is not allowed for creating new rows, try update instead'); } $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php index d75150f2bb..85474840df 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php @@ -106,7 +106,7 @@ class XList extends Action $tables = $dbForProject->find('database_' . $database->getInternalId(), $queries); $total = $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT); } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); } $response->dynamic(new Document([ From e0a4c698bc24505b508bd5e42f5d686b136f4607 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 18:43:32 +0530 Subject: [PATCH 040/343] fix: `float` column creation! --- .../Platform/Modules/Databases/Http/Columns/Float/Create.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php index b8f13d481b..088eef0b39 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php @@ -87,8 +87,8 @@ class Create extends ColumnAction EventDatabase $queueForDatabase, Event $queueForEvents ): void { - $min ??= -INF; - $max ??= INF; + $min ??= -PHP_FLOAT_MAX; + $max ??= PHP_FLOAT_MAX; if ($min > $max) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); From d184d1c7b163f53764893e9d3857865b78417d38 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 18:50:24 +0530 Subject: [PATCH 041/343] fix: lint! --- .../Platform/Modules/Databases/Http/Columns/Float/Create.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php index 088eef0b39..28e671fb72 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php @@ -2,8 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Float; -use const INF; - use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; use Appwrite\Extend\Exception; From 8546195c04a43dce11802b3cb08c917e133bcc8b Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 4 May 2025 19:16:25 +0530 Subject: [PATCH 042/343] address comments by `coderabbitai`. --- app/config/locale/translations/it.json | 2 +- app/config/locale/translations/ur.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/config/locale/translations/it.json b/app/config/locale/translations/it.json index 65a9961529..f0e290b481 100644 --- a/app/config/locale/translations/it.json +++ b/app/config/locale/translations/it.json @@ -28,7 +28,7 @@ "emails.invitation.body": "Hai ricevuto questa email perché {{owner}} ti ha invitato a diventare un membro del team {{team}} di {{project}}.", "emails.invitation.footer": "Ignora questo messaggio se non sei interessatə.", "emails.invitation.thanks": "Grazie,", - "emails.invitation.buttonText": "Accetta invito a {{team}", + "emails.invitation.buttonText": "Accetta invito a {{team}}", "emails.invitation.signature": "Il team {{project}}", "locale.country.unknown": "Sconosciuto", "countries.af": "Afghanistan", diff --git a/app/config/locale/translations/ur.json b/app/config/locale/translations/ur.json index 4c93f36b51..8823e0da2e 100644 --- a/app/config/locale/translations/ur.json +++ b/app/config/locale/translations/ur.json @@ -29,7 +29,7 @@ "emails.invitation.footer": "اگر آپ دلچسپی نہیں رکھتے تو آپ اس پیغام کو نظر انداز کر سکتے ہیں۔", "emails.invitation.thanks": "شکریہ،", "emails.invitation.buttonText": "{{team}} کی دعوت قبول کریں", - "emails.invitation.signature": "ٹیم۔ {{project}", + "emails.invitation.signature": "ٹیم۔ {{project}}", "locale.country.unknown": "نامعلوم", "countries.af": "افغانستان", "countries.ao": "انگولا", From 8504fbc0b93eb2802d8ae0fb1bfa68c97f61ddbe Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 5 May 2025 09:14:20 +0530 Subject: [PATCH 043/343] update: `collection` response model to `table`. --- src/Appwrite/Utopia/Response.php | 12 ++++----- .../Utopia/Response/Model/BaseList.php | 6 ++--- .../Model/{Collection.php => Table.php} | 26 +++++++++---------- 3 files changed, 22 insertions(+), 22 deletions(-) rename src/Appwrite/Utopia/Response/Model/{Collection.php => Table.php} (77%) diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 3d69ac1291..ad2e7ad9b8 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -31,7 +31,7 @@ use Appwrite\Utopia\Response\Model\AuthProvider; use Appwrite\Utopia\Response\Model\BaseList; use Appwrite\Utopia\Response\Model\Branch; use Appwrite\Utopia\Response\Model\Bucket; -use Appwrite\Utopia\Response\Model\Collection; +use Appwrite\Utopia\Response\Model\Table; use Appwrite\Utopia\Response\Model\ConsoleVariables; use Appwrite\Utopia\Response\Model\Continent; use Appwrite\Utopia\Response\Model\Country; @@ -160,8 +160,8 @@ class Response extends SwooleResponse // Database public const MODEL_DATABASE = 'database'; public const MODEL_DATABASE_LIST = 'databaseList'; - public const MODEL_COLLECTION = 'collection'; - public const MODEL_COLLECTION_LIST = 'collectionList'; + public const MODEL_TABLE = 'table'; + public const MODEL_TABLE_LIST = 'tableList'; public const MODEL_INDEX = 'index'; public const MODEL_INDEX_LIST = 'indexList'; public const MODEL_DOCUMENT = 'document'; @@ -376,8 +376,8 @@ class Response extends SwooleResponse ->setModel(new Error()) ->setModel(new ErrorDev()) // Lists - ->setModel(new BaseList('Documents List', self::MODEL_DOCUMENT_LIST, 'documents', self::MODEL_DOCUMENT)) - ->setModel(new BaseList('Collections List', self::MODEL_COLLECTION_LIST, 'collections', self::MODEL_COLLECTION)) + ->setModel(new BaseList('Rows List', self::MODEL_DOCUMENT_LIST, 'rows', self::MODEL_DOCUMENT)) + ->setModel(new BaseList('Tables List', self::MODEL_TABLE_LIST, 'tables', self::MODEL_TABLE)) ->setModel(new BaseList('Databases List', self::MODEL_DATABASE_LIST, 'databases', self::MODEL_DATABASE)) ->setModel(new BaseList('Indexes List', self::MODEL_INDEX_LIST, 'indexes', self::MODEL_INDEX)) ->setModel(new BaseList('Users List', self::MODEL_USER_LIST, 'users', self::MODEL_USER)) @@ -428,7 +428,7 @@ class Response extends SwooleResponse ->setModel(new BaseList('VCS Content List', self::MODEL_VCS_CONTENT_LIST, 'contents', self::MODEL_VCS_CONTENT)) // Entities ->setModel(new Database()) - ->setModel(new Collection()) + ->setModel(new Table()) ->setModel(new Attribute()) ->setModel(new AttributeList()) ->setModel(new AttributeString()) diff --git a/src/Appwrite/Utopia/Response/Model/BaseList.php b/src/Appwrite/Utopia/Response/Model/BaseList.php index d4ba6b0ab7..1fa3197ba7 100644 --- a/src/Appwrite/Utopia/Response/Model/BaseList.php +++ b/src/Appwrite/Utopia/Response/Model/BaseList.php @@ -32,15 +32,15 @@ class BaseList extends Model if ($paging) { $namesWithCap = [ - 'documents', 'collections', 'users', 'files', 'buckets', 'functions', + 'rows', 'tables', 'users', 'files', 'buckets', 'functions', 'deployments', 'executions', 'projects', 'webhooks', 'keys', 'platforms', 'rules', 'memberships', 'teams' ]; if (\in_array($name, $namesWithCap)) { - $description = 'Total number of ' . $key . ' documents that matched your query used as reference for offset pagination. When the `total` number of ' . $key . ' documents available is greater than 5000, total returned will be capped at 5000, and cursor pagination should be used. Read more about [pagination](https://appwrite.io/docs/pagination).'; + $description = 'Total number of ' . $key . ' rows that matched your query used as reference for offset pagination. When the `total` number of ' . $key . ' rows available is greater than 5000, total returned will be capped at 5000, and cursor pagination should be used. Read more about [pagination](https://appwrite.io/docs/pagination).'; } else { - $description = 'Total number of ' . $key . ' documents that matched your query.'; + $description = 'Total number of ' . $key . ' rows that matched your query.'; } $this->addRule('total', [ diff --git a/src/Appwrite/Utopia/Response/Model/Collection.php b/src/Appwrite/Utopia/Response/Model/Table.php similarity index 77% rename from src/Appwrite/Utopia/Response/Model/Collection.php rename to src/Appwrite/Utopia/Response/Model/Table.php index 2c2bf0cca8..305f1db3c9 100644 --- a/src/Appwrite/Utopia/Response/Model/Collection.php +++ b/src/Appwrite/Utopia/Response/Model/Table.php @@ -5,32 +5,32 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; -class Collection extends Model +class Table extends Model { public function __construct() { $this ->addRule('$id', [ 'type' => self::TYPE_STRING, - 'description' => 'Collection ID.', + 'description' => 'Table ID.', 'default' => '', 'example' => '5e5ea5c16897e', ]) ->addRule('$createdAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Collection creation date in ISO 8601 format.', + 'description' => 'Table creation date in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) ->addRule('$updatedAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Collection update date in ISO 8601 format.', + 'description' => 'Table update date in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) ->addRule('$permissions', [ 'type' => self::TYPE_STRING, - 'description' => 'Collection permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', + 'description' => 'Table permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', 'default' => '', 'example' => ['read("any")'], 'array' => true @@ -43,13 +43,13 @@ class Collection extends Model ]) ->addRule('name', [ 'type' => self::TYPE_STRING, - 'description' => 'Collection name.', + 'description' => 'Table name.', 'default' => '', - 'example' => 'My Collection', + 'example' => 'My Table', ]) ->addRule('enabled', [ 'type' => self::TYPE_BOOLEAN, - 'description' => 'Collection enabled. Can be \'enabled\' or \'disabled\'. When disabled, the collection is inaccessible to users, but remains accessible to Server SDKs using API keys.', + 'description' => 'Table enabled. Can be \'enabled\' or \'disabled\'. When disabled, the table is inaccessible to users, but remains accessible to Server SDKs using API keys.', 'default' => true, 'example' => false, ]) @@ -59,7 +59,7 @@ class Collection extends Model 'default' => '', 'example' => true, ]) - ->addRule('attributes', [ + ->addRule('columns', [ 'type' => [ Response::MODEL_ATTRIBUTE_BOOLEAN, Response::MODEL_ATTRIBUTE_INTEGER, @@ -72,14 +72,14 @@ class Collection extends Model Response::MODEL_ATTRIBUTE_RELATIONSHIP, Response::MODEL_ATTRIBUTE_STRING, // needs to be last, since its condition would dominate any other string attribute ], - 'description' => 'Collection attributes.', + 'description' => 'Table columns.', 'default' => [], 'example' => new \stdClass(), 'array' => true, ]) ->addRule('indexes', [ 'type' => Response::MODEL_INDEX, - 'description' => 'Collection indexes.', + 'description' => 'Table indexes.', 'default' => [], 'example' => new \stdClass(), 'array' => true @@ -94,7 +94,7 @@ class Collection extends Model */ public function getName(): string { - return 'Collection'; + return 'Table'; } /** @@ -104,6 +104,6 @@ class Collection extends Model */ public function getType(): string { - return Response::MODEL_COLLECTION; + return Response::MODEL_TABLE; } } From 675d404b9b1c4bf9724a3bf4f715b9bb3544e296 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 5 May 2025 09:30:27 +0530 Subject: [PATCH 044/343] update: `attribute*` response model to `column*`. --- app/config/events.php | 2 +- .../Databases/Http/Columns/Boolean/Create.php | 4 +- .../Databases/Http/Columns/Boolean/Update.php | 4 +- .../Http/Columns/Datetime/Create.php | 4 +- .../Http/Columns/Datetime/Update.php | 4 +- .../Modules/Databases/Http/Columns/Delete.php | 22 +++--- .../Databases/Http/Columns/Email/Create.php | 4 +- .../Databases/Http/Columns/Email/Update.php | 4 +- .../Databases/Http/Columns/Enum/Create.php | 4 +- .../Databases/Http/Columns/Enum/Update.php | 4 +- .../Databases/Http/Columns/Float/Create.php | 4 +- .../Databases/Http/Columns/Float/Update.php | 4 +- .../Modules/Databases/Http/Columns/Get.php | 42 +++++----- .../Databases/Http/Columns/IP/Create.php | 4 +- .../Databases/Http/Columns/IP/Update.php | 4 +- .../Databases/Http/Columns/Integer/Create.php | 4 +- .../Databases/Http/Columns/Integer/Update.php | 4 +- .../Http/Columns/Relationship/Create.php | 4 +- .../Http/Columns/Relationship/Update.php | 4 +- .../Databases/Http/Columns/String/Create.php | 4 +- .../Databases/Http/Columns/String/Update.php | 4 +- .../Databases/Http/Columns/URL/Create.php | 4 +- .../Databases/Http/Columns/URL/Update.php | 4 +- .../Modules/Databases/Http/Columns/XList.php | 4 +- src/Appwrite/Utopia/Response.php | 78 +++++++++---------- .../Utopia/Response/Model/AttributeList.php | 58 -------------- .../Model/{Attribute.php => Column.php} | 22 +++--- ...AttributeBoolean.php => ColumnBoolean.php} | 10 +-- ...tributeDatetime.php => ColumnDatetime.php} | 10 +-- .../{AttributeEmail.php => ColumnEmail.php} | 10 +-- .../{AttributeEnum.php => ColumnEnum.php} | 10 +-- .../{AttributeFloat.php => ColumnFloat.php} | 10 +-- .../Model/{AttributeIP.php => ColumnIP.php} | 10 +-- ...AttributeInteger.php => ColumnInteger.php} | 10 +-- .../Utopia/Response/Model/ColumnList.php | 58 ++++++++++++++ ...elationship.php => ColumnRelationship.php} | 10 +-- .../{AttributeString.php => ColumnString.php} | 10 +-- .../Model/{AttributeURL.php => ColumnURL.php} | 14 ++-- src/Appwrite/Utopia/Response/Model/Table.php | 20 ++--- 39 files changed, 245 insertions(+), 245 deletions(-) delete mode 100644 src/Appwrite/Utopia/Response/Model/AttributeList.php rename src/Appwrite/Utopia/Response/Model/{Attribute.php => Column.php} (74%) rename src/Appwrite/Utopia/Response/Model/{AttributeBoolean.php => ColumnBoolean.php} (83%) rename src/Appwrite/Utopia/Response/Model/{AttributeDatetime.php => ColumnDatetime.php} (86%) rename src/Appwrite/Utopia/Response/Model/{AttributeEmail.php => ColumnEmail.php} (86%) rename src/Appwrite/Utopia/Response/Model/{AttributeEnum.php => ColumnEnum.php} (88%) rename src/Appwrite/Utopia/Response/Model/{AttributeFloat.php => ColumnFloat.php} (88%) rename src/Appwrite/Utopia/Response/Model/{AttributeIP.php => ColumnIP.php} (87%) rename src/Appwrite/Utopia/Response/Model/{AttributeInteger.php => ColumnInteger.php} (88%) create mode 100644 src/Appwrite/Utopia/Response/Model/ColumnList.php rename src/Appwrite/Utopia/Response/Model/{AttributeRelationship.php => ColumnRelationship.php} (91%) rename src/Appwrite/Utopia/Response/Model/{AttributeString.php => ColumnString.php} (74%) rename src/Appwrite/Utopia/Response/Model/{AttributeURL.php => ColumnURL.php} (76%) diff --git a/app/config/events.php b/app/config/events.php index 3b0cc982a0..41857fad70 100644 --- a/app/config/events.php +++ b/app/config/events.php @@ -125,7 +125,7 @@ return [ ] ], 'columns' => [ - '$model' => Response::MODEL_ATTRIBUTE, + '$model' => Response::MODEL_COLUMN, '$resource' => true, '$description' => 'This event triggers on any columns event.', 'create' => [ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php index dab0527fa7..7e1331a637 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php @@ -48,7 +48,7 @@ class Create extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN, + model: UtopiaResponse::MODEL_COLUMN_BOOLEAN, ) ] )) @@ -79,6 +79,6 @@ class Create extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_BOOLEAN); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php index 35148fc174..6725e0c817 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php @@ -48,7 +48,7 @@ class Update extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN, + model: UtopiaResponse::MODEL_COLUMN_BOOLEAN, ) ], contentType: ContentType::JSON @@ -81,6 +81,6 @@ class Update extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_BOOLEAN); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php index 36ddfb4dfa..775d33ab19 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php @@ -50,7 +50,7 @@ class Create extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_ATTRIBUTE_DATETIME, + model: UtopiaResponse::MODEL_COLUMN_DATETIME, ) ] )) @@ -101,6 +101,6 @@ class Create extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_DATETIME); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_DATETIME); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php index d323ed4fd0..6ff0744859 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php @@ -50,7 +50,7 @@ class Update extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ATTRIBUTE_DATETIME, + model: UtopiaResponse::MODEL_COLUMN_DATETIME, ) ], contentType: ContentType::JSON @@ -92,6 +92,6 @@ class Update extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_DATETIME); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_DATETIME); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php index 9baa857fec..945097e66b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php @@ -136,19 +136,19 @@ class Delete extends Action $format = $column->getAttribute('format'); $model = match ($type) { - Database::VAR_BOOLEAN => UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN, - Database::VAR_INTEGER => UtopiaResponse::MODEL_ATTRIBUTE_INTEGER, - Database::VAR_FLOAT => UtopiaResponse::MODEL_ATTRIBUTE_FLOAT, - Database::VAR_DATETIME => UtopiaResponse::MODEL_ATTRIBUTE_DATETIME, - Database::VAR_RELATIONSHIP => UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP, + Database::VAR_BOOLEAN => UtopiaResponse::MODEL_COLUMN_BOOLEAN, + Database::VAR_INTEGER => UtopiaResponse::MODEL_COLUMN_INTEGER, + Database::VAR_FLOAT => UtopiaResponse::MODEL_COLUMN_FLOAT, + Database::VAR_DATETIME => UtopiaResponse::MODEL_COLUMN_DATETIME, + Database::VAR_RELATIONSHIP => UtopiaResponse::MODEL_COLUMN_RELATIONSHIP, Database::VAR_STRING => match ($format) { - APP_DATABASE_ATTRIBUTE_EMAIL => UtopiaResponse::MODEL_ATTRIBUTE_EMAIL, - APP_DATABASE_ATTRIBUTE_ENUM => UtopiaResponse::MODEL_ATTRIBUTE_ENUM, - APP_DATABASE_ATTRIBUTE_IP => UtopiaResponse::MODEL_ATTRIBUTE_IP, - APP_DATABASE_ATTRIBUTE_URL => UtopiaResponse::MODEL_ATTRIBUTE_URL, - default => UtopiaResponse::MODEL_ATTRIBUTE_STRING, + APP_DATABASE_ATTRIBUTE_EMAIL => UtopiaResponse::MODEL_COLUMN_EMAIL, + APP_DATABASE_ATTRIBUTE_ENUM => UtopiaResponse::MODEL_COLUMN_ENUM, + APP_DATABASE_ATTRIBUTE_IP => UtopiaResponse::MODEL_COLUMN_IP, + APP_DATABASE_ATTRIBUTE_URL => UtopiaResponse::MODEL_COLUMN_URL, + default => UtopiaResponse::MODEL_COLUMN_STRING, }, - default => UtopiaResponse::MODEL_ATTRIBUTE, + default => UtopiaResponse::MODEL_COLUMN, }; $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php index 1d51e26efc..2372d8b032 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php @@ -50,7 +50,7 @@ class Create extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_ATTRIBUTE_EMAIL, + model: UtopiaResponse::MODEL_COLUMN_EMAIL, ) ] )) @@ -99,6 +99,6 @@ class Create extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_EMAIL); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_EMAIL); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php index 53e03c93a2..74124eba37 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php @@ -50,7 +50,7 @@ class Update extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ATTRIBUTE_EMAIL, + model: UtopiaResponse::MODEL_COLUMN_EMAIL, ) ], contentType: ContentType::JSON @@ -93,6 +93,6 @@ class Update extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_EMAIL); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_EMAIL); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php index 95ed0b0630..5c5c7da071 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php @@ -52,7 +52,7 @@ class Create extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_ATTRIBUTE_ENUM, + model: UtopiaResponse::MODEL_COLUMN_ENUM, ) ] )) @@ -108,6 +108,6 @@ class Create extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_ENUM); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_ENUM); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php index d52dd161e4..aa588a9f1b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php @@ -51,7 +51,7 @@ class Update extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ATTRIBUTE_ENUM, + model: UtopiaResponse::MODEL_COLUMN_ENUM, ) ], contentType: ContentType::JSON @@ -97,6 +97,6 @@ class Update extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_ENUM); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_ENUM); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php index 28e671fb72..150ce8d25e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php @@ -52,7 +52,7 @@ class Create extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_ATTRIBUTE_FLOAT, + model: UtopiaResponse::MODEL_COLUMN_FLOAT, ) ] )) @@ -116,6 +116,6 @@ class Create extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_FLOAT); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_FLOAT); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php index c585205388..8ea7ab474a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php @@ -50,7 +50,7 @@ class Update extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ATTRIBUTE_FLOAT, + model: UtopiaResponse::MODEL_COLUMN_FLOAT, ) ], contentType: ContentType::JSON @@ -104,6 +104,6 @@ class Update extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_FLOAT); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_FLOAT); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php index 14744f0442..160ab60868 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php @@ -44,16 +44,16 @@ class Get extends Action new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, model: [ - UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN, - UtopiaResponse::MODEL_ATTRIBUTE_INTEGER, - UtopiaResponse::MODEL_ATTRIBUTE_FLOAT, - UtopiaResponse::MODEL_ATTRIBUTE_EMAIL, - UtopiaResponse::MODEL_ATTRIBUTE_ENUM, - UtopiaResponse::MODEL_ATTRIBUTE_URL, - UtopiaResponse::MODEL_ATTRIBUTE_IP, - UtopiaResponse::MODEL_ATTRIBUTE_DATETIME, - UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP, - UtopiaResponse::MODEL_ATTRIBUTE_STRING, + UtopiaResponse::MODEL_COLUMN_BOOLEAN, + UtopiaResponse::MODEL_COLUMN_INTEGER, + UtopiaResponse::MODEL_COLUMN_FLOAT, + UtopiaResponse::MODEL_COLUMN_EMAIL, + UtopiaResponse::MODEL_COLUMN_ENUM, + UtopiaResponse::MODEL_COLUMN_URL, + UtopiaResponse::MODEL_COLUMN_IP, + UtopiaResponse::MODEL_COLUMN_DATETIME, + UtopiaResponse::MODEL_COLUMN_RELATIONSHIP, + UtopiaResponse::MODEL_COLUMN_STRING, ] ) ] @@ -92,19 +92,19 @@ class Get extends Action } $model = match ($type) { - Database::VAR_BOOLEAN => UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN, - Database::VAR_INTEGER => UtopiaResponse::MODEL_ATTRIBUTE_INTEGER, - Database::VAR_FLOAT => UtopiaResponse::MODEL_ATTRIBUTE_FLOAT, - Database::VAR_DATETIME => UtopiaResponse::MODEL_ATTRIBUTE_DATETIME, - Database::VAR_RELATIONSHIP => UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP, + Database::VAR_BOOLEAN => UtopiaResponse::MODEL_COLUMN_BOOLEAN, + Database::VAR_INTEGER => UtopiaResponse::MODEL_COLUMN_INTEGER, + Database::VAR_FLOAT => UtopiaResponse::MODEL_COLUMN_FLOAT, + Database::VAR_DATETIME => UtopiaResponse::MODEL_COLUMN_DATETIME, + Database::VAR_RELATIONSHIP => UtopiaResponse::MODEL_COLUMN_RELATIONSHIP, Database::VAR_STRING => match ($format) { - APP_DATABASE_ATTRIBUTE_EMAIL => UtopiaResponse::MODEL_ATTRIBUTE_EMAIL, - APP_DATABASE_ATTRIBUTE_ENUM => UtopiaResponse::MODEL_ATTRIBUTE_ENUM, - APP_DATABASE_ATTRIBUTE_IP => UtopiaResponse::MODEL_ATTRIBUTE_IP, - APP_DATABASE_ATTRIBUTE_URL => UtopiaResponse::MODEL_ATTRIBUTE_URL, - default => UtopiaResponse::MODEL_ATTRIBUTE_STRING, + APP_DATABASE_ATTRIBUTE_EMAIL => UtopiaResponse::MODEL_COLUMN_EMAIL, + APP_DATABASE_ATTRIBUTE_ENUM => UtopiaResponse::MODEL_COLUMN_ENUM, + APP_DATABASE_ATTRIBUTE_IP => UtopiaResponse::MODEL_COLUMN_IP, + APP_DATABASE_ATTRIBUTE_URL => UtopiaResponse::MODEL_COLUMN_URL, + default => UtopiaResponse::MODEL_COLUMN_STRING, }, - default => UtopiaResponse::MODEL_ATTRIBUTE, + default => UtopiaResponse::MODEL_COLUMN, }; $response->dynamic($column, $model); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php index b3916a5fad..73d8c93031 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php @@ -50,7 +50,7 @@ class Create extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_ATTRIBUTE_IP, + model: UtopiaResponse::MODEL_COLUMN_IP, ) ] )) @@ -91,6 +91,6 @@ class Create extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_IP); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_IP); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php index 6da08a2c9f..4b9fa8bca8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php @@ -50,7 +50,7 @@ class Update extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ATTRIBUTE_IP, + model: UtopiaResponse::MODEL_COLUMN_IP, ) ], contentType: ContentType::JSON @@ -93,6 +93,6 @@ class Update extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_IP); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_IP); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php index 7a26d10bc8..d58b79d597 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php @@ -52,7 +52,7 @@ class Create extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_ATTRIBUTE_INTEGER, + model: UtopiaResponse::MODEL_COLUMN_INTEGER, ) ] )) @@ -118,6 +118,6 @@ class Create extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_INTEGER); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_INTEGER); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php index 27616c07c9..1806cc91c3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php @@ -50,7 +50,7 @@ class Update extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ATTRIBUTE_INTEGER, + model: UtopiaResponse::MODEL_COLUMN_INTEGER, ) ], contentType: ContentType::JSON @@ -104,6 +104,6 @@ class Update extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_INTEGER); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_INTEGER); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php index f5806b6d8c..d063c8e055 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php @@ -52,7 +52,7 @@ class Create extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP + model: UtopiaResponse::MODEL_COLUMN_RELATIONSHIP ) ] )) @@ -163,6 +163,6 @@ class Create extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_RELATIONSHIP); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php index 34231ad611..80ca25e9cf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php @@ -48,7 +48,7 @@ class Update extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP + model: UtopiaResponse::MODEL_COLUMN_RELATIONSHIP ) ], contentType: ContentType::JSON @@ -98,6 +98,6 @@ class Update extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_RELATIONSHIP); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php index 1987f5fdbe..caafdbc32f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php @@ -53,7 +53,7 @@ class Create extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_ATTRIBUTE_STRING + model: UtopiaResponse::MODEL_COLUMN_STRING ) ] )) @@ -117,6 +117,6 @@ class Create extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_STRING); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_STRING); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php index a73ae0f9b1..35fe6bc86d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php @@ -51,7 +51,7 @@ class Update extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ATTRIBUTE_STRING, + model: UtopiaResponse::MODEL_COLUMN_STRING, ) ], contentType: ContentType::JSON @@ -96,6 +96,6 @@ class Update extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_STRING); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_STRING); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php index 74eedfa98b..c1483c373a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php @@ -50,7 +50,7 @@ class Create extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_ATTRIBUTE_URL, + model: UtopiaResponse::MODEL_COLUMN_URL, ) ] )) @@ -91,6 +91,6 @@ class Create extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_URL); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_URL); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php index 109b9c575b..db35cf56c4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php @@ -50,7 +50,7 @@ class Update extends ColumnAction responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ATTRIBUTE_URL, + model: UtopiaResponse::MODEL_COLUMN_URL, ) ], contentType: ContentType::JSON @@ -93,6 +93,6 @@ class Update extends ColumnAction $response ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_ATTRIBUTE_URL); + ->dynamic($column, UtopiaResponse::MODEL_COLUMN_URL); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php index f2343e927b..cba6e2d077 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php @@ -47,7 +47,7 @@ class XList extends Action responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ATTRIBUTE_LIST + model: UtopiaResponse::MODEL_COLUMN_LIST ) ] )) @@ -120,6 +120,6 @@ class XList extends Action $response->dynamic(new Document([ 'attributes' => $columns, 'total' => $total, - ]), UtopiaResponse::MODEL_ATTRIBUTE_LIST); + ]), UtopiaResponse::MODEL_COLUMN_LIST); } } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index ad2e7ad9b8..0fae030b82 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -15,23 +15,22 @@ use Appwrite\Utopia\Response\Model\AlgoScrypt; use Appwrite\Utopia\Response\Model\AlgoScryptModified; use Appwrite\Utopia\Response\Model\AlgoSha; use Appwrite\Utopia\Response\Model\Any; -use Appwrite\Utopia\Response\Model\Attribute; -use Appwrite\Utopia\Response\Model\AttributeBoolean; -use Appwrite\Utopia\Response\Model\AttributeDatetime; -use Appwrite\Utopia\Response\Model\AttributeEmail; -use Appwrite\Utopia\Response\Model\AttributeEnum; -use Appwrite\Utopia\Response\Model\AttributeFloat; -use Appwrite\Utopia\Response\Model\AttributeInteger; -use Appwrite\Utopia\Response\Model\AttributeIP; -use Appwrite\Utopia\Response\Model\AttributeList; -use Appwrite\Utopia\Response\Model\AttributeRelationship; -use Appwrite\Utopia\Response\Model\AttributeString; -use Appwrite\Utopia\Response\Model\AttributeURL; use Appwrite\Utopia\Response\Model\AuthProvider; use Appwrite\Utopia\Response\Model\BaseList; use Appwrite\Utopia\Response\Model\Branch; use Appwrite\Utopia\Response\Model\Bucket; -use Appwrite\Utopia\Response\Model\Table; +use Appwrite\Utopia\Response\Model\Column; +use Appwrite\Utopia\Response\Model\ColumnBoolean; +use Appwrite\Utopia\Response\Model\ColumnDatetime; +use Appwrite\Utopia\Response\Model\ColumnEmail; +use Appwrite\Utopia\Response\Model\ColumnEnum; +use Appwrite\Utopia\Response\Model\ColumnFloat; +use Appwrite\Utopia\Response\Model\ColumnInteger; +use Appwrite\Utopia\Response\Model\ColumnIP; +use Appwrite\Utopia\Response\Model\ColumnList; +use Appwrite\Utopia\Response\Model\ColumnRelationship; +use Appwrite\Utopia\Response\Model\ColumnString; +use Appwrite\Utopia\Response\Model\ColumnURL; use Appwrite\Utopia\Response\Model\ConsoleVariables; use Appwrite\Utopia\Response\Model\Continent; use Appwrite\Utopia\Response\Model\Country; @@ -94,6 +93,7 @@ use Appwrite\Utopia\Response\Model\Session; use Appwrite\Utopia\Response\Model\Site; use Appwrite\Utopia\Response\Model\Specification; use Appwrite\Utopia\Response\Model\Subscriber; +use Appwrite\Utopia\Response\Model\Table; use Appwrite\Utopia\Response\Model\Target; use Appwrite\Utopia\Response\Model\Team; use Appwrite\Utopia\Response\Model\TemplateEmail; @@ -168,18 +168,18 @@ class Response extends SwooleResponse public const MODEL_DOCUMENT_LIST = 'documentList'; // Database Attributes - public const MODEL_ATTRIBUTE = 'attribute'; - public const MODEL_ATTRIBUTE_LIST = 'attributeList'; - public const MODEL_ATTRIBUTE_STRING = 'attributeString'; - public const MODEL_ATTRIBUTE_INTEGER = 'attributeInteger'; - public const MODEL_ATTRIBUTE_FLOAT = 'attributeFloat'; - public const MODEL_ATTRIBUTE_BOOLEAN = 'attributeBoolean'; - public const MODEL_ATTRIBUTE_EMAIL = 'attributeEmail'; - public const MODEL_ATTRIBUTE_ENUM = 'attributeEnum'; - public const MODEL_ATTRIBUTE_IP = 'attributeIp'; - public const MODEL_ATTRIBUTE_URL = 'attributeUrl'; - public const MODEL_ATTRIBUTE_DATETIME = 'attributeDatetime'; - public const MODEL_ATTRIBUTE_RELATIONSHIP = 'attributeRelationship'; + public const MODEL_COLUMN = 'column'; + public const MODEL_COLUMN_LIST = 'columnList'; + public const MODEL_COLUMN_STRING = 'columnString'; + public const MODEL_COLUMN_INTEGER = 'columnInteger'; + public const MODEL_COLUMN_FLOAT = 'columnFloat'; + public const MODEL_COLUMN_BOOLEAN = 'columnBoolean'; + public const MODEL_COLUMN_EMAIL = 'columnEmail'; + public const MODEL_COLUMN_ENUM = 'columnEnum'; + public const MODEL_COLUMN_IP = 'columnIp'; + public const MODEL_COLUMN_URL = 'columnUrl'; + public const MODEL_COLUMN_DATETIME = 'columnDatetime'; + public const MODEL_COLUMN_RELATIONSHIP = 'columnRelationship'; // Users public const MODEL_ACCOUNT = 'account'; @@ -429,18 +429,18 @@ class Response extends SwooleResponse // Entities ->setModel(new Database()) ->setModel(new Table()) - ->setModel(new Attribute()) - ->setModel(new AttributeList()) - ->setModel(new AttributeString()) - ->setModel(new AttributeInteger()) - ->setModel(new AttributeFloat()) - ->setModel(new AttributeBoolean()) - ->setModel(new AttributeEmail()) - ->setModel(new AttributeEnum()) - ->setModel(new AttributeIP()) - ->setModel(new AttributeURL()) - ->setModel(new AttributeDatetime()) - ->setModel(new AttributeRelationship()) + ->setModel(new Column()) + ->setModel(new ColumnList()) + ->setModel(new ColumnString()) + ->setModel(new ColumnInteger()) + ->setModel(new ColumnFloat()) + ->setModel(new ColumnBoolean()) + ->setModel(new ColumnEmail()) + ->setModel(new ColumnEnum()) + ->setModel(new ColumnIP()) + ->setModel(new ColumnURL()) + ->setModel(new ColumnDatetime()) + ->setModel(new ColumnRelationship()) ->setModel(new Index()) ->setModel(new ModelDocument()) ->setModel(new Log()) @@ -558,7 +558,7 @@ class Response extends SwooleResponse * * @return self */ - public function setModel(Model $instance) + public function setModel(Model $instance): Response { $this->models[$instance->getType()] = $instance; @@ -836,7 +836,7 @@ class Response extends SwooleResponse /** * Function to add a response filter, the order of filters are first in - first out. * - * @param $filter the response filter to set + * @param $filter - the response filter to set * * @return void */ diff --git a/src/Appwrite/Utopia/Response/Model/AttributeList.php b/src/Appwrite/Utopia/Response/Model/AttributeList.php deleted file mode 100644 index 8b04475a14..0000000000 --- a/src/Appwrite/Utopia/Response/Model/AttributeList.php +++ /dev/null @@ -1,58 +0,0 @@ -addRule('total', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Total number of attributes in the given collection.', - 'default' => 0, - 'example' => 5, - ]) - ->addRule('attributes', [ - 'type' => [ - Response::MODEL_ATTRIBUTE_BOOLEAN, - Response::MODEL_ATTRIBUTE_INTEGER, - Response::MODEL_ATTRIBUTE_FLOAT, - Response::MODEL_ATTRIBUTE_EMAIL, - Response::MODEL_ATTRIBUTE_ENUM, - Response::MODEL_ATTRIBUTE_URL, - Response::MODEL_ATTRIBUTE_IP, - Response::MODEL_ATTRIBUTE_DATETIME, - Response::MODEL_ATTRIBUTE_RELATIONSHIP, - Response::MODEL_ATTRIBUTE_STRING // needs to be last, since its condition would dominate any other string attribute - ], - 'description' => 'List of attributes.', - 'default' => [], - 'array' => true - ]) - ; - } - - /** - * Get Name - * - * @return string - */ - public function getName(): string - { - return 'Attributes List'; - } - - /** - * Get Type - * - * @return string - */ - public function getType(): string - { - return Response::MODEL_ATTRIBUTE_LIST; - } -} diff --git a/src/Appwrite/Utopia/Response/Model/Attribute.php b/src/Appwrite/Utopia/Response/Model/Column.php similarity index 74% rename from src/Appwrite/Utopia/Response/Model/Attribute.php rename to src/Appwrite/Utopia/Response/Model/Column.php index 8c43f8d21c..5562de39f2 100644 --- a/src/Appwrite/Utopia/Response/Model/Attribute.php +++ b/src/Appwrite/Utopia/Response/Model/Column.php @@ -5,57 +5,57 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; -class Attribute extends Model +class Column extends Model { public function __construct() { $this ->addRule('key', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute Key.', + 'description' => 'Column Key.', 'default' => '', 'example' => 'fullName', ]) ->addRule('type', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute type.', + 'description' => 'Column type.', 'default' => '', 'example' => 'string', ]) ->addRule('status', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`', + 'description' => 'Column status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`', 'default' => '', 'example' => 'available', ]) ->addRule('error', [ 'type' => self::TYPE_STRING, - 'description' => 'Error message. Displays error generated on failure of creating or deleting an attribute.', + 'description' => 'Error message. Displays error generated on failure of creating or deleting an column.', 'default' => '', 'example' => 'string', ]) ->addRule('required', [ 'type' => self::TYPE_BOOLEAN, - 'description' => 'Is attribute required?', + 'description' => 'Is column required?', 'default' => false, 'example' => true, ]) ->addRule('array', [ 'type' => self::TYPE_BOOLEAN, - 'description' => 'Is attribute an array?', + 'description' => 'Is column an array?', 'default' => false, 'required' => false, 'example' => false, ]) ->addRule('$createdAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Attribute creation date in ISO 8601 format.', + 'description' => 'Column creation date in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) ->addRule('$updatedAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Attribute update date in ISO 8601 format.', + 'description' => 'Column update date in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]); @@ -70,7 +70,7 @@ class Attribute extends Model */ public function getName(): string { - return 'Attribute'; + return 'Column'; } /** @@ -80,6 +80,6 @@ class Attribute extends Model */ public function getType(): string { - return Response::MODEL_ATTRIBUTE; + return Response::MODEL_COLUMN; } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php b/src/Appwrite/Utopia/Response/Model/ColumnBoolean.php similarity index 83% rename from src/Appwrite/Utopia/Response/Model/AttributeBoolean.php rename to src/Appwrite/Utopia/Response/Model/ColumnBoolean.php index 05846817ca..ffbfe0e793 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnBoolean.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -class AttributeBoolean extends Attribute +class ColumnBoolean extends Column { public function __construct() { @@ -13,13 +13,13 @@ class AttributeBoolean extends Attribute $this ->addRule('key', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute Key.', + 'description' => 'Column Key.', 'default' => '', 'example' => 'isEnabled', ]) ->addRule('type', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute type.', + 'description' => 'Column type.', 'default' => '', 'example' => 'boolean', ]) @@ -44,7 +44,7 @@ class AttributeBoolean extends Attribute */ public function getName(): string { - return 'AttributeBoolean'; + return 'ColumnBoolean'; } /** @@ -54,6 +54,6 @@ class AttributeBoolean extends Attribute */ public function getType(): string { - return Response::MODEL_ATTRIBUTE_BOOLEAN; + return Response::MODEL_COLUMN_BOOLEAN; } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeDatetime.php b/src/Appwrite/Utopia/Response/Model/ColumnDatetime.php similarity index 86% rename from src/Appwrite/Utopia/Response/Model/AttributeDatetime.php rename to src/Appwrite/Utopia/Response/Model/ColumnDatetime.php index 4651aebd06..4c68102775 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeDatetime.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnDatetime.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -class AttributeDatetime extends Attribute +class ColumnDatetime extends Column { public function __construct() { @@ -13,13 +13,13 @@ class AttributeDatetime extends Attribute $this ->addRule('key', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute Key.', + 'description' => 'Column Key.', 'default' => '', 'example' => 'birthDay', ]) ->addRule('type', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute type.', + 'description' => 'Column type.', 'default' => '', 'example' => self::TYPE_DATETIME, ]) @@ -52,7 +52,7 @@ class AttributeDatetime extends Attribute */ public function getName(): string { - return 'AttributeDatetime'; + return 'ColumnDatetime'; } /** @@ -62,6 +62,6 @@ class AttributeDatetime extends Attribute */ public function getType(): string { - return Response::MODEL_ATTRIBUTE_DATETIME; + return Response::MODEL_COLUMN_DATETIME; } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeEmail.php b/src/Appwrite/Utopia/Response/Model/ColumnEmail.php similarity index 86% rename from src/Appwrite/Utopia/Response/Model/AttributeEmail.php rename to src/Appwrite/Utopia/Response/Model/ColumnEmail.php index 078087dd4b..446f993227 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeEmail.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnEmail.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -class AttributeEmail extends Attribute +class ColumnEmail extends Column { public function __construct() { @@ -13,13 +13,13 @@ class AttributeEmail extends Attribute $this ->addRule('key', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute Key.', + 'description' => 'Column Key.', 'default' => '', 'example' => 'userEmail', ]) ->addRule('type', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute type.', + 'description' => 'Column type.', 'default' => '', 'example' => 'string', ]) @@ -51,7 +51,7 @@ class AttributeEmail extends Attribute */ public function getName(): string { - return 'AttributeEmail'; + return 'ColumnEmail'; } /** @@ -61,6 +61,6 @@ class AttributeEmail extends Attribute */ public function getType(): string { - return Response::MODEL_ATTRIBUTE_EMAIL; + return Response::MODEL_COLUMN_EMAIL; } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeEnum.php b/src/Appwrite/Utopia/Response/Model/ColumnEnum.php similarity index 88% rename from src/Appwrite/Utopia/Response/Model/AttributeEnum.php rename to src/Appwrite/Utopia/Response/Model/ColumnEnum.php index 992b62ee3a..b0873a2f7b 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeEnum.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnEnum.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -class AttributeEnum extends Attribute +class ColumnEnum extends Column { public function __construct() { @@ -13,13 +13,13 @@ class AttributeEnum extends Attribute $this ->addRule('key', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute Key.', + 'description' => 'Column Key.', 'default' => '', 'example' => 'status', ]) ->addRule('type', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute type.', + 'description' => 'Column type.', 'default' => '', 'example' => 'string', ]) @@ -58,7 +58,7 @@ class AttributeEnum extends Attribute */ public function getName(): string { - return 'AttributeEnum'; + return 'ColumnEnum'; } /** @@ -68,6 +68,6 @@ class AttributeEnum extends Attribute */ public function getType(): string { - return Response::MODEL_ATTRIBUTE_ENUM; + return Response::MODEL_COLUMN_ENUM; } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeFloat.php b/src/Appwrite/Utopia/Response/Model/ColumnFloat.php similarity index 88% rename from src/Appwrite/Utopia/Response/Model/AttributeFloat.php rename to src/Appwrite/Utopia/Response/Model/ColumnFloat.php index 266b89c330..5867ac8712 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeFloat.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnFloat.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -class AttributeFloat extends Attribute +class ColumnFloat extends Column { public function __construct() { @@ -13,13 +13,13 @@ class AttributeFloat extends Attribute $this ->addRule('key', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute Key.', + 'description' => 'Column Key.', 'default' => '', 'example' => 'percentageCompleted', ]) ->addRule('type', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute type.', + 'description' => 'Column type.', 'default' => '', 'example' => 'double', ]) @@ -58,7 +58,7 @@ class AttributeFloat extends Attribute */ public function getName(): string { - return 'AttributeFloat'; + return 'ColumnFloat'; } /** @@ -68,6 +68,6 @@ class AttributeFloat extends Attribute */ public function getType(): string { - return Response::MODEL_ATTRIBUTE_FLOAT; + return Response::MODEL_COLUMN_FLOAT; } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeIP.php b/src/Appwrite/Utopia/Response/Model/ColumnIP.php similarity index 87% rename from src/Appwrite/Utopia/Response/Model/AttributeIP.php rename to src/Appwrite/Utopia/Response/Model/ColumnIP.php index cfa309317a..2ca7130720 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeIP.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnIP.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -class AttributeIP extends Attribute +class ColumnIP extends Column { public function __construct() { @@ -13,13 +13,13 @@ class AttributeIP extends Attribute $this ->addRule('key', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute Key.', + 'description' => 'Column Key.', 'default' => '', 'example' => 'ipAddress', ]) ->addRule('type', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute type.', + 'description' => 'Column type.', 'default' => '', 'example' => 'string', ]) @@ -51,7 +51,7 @@ class AttributeIP extends Attribute */ public function getName(): string { - return 'AttributeIP'; + return 'ColumnIP'; } /** @@ -61,6 +61,6 @@ class AttributeIP extends Attribute */ public function getType(): string { - return Response::MODEL_ATTRIBUTE_IP; + return Response::MODEL_COLUMN_IP; } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeInteger.php b/src/Appwrite/Utopia/Response/Model/ColumnInteger.php similarity index 88% rename from src/Appwrite/Utopia/Response/Model/AttributeInteger.php rename to src/Appwrite/Utopia/Response/Model/ColumnInteger.php index fddfe57445..086f36a961 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeInteger.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnInteger.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -class AttributeInteger extends Attribute +class ColumnInteger extends Column { public function __construct() { @@ -13,13 +13,13 @@ class AttributeInteger extends Attribute $this ->addRule('key', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute Key.', + 'description' => 'Column Key.', 'default' => '', 'example' => 'count', ]) ->addRule('type', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute type.', + 'description' => 'Column type.', 'default' => '', 'example' => 'integer', ]) @@ -57,7 +57,7 @@ class AttributeInteger extends Attribute */ public function getName(): string { - return 'AttributeInteger'; + return 'ColumnInteger'; } /** @@ -67,6 +67,6 @@ class AttributeInteger extends Attribute */ public function getType(): string { - return Response::MODEL_ATTRIBUTE_INTEGER; + return Response::MODEL_COLUMN_INTEGER; } } diff --git a/src/Appwrite/Utopia/Response/Model/ColumnList.php b/src/Appwrite/Utopia/Response/Model/ColumnList.php new file mode 100644 index 0000000000..0c9f5a49b5 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/ColumnList.php @@ -0,0 +1,58 @@ +addRule('total', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total number of columns in the given table.', + 'default' => 0, + 'example' => 5, + ]) + ->addRule('columns', [ + 'type' => [ + Response::MODEL_COLUMN_BOOLEAN, + Response::MODEL_COLUMN_INTEGER, + Response::MODEL_COLUMN_FLOAT, + Response::MODEL_COLUMN_EMAIL, + Response::MODEL_COLUMN_ENUM, + Response::MODEL_COLUMN_URL, + Response::MODEL_COLUMN_IP, + Response::MODEL_COLUMN_DATETIME, + Response::MODEL_COLUMN_RELATIONSHIP, + Response::MODEL_COLUMN_STRING // needs to be last, since its condition would dominate any other string attribute + ], + 'description' => 'List of columns.', + 'default' => [], + 'array' => true + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'Columns List'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_COLUMN_LIST; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php b/src/Appwrite/Utopia/Response/Model/ColumnRelationship.php similarity index 91% rename from src/Appwrite/Utopia/Response/Model/AttributeRelationship.php rename to src/Appwrite/Utopia/Response/Model/ColumnRelationship.php index d88fbd1530..2c5649b5bf 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnRelationship.php @@ -5,7 +5,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Utopia\Database\Document; -class AttributeRelationship extends Attribute +class ColumnRelationship extends Column { public function __construct() { @@ -14,9 +14,9 @@ class AttributeRelationship extends Attribute $this ->addRule('relatedCollection', [ 'type' => self::TYPE_STRING, - 'description' => 'The ID of the related collection.', + 'description' => 'The ID of the related table.', 'default' => null, - 'example' => 'collection', + 'example' => 'table', ]) ->addRule('relationType', [ 'type' => self::TYPE_STRING, @@ -62,7 +62,7 @@ class AttributeRelationship extends Attribute */ public function getName(): string { - return 'AttributeRelationship'; + return 'ColumnRelationship'; } /** @@ -72,7 +72,7 @@ class AttributeRelationship extends Attribute */ public function getType(): string { - return Response::MODEL_ATTRIBUTE_RELATIONSHIP; + return Response::MODEL_COLUMN_RELATIONSHIP; } /** diff --git a/src/Appwrite/Utopia/Response/Model/AttributeString.php b/src/Appwrite/Utopia/Response/Model/ColumnString.php similarity index 74% rename from src/Appwrite/Utopia/Response/Model/AttributeString.php rename to src/Appwrite/Utopia/Response/Model/ColumnString.php index 12bb42009d..f962e51c37 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeString.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnString.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -class AttributeString extends Attribute +class ColumnString extends Column { public function __construct() { @@ -13,13 +13,13 @@ class AttributeString extends Attribute $this ->addRule('size', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Attribute size.', + 'description' => 'Column size.', 'default' => 0, 'example' => 128, ]) ->addRule('default', [ 'type' => self::TYPE_STRING, - 'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.', + 'description' => 'Default value for column when not provided. Cannot be set when column is required.', 'default' => null, 'required' => false, 'example' => 'default', @@ -38,7 +38,7 @@ class AttributeString extends Attribute */ public function getName(): string { - return 'AttributeString'; + return 'ColumnString'; } /** @@ -48,6 +48,6 @@ class AttributeString extends Attribute */ public function getType(): string { - return Response::MODEL_ATTRIBUTE_STRING; + return Response::MODEL_COLUMN_STRING; } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeURL.php b/src/Appwrite/Utopia/Response/Model/ColumnURL.php similarity index 76% rename from src/Appwrite/Utopia/Response/Model/AttributeURL.php rename to src/Appwrite/Utopia/Response/Model/ColumnURL.php index 633d5b49d7..12850b3907 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeURL.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnURL.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -class AttributeURL extends Attribute +class ColumnURL extends Column { public function __construct() { @@ -13,13 +13,13 @@ class AttributeURL extends Attribute $this ->addRule('key', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute Key.', + 'description' => 'Column Key.', 'default' => '', 'example' => 'githubUrl', ]) ->addRule('type', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute type.', + 'description' => 'Column type.', 'default' => '', 'example' => 'string', ]) @@ -31,10 +31,10 @@ class AttributeURL extends Attribute ]) ->addRule('default', [ 'type' => self::TYPE_STRING, - 'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.', + 'description' => 'Default value for column when not provided. Cannot be set when column is required.', 'default' => null, 'required' => false, - 'example' => 'http://example.com', + 'example' => 'https://example.com', ]) ; } @@ -51,7 +51,7 @@ class AttributeURL extends Attribute */ public function getName(): string { - return 'AttributeURL'; + return 'ColumnURL'; } /** @@ -61,6 +61,6 @@ class AttributeURL extends Attribute */ public function getType(): string { - return Response::MODEL_ATTRIBUTE_URL; + return Response::MODEL_COLUMN_URL; } } diff --git a/src/Appwrite/Utopia/Response/Model/Table.php b/src/Appwrite/Utopia/Response/Model/Table.php index 305f1db3c9..d7098f313f 100644 --- a/src/Appwrite/Utopia/Response/Model/Table.php +++ b/src/Appwrite/Utopia/Response/Model/Table.php @@ -61,16 +61,16 @@ class Table extends Model ]) ->addRule('columns', [ 'type' => [ - Response::MODEL_ATTRIBUTE_BOOLEAN, - Response::MODEL_ATTRIBUTE_INTEGER, - Response::MODEL_ATTRIBUTE_FLOAT, - Response::MODEL_ATTRIBUTE_EMAIL, - Response::MODEL_ATTRIBUTE_ENUM, - Response::MODEL_ATTRIBUTE_URL, - Response::MODEL_ATTRIBUTE_IP, - Response::MODEL_ATTRIBUTE_DATETIME, - Response::MODEL_ATTRIBUTE_RELATIONSHIP, - Response::MODEL_ATTRIBUTE_STRING, // needs to be last, since its condition would dominate any other string attribute + Response::MODEL_COLUMN_BOOLEAN, + Response::MODEL_COLUMN_INTEGER, + Response::MODEL_COLUMN_FLOAT, + Response::MODEL_COLUMN_EMAIL, + Response::MODEL_COLUMN_ENUM, + Response::MODEL_COLUMN_URL, + Response::MODEL_COLUMN_IP, + Response::MODEL_COLUMN_DATETIME, + Response::MODEL_COLUMN_RELATIONSHIP, + Response::MODEL_COLUMN_STRING, // needs to be last, since its condition would dominate any other string attribute ], 'description' => 'Table columns.', 'default' => [], From 7a5368078622fdaa8ef08ffb55121586dda197e1 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 5 May 2025 09:42:33 +0530 Subject: [PATCH 045/343] update: `document` response model to `row`; refactor: old collection to table models on response types. --- app/config/events.php | 4 +-- .../Modules/Databases/Http/Rows/Create.php | 4 +-- .../Modules/Databases/Http/Rows/Delete.php | 2 +- .../Modules/Databases/Http/Rows/Get.php | 4 +-- .../Modules/Databases/Http/Rows/Update.php | 4 +-- .../Modules/Databases/Http/Rows/XList.php | 4 +-- .../Modules/Databases/Http/Tables/Create.php | 4 +-- .../Modules/Databases/Http/Tables/Delete.php | 2 +- .../Modules/Databases/Http/Tables/Get.php | 4 +-- .../Modules/Databases/Http/Tables/Update.php | 4 +-- .../Modules/Databases/Http/Tables/XList.php | 6 ++--- src/Appwrite/Utopia/Response.php | 10 +++---- .../Response/Model/{Document.php => Row.php} | 26 +++++++++---------- tests/unit/GraphQL/BuilderTest.php | 4 +-- 14 files changed, 41 insertions(+), 41 deletions(-) rename src/Appwrite/Utopia/Response/Model/{Document.php => Row.php} (73%) diff --git a/app/config/events.php b/app/config/events.php index 41857fad70..4523b56206 100644 --- a/app/config/events.php +++ b/app/config/events.php @@ -96,11 +96,11 @@ return [ '$resource' => true, '$description' => 'This event triggers on any database event.', 'tables' => [ - '$model' => Response::MODEL_COLLECTION, + '$model' => Response::MODEL_TABLE, '$resource' => true, '$description' => 'This event triggers on any table event.', 'rows' => [ - '$model' => Response::MODEL_DOCUMENT, + '$model' => Response::MODEL_ROW, '$resource' => true, '$description' => 'This event triggers on any rows event.', 'create' => [ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php index 215ee94550..55efbc3632 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php @@ -63,7 +63,7 @@ class Create extends Action responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_CREATED, - model: UtopiaResponse::MODEL_DOCUMENT, + model: UtopiaResponse::MODEL_ROW, ) ], contentType: ContentType::JSON @@ -293,7 +293,7 @@ class Create extends Action $response ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) - ->dynamic($row, UtopiaResponse::MODEL_DOCUMENT); + ->dynamic($row, UtopiaResponse::MODEL_ROW); $relationships = \array_map( fn ($document) => $document->getAttribute('key'), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php index 61ed961c64..bba042bca5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php @@ -160,7 +160,7 @@ class Delete extends Action ->setParam('rowId', $row->getId()) ->setContext('table', $table) ->setContext('database', $database) - ->setPayload($response->output($row, UtopiaResponse::MODEL_DOCUMENT), sensitive: $relationships); + ->setPayload($response->output($row, UtopiaResponse::MODEL_ROW), sensitive: $relationships); $response->noContent(); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php index a3a484be70..85b6127bd3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php @@ -51,7 +51,7 @@ class Get extends Action responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_DOCUMENT, + model: UtopiaResponse::MODEL_ROW, ) ], contentType: ContentType::JSON @@ -149,6 +149,6 @@ class Get extends Action $response->addHeader('X-Debug-Operations', $operations); - $response->dynamic($row, UtopiaResponse::MODEL_DOCUMENT); + $response->dynamic($row, UtopiaResponse::MODEL_ROW); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php index bc41118206..b7f3a4f6c4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php @@ -62,7 +62,7 @@ class Update extends Action responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_DOCUMENT, + model: UtopiaResponse::MODEL_ROW, ) ], contentType: ContentType::JSON @@ -281,7 +281,7 @@ class Update extends Action $processRow($table, $row); - $response->dynamic($row, UtopiaResponse::MODEL_DOCUMENT); + $response->dynamic($row, UtopiaResponse::MODEL_ROW); $relationships = \array_map( fn ($document) => $document->getAttribute('key'), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php index b27930405f..e93d72cad6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php @@ -52,7 +52,7 @@ class XList extends Action responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_DOCUMENT_LIST, + model: UtopiaResponse::MODEL_ROW_LIST, ) ], contentType: ContentType::JSON @@ -218,6 +218,6 @@ class XList extends Action $response->dynamic(new Document([ 'total' => $total, 'documents' => $rows, - ]), UtopiaResponse::MODEL_DOCUMENT_LIST); + ]), UtopiaResponse::MODEL_ROW_LIST); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php index ead5a64f88..9acd248190 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php @@ -56,7 +56,7 @@ class Create extends Action responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_CREATED, - model: UtopiaResponse::MODEL_COLLECTION, + model: UtopiaResponse::MODEL_TABLE, ) ], contentType: ContentType::JSON @@ -111,6 +111,6 @@ class Create extends Action $response ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) - ->dynamic($table, UtopiaResponse::MODEL_COLLECTION); + ->dynamic($table, UtopiaResponse::MODEL_TABLE); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php index 92003f3eeb..6fe7228ed9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php @@ -89,7 +89,7 @@ class Delete extends Action ->setContext('database', $database) ->setParam('databaseId', $databaseId) ->setParam('tableId', $table->getId()) - ->setPayload($response->output($table, UtopiaResponse::MODEL_COLLECTION)); + ->setPayload($response->output($table, UtopiaResponse::MODEL_TABLE)); $response->noContent(); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php index 2b0f77fc81..63bc1fa48c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php @@ -43,7 +43,7 @@ class Get extends Action responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLLECTION, + model: UtopiaResponse::MODEL_TABLE, ) ], contentType: ContentType::JSON @@ -69,6 +69,6 @@ class Get extends Action throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $response->dynamic($table, UtopiaResponse::MODEL_COLLECTION); + $response->dynamic($table, UtopiaResponse::MODEL_TABLE); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php index dc302ce47f..d5f8d388ab 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php @@ -51,7 +51,7 @@ class Update extends Action responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLLECTION, + model: UtopiaResponse::MODEL_TABLE, ) ], contentType: ContentType::JSON @@ -105,6 +105,6 @@ class Update extends Action ->setParam('databaseId', $databaseId) ->setParam('tableId', $table->getId()); - $response->dynamic($table, UtopiaResponse::MODEL_COLLECTION); + $response->dynamic($table, UtopiaResponse::MODEL_TABLE); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php index 85474840df..a5e6789eaa 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php @@ -49,7 +49,7 @@ class XList extends Action responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLLECTION_LIST, + model: UtopiaResponse::MODEL_TABLE, ) ], contentType: ContentType::JSON @@ -110,8 +110,8 @@ class XList extends Action } $response->dynamic(new Document([ - 'collections' => $tables, // TODO: consider renaming to 'tables' + 'collections' => $tables, 'total' => $total, - ]), UtopiaResponse::MODEL_COLLECTION_LIST); + ]), UtopiaResponse::MODEL_TABLE_LIST); } } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 0fae030b82..2ea399c450 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -40,7 +40,6 @@ use Appwrite\Utopia\Response\Model\Deployment; use Appwrite\Utopia\Response\Model\DetectionFramework; use Appwrite\Utopia\Response\Model\DetectionRuntime; use Appwrite\Utopia\Response\Model\DevKey; -use Appwrite\Utopia\Response\Model\Document as ModelDocument; use Appwrite\Utopia\Response\Model\Error; use Appwrite\Utopia\Response\Model\ErrorDev; use Appwrite\Utopia\Response\Model\Execution; @@ -87,6 +86,7 @@ use Appwrite\Utopia\Response\Model\ProviderRepository; use Appwrite\Utopia\Response\Model\ProviderRepositoryFramework; use Appwrite\Utopia\Response\Model\ProviderRepositoryRuntime; use Appwrite\Utopia\Response\Model\ResourceToken; +use Appwrite\Utopia\Response\Model\Row; use Appwrite\Utopia\Response\Model\Rule; use Appwrite\Utopia\Response\Model\Runtime; use Appwrite\Utopia\Response\Model\Session; @@ -164,8 +164,8 @@ class Response extends SwooleResponse public const MODEL_TABLE_LIST = 'tableList'; public const MODEL_INDEX = 'index'; public const MODEL_INDEX_LIST = 'indexList'; - public const MODEL_DOCUMENT = 'document'; - public const MODEL_DOCUMENT_LIST = 'documentList'; + public const MODEL_ROW = 'row'; + public const MODEL_ROW_LIST = 'rowList'; // Database Attributes public const MODEL_COLUMN = 'column'; @@ -376,7 +376,7 @@ class Response extends SwooleResponse ->setModel(new Error()) ->setModel(new ErrorDev()) // Lists - ->setModel(new BaseList('Rows List', self::MODEL_DOCUMENT_LIST, 'rows', self::MODEL_DOCUMENT)) + ->setModel(new BaseList('Rows List', self::MODEL_ROW_LIST, 'rows', self::MODEL_ROW)) ->setModel(new BaseList('Tables List', self::MODEL_TABLE_LIST, 'tables', self::MODEL_TABLE)) ->setModel(new BaseList('Databases List', self::MODEL_DATABASE_LIST, 'databases', self::MODEL_DATABASE)) ->setModel(new BaseList('Indexes List', self::MODEL_INDEX_LIST, 'indexes', self::MODEL_INDEX)) @@ -442,7 +442,7 @@ class Response extends SwooleResponse ->setModel(new ColumnDatetime()) ->setModel(new ColumnRelationship()) ->setModel(new Index()) - ->setModel(new ModelDocument()) + ->setModel(new Row()) ->setModel(new Log()) ->setModel(new User()) ->setModel(new AlgoMd5()) diff --git a/src/Appwrite/Utopia/Response/Model/Document.php b/src/Appwrite/Utopia/Response/Model/Row.php similarity index 73% rename from src/Appwrite/Utopia/Response/Model/Document.php rename to src/Appwrite/Utopia/Response/Model/Row.php index 41a10cee89..49325bdc81 100644 --- a/src/Appwrite/Utopia/Response/Model/Document.php +++ b/src/Appwrite/Utopia/Response/Model/Row.php @@ -5,7 +5,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Utopia\Database\Document as DatabaseDocument; -class Document extends Any +class Row extends Any { /** * Get Name @@ -14,7 +14,7 @@ class Document extends Any */ public function getName(): string { - return 'Document'; + return 'Row'; } /** @@ -24,7 +24,7 @@ class Document extends Any */ public function getType(): string { - return Response::MODEL_DOCUMENT; + return Response::MODEL_ROW; } public function __construct() @@ -32,13 +32,13 @@ class Document extends Any $this ->addRule('$id', [ 'type' => self::TYPE_STRING, - 'description' => 'Document ID.', + 'description' => 'Row ID.', 'default' => '', 'example' => '5e5ea5c16897e', ]) ->addRule('$collectionId', [ 'type' => self::TYPE_STRING, - 'description' => 'Collection ID.', + 'description' => 'Table ID.', 'default' => '', 'example' => '5e5ea5c15117e', ]) @@ -50,19 +50,19 @@ class Document extends Any ]) ->addRule('$createdAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Document creation date in ISO 8601 format.', + 'description' => 'Row creation date in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) ->addRule('$updatedAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Document update date in ISO 8601 format.', + 'description' => 'Row update date in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) ->addRule('$permissions', [ 'type' => self::TYPE_STRING, - 'description' => 'Document permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', + 'description' => 'Row permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', 'default' => '', 'example' => ['read("any")'], 'array' => true, @@ -75,15 +75,15 @@ class Document extends Any $document->removeAttribute('$collection'); $document->removeAttribute('$tenant'); - foreach ($document->getAttributes() as $attribute) { - if (\is_array($attribute)) { - foreach ($attribute as $subAttribute) { + foreach ($document->getAttributes() as $column) { + if (\is_array($column)) { + foreach ($column as $subAttribute) { if ($subAttribute instanceof DatabaseDocument) { $this->filter($subAttribute); } } - } elseif ($attribute instanceof DatabaseDocument) { - $this->filter($attribute); + } elseif ($column instanceof DatabaseDocument) { + $this->filter($column); } } diff --git a/tests/unit/GraphQL/BuilderTest.php b/tests/unit/GraphQL/BuilderTest.php index d79a104c90..3dd1bcadc7 100644 --- a/tests/unit/GraphQL/BuilderTest.php +++ b/tests/unit/GraphQL/BuilderTest.php @@ -22,8 +22,8 @@ class BuilderTest extends TestCase */ public function testCreateTypeMapping() { - $model = $this->response->getModel(Response::MODEL_COLLECTION); + $model = $this->response->getModel(Response::MODEL_TABLE); $type = Mapper::model(\ucfirst($model->getType())); - $this->assertEquals('Collection', $type->name); + $this->assertEquals('Table', $type->name); } } From cabf32559a723d28c6f8f1b6fb09bb2a3678d7e6 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 5 May 2025 09:50:57 +0530 Subject: [PATCH 046/343] update: return keys. --- .../Platform/Modules/Databases/Http/Columns/XList.php | 2 +- .../Modules/Databases/Http/Databases/Usage/Get.php | 8 ++++---- .../Modules/Databases/Http/Databases/Usage/XList.php | 8 ++++---- .../Platform/Modules/Databases/Http/Rows/Update.php | 10 +++++----- .../Platform/Modules/Databases/Http/Rows/XList.php | 2 +- .../Modules/Databases/Http/Tables/Usage/Get.php | 4 ++-- .../Platform/Modules/Databases/Http/Tables/XList.php | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php index cba6e2d077..e9800e71a0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php @@ -118,7 +118,7 @@ class XList extends Action } $response->dynamic(new Document([ - 'attributes' => $columns, + 'columns' => $columns, 'total' => $total, ]), UtopiaResponse::MODEL_COLUMN_LIST); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php index c4105effa0..c7ae2e4d81 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -123,13 +123,13 @@ class Get extends Action $response->dynamic(new Document([ 'range' => $range, - 'collectionsTotal' => $usage[$metrics[0]]['total'], - 'documentsTotal' => $usage[$metrics[1]]['total'], + 'tablesTotal' => $usage[$metrics[0]]['total'], + 'rowsTotal' => $usage[$metrics[1]]['total'], 'storageTotal' => $usage[$metrics[2]]['total'], 'databaseReadsTotal' => $usage[$metrics[3]]['total'], 'databaseWritesTotal' => $usage[$metrics[4]]['total'], - 'collections' => $usage[$metrics[0]]['data'], - 'documents' => $usage[$metrics[1]]['data'], + 'tables' => $usage[$metrics[0]]['data'], + 'rows' => $usage[$metrics[1]]['data'], 'storage' => $usage[$metrics[2]]['data'], 'databaseReads' => $usage[$metrics[3]]['data'], 'databaseWrites' => $usage[$metrics[4]]['data'], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php index 0078d54a4b..8737585e8c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -116,14 +116,14 @@ class XList extends Action $response->dynamic(new Document([ 'range' => $range, 'databasesTotal' => $usage[$metrics[0]]['total'], - 'collectionsTotal' => $usage[$metrics[1]]['total'], - 'documentsTotal' => $usage[$metrics[2]]['total'], + 'tablesTotal' => $usage[$metrics[1]]['total'], + 'rowsTotal' => $usage[$metrics[2]]['total'], 'storageTotal' => $usage[$metrics[3]]['total'], 'databasesReadsTotal' => $usage[$metrics[4]]['total'], 'databasesWritesTotal' => $usage[$metrics[5]]['total'], 'databases' => $usage[$metrics[0]]['data'], - 'collections' => $usage[$metrics[1]]['data'], - 'documents' => $usage[$metrics[2]]['data'], + 'tables' => $usage[$metrics[1]]['data'], + 'rows' => $usage[$metrics[2]]['data'], 'storage' => $usage[$metrics[3]]['data'], 'databasesReads' => $usage[$metrics[4]]['data'], 'databasesWrites' => $usage[$metrics[5]]['data'], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php index b7f3a4f6c4..c9ed71d569 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php @@ -150,17 +150,17 @@ class Update extends Action $operations = 0; - $setTable = (function (Document $collection, Document $document) use (&$setTable, $dbForProject, $database, &$operations) { + $setTable = (function (Document $table, Document $row) use (&$setTable, $dbForProject, $database, &$operations) { $operations++; $relationships = \array_filter( - $collection->getAttribute('attributes', []), + $table->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); + $related = $row->getAttribute($relationship->getAttribute('key')); if (empty($related)) { continue; @@ -212,9 +212,9 @@ class Update extends Action } if ($isList) { - $document->setAttribute($relationship->getAttribute('key'), \array_values($relations)); + $row->setAttribute($relationship->getAttribute('key'), \array_values($relations)); } else { - $document->setAttribute($relationship->getAttribute('key'), \reset($relations)); + $row->setAttribute($relationship->getAttribute('key'), \reset($relations)); } } }); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php index e93d72cad6..4396c2b112 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php @@ -217,7 +217,7 @@ class XList extends Action $response->dynamic(new Document([ 'total' => $total, - 'documents' => $rows, + 'rows' => $rows, ]), UtopiaResponse::MODEL_ROW_LIST); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php index 3943c27618..b55fa84282 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php @@ -124,8 +124,8 @@ class Get extends Action $response->dynamic(new Document([ 'range' => $range, - 'documentsTotal' => $usage[$metrics[0]]['total'], - 'documents' => $usage[$metrics[0]]['data'], + 'rows' => $usage[$metrics[0]]['data'], + 'rowsTotal' => $usage[$metrics[0]]['total'], ]), UtopiaResponse::MODEL_USAGE_COLLECTION); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php index a5e6789eaa..86107cc533 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php @@ -110,7 +110,7 @@ class XList extends Action } $response->dynamic(new Document([ - 'collections' => $tables, + 'tables' => $tables, 'total' => $total, ]), UtopiaResponse::MODEL_TABLE_LIST); } From 6cb44399c147cffe0dfb69dc0e4276da9230bdcd Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 5 May 2025 10:57:54 +0530 Subject: [PATCH 047/343] update: services. --- app/config/services.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/services.php b/app/config/services.php index 7e4656a277..edc4024272 100644 --- a/app/config/services.php +++ b/app/config/services.php @@ -58,7 +58,7 @@ return [ 'name' => 'Databases', 'subtitle' => 'The Databases service allows you to create structured collections of documents, query and filter lists of documents', 'description' => '/docs/services/databases.md', - 'controller' => 'api/databases.php', + 'controller' => '', // Uses modules 'sdk' => true, 'docs' => true, 'docsUrl' => 'https://appwrite.io/docs/client/databases', From 71ad9c203e7d03be19958618a71ba234d34959ec Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 5 May 2025 13:53:57 +0530 Subject: [PATCH 048/343] fix: response modals, mappings, filters. --- .../Databases/Http/Tables/Usage/Get.php | 4 +- src/Appwrite/Utopia/Request/Filters/V19.php | 19 +++-- src/Appwrite/Utopia/Response.php | 6 +- src/Appwrite/Utopia/Response/Filters/V19.php | 77 ++++++++++++++++++- .../Response/Model/ColumnRelationship.php | 4 +- src/Appwrite/Utopia/Response/Model/Table.php | 38 +++++++++ .../Utopia/Response/Model/UsageDatabase.php | 16 ++-- .../Utopia/Response/Model/UsageDatabases.php | 16 ++-- .../{UsageCollection.php => UsageTable.php} | 14 ++-- 9 files changed, 152 insertions(+), 42 deletions(-) rename src/Appwrite/Utopia/Response/Model/{UsageCollection.php => UsageTable.php} (77%) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php index b55fa84282..4c591bff1a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php @@ -47,7 +47,7 @@ class Get extends Action responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_USAGE_COLLECTION, + model: UtopiaResponse::MODEL_USAGE_TABLE, ) ], contentType: ContentType::JSON, @@ -126,6 +126,6 @@ class Get extends Action 'range' => $range, 'rows' => $usage[$metrics[0]]['data'], 'rowsTotal' => $usage[$metrics[0]]['total'], - ]), UtopiaResponse::MODEL_USAGE_COLLECTION); + ]), UtopiaResponse::MODEL_USAGE_TABLE); } } diff --git a/src/Appwrite/Utopia/Request/Filters/V19.php b/src/Appwrite/Utopia/Request/Filters/V19.php index 041c126a69..ee04cea038 100644 --- a/src/Appwrite/Utopia/Request/Filters/V19.php +++ b/src/Appwrite/Utopia/Request/Filters/V19.php @@ -9,15 +9,18 @@ class V19 extends Filter // Convert 1.6 params to 1.7 public function parse(array $content, string $model): array { - /* - Uncomment with first request filter; current is just a copy of V18 - switch ($model) { - case 'functions.create': - $content['something'] = $content['somethingElse'] ?? ""; - unset($content['something']); - break; + return match ($model) { + 'databases.createRelationshipColumn' => $this->convertV16RelationshipParams($content), + default => $content + }; + } + + protected function convertV16RelationshipParams(array $content): array + { + if (isset($content['relatedCollectionId'])) { + $content['relatedTableId'] = $content['relatedCollectionId']; + unset($content['relatedCollectionId']); } - */ return $content; } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 2ea399c450..62822e9956 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -106,7 +106,6 @@ use Appwrite\Utopia\Response\Model\TemplateVariable; use Appwrite\Utopia\Response\Model\Token; use Appwrite\Utopia\Response\Model\Topic; use Appwrite\Utopia\Response\Model\UsageBuckets; -use Appwrite\Utopia\Response\Model\UsageCollection; use Appwrite\Utopia\Response\Model\UsageDatabase; use Appwrite\Utopia\Response\Model\UsageDatabases; use Appwrite\Utopia\Response\Model\UsageFunction; @@ -115,6 +114,7 @@ use Appwrite\Utopia\Response\Model\UsageProject; use Appwrite\Utopia\Response\Model\UsageSite; use Appwrite\Utopia\Response\Model\UsageSites; use Appwrite\Utopia\Response\Model\UsageStorage; +use Appwrite\Utopia\Response\Model\UsageTable; use Appwrite\Utopia\Response\Model\UsageUsers; use Appwrite\Utopia\Response\Model\User; use Appwrite\Utopia\Response\Model\Variable; @@ -147,7 +147,7 @@ class Response extends SwooleResponse public const MODEL_BASE_LIST = 'baseList'; public const MODEL_USAGE_DATABASES = 'usageDatabases'; public const MODEL_USAGE_DATABASE = 'usageDatabase'; - public const MODEL_USAGE_COLLECTION = 'usageCollection'; + public const MODEL_USAGE_TABLE = 'usageTable'; public const MODEL_USAGE_USERS = 'usageUsers'; public const MODEL_USAGE_BUCKETS = 'usageBuckets'; public const MODEL_USAGE_STORAGE = 'usageStorage'; @@ -508,7 +508,7 @@ class Response extends SwooleResponse ->setModel(new MetricBreakdown()) ->setModel(new UsageDatabases()) ->setModel(new UsageDatabase()) - ->setModel(new UsageCollection()) + ->setModel(new UsageTable()) ->setModel(new UsageUsers()) ->setModel(new UsageStorage()) ->setModel(new UsageBuckets()) diff --git a/src/Appwrite/Utopia/Response/Filters/V19.php b/src/Appwrite/Utopia/Response/Filters/V19.php index 2987c5a7e4..5e1a7e40e7 100644 --- a/src/Appwrite/Utopia/Response/Filters/V19.php +++ b/src/Appwrite/Utopia/Response/Filters/V19.php @@ -7,24 +7,93 @@ use Appwrite\Utopia\Response\Filter; class V19 extends Filter { + private const DATABASE_MAPPINGS = [ + 'table' => 'collection', + 'tables' => 'collections', + 'tablesTotal' => 'collectionsTotal', + 'relatedTable' => 'relatedCollection', + + 'column' => 'attribute', + 'columns' => 'attributes', + 'columnsTotal' => 'attributesTotal', + + 'row' => 'document', + 'rows' => 'documents', + 'rowsTotal' => 'documentsTotal' + ]; + // Convert 1.7 Data format to 1.6 format public function parse(array $content, string $model): array { $parsedResponse = $content; - $parsedResponse = match($model) { + return match ($model) { + Response::MODEL_ROW, + Response::MODEL_TABLE, + Response::MODEL_COLUMN, + Response::MODEL_ROW_LIST, + Response::MODEL_TABLE_LIST, + Response::MODEL_COLUMN_LIST, + Response::MODEL_USAGE_TABLE, + Response::MODEL_USAGE_DATABASE, + Response::MODEL_USAGE_DATABASES, + Response::MODEL_COLUMN_RELATIONSHIP => $this->handleDBTerminology($model, $content), + Response::MODEL_FUNCTION => $this->parseFunction($content), Response::MODEL_FUNCTION_LIST => $this->handleList($content, 'functions', fn ($item) => $this->parseFunction($item)), default => $parsedResponse, }; - - return $parsedResponse; } - protected function parseFunction(array $content) + protected function parseFunction(array $content): array { $content['deployment'] = $content['deploymentId'] ?? ''; unset($content['deploymentId']); return $content; } + + protected function handleDBTerminology(string $model, array $content): array + { + $isListModel = match ($model) { + Response::MODEL_ROW_LIST, + Response::MODEL_TABLE_LIST, + Response::MODEL_COLUMN_LIST => true, + + default => false + }; + + if ($isListModel) { + foreach (self::DATABASE_MAPPINGS as $oldKey => $newKey) { + if (isset($content[$oldKey])) { + $content[$newKey] = array_map(fn ($item) => $this->remapKeys($item), $content[$oldKey]); + unset($content[$oldKey]); + } + } + } else { + $content = $this->remapKeysRecursive($content); + } + + return $content; + } + + private function remapKeys(array $data): array + { + foreach (self::DATABASE_MAPPINGS as $old => $new) { + if (isset($data[$old])) { + $data[$new] = $data[$old]; + unset($data[$old]); + } + } + return $data; + } + + private function remapKeysRecursive(array $data): array + { + $result = []; + foreach ($data as $key => $value) { + $newKey = self::DATABASE_MAPPINGS[$key] ?? $key; + $result[$newKey] = \is_array($value) ? $this->remapKeysRecursive($value) : $value; + } + return $result; + } } diff --git a/src/Appwrite/Utopia/Response/Model/ColumnRelationship.php b/src/Appwrite/Utopia/Response/Model/ColumnRelationship.php index 2c5649b5bf..877982365b 100644 --- a/src/Appwrite/Utopia/Response/Model/ColumnRelationship.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnRelationship.php @@ -12,7 +12,7 @@ class ColumnRelationship extends Column parent::__construct(); $this - ->addRule('relatedCollection', [ + ->addRule('relatedTable', [ 'type' => self::TYPE_STRING, 'description' => 'The ID of the related table.', 'default' => null, @@ -84,7 +84,7 @@ class ColumnRelationship extends Column { $options = $document->getAttribute('options'); if (!\is_null($options)) { - $document->setAttribute('relatedCollection', $options['relatedCollection']); + $document->setAttribute('relatedTable', $options['relatedCollection']); $document->setAttribute('relationType', $options['relationType']); $document->setAttribute('twoWay', $options['twoWay']); $document->setAttribute('twoWayKey', $options['twoWayKey']); diff --git a/src/Appwrite/Utopia/Response/Model/Table.php b/src/Appwrite/Utopia/Response/Model/Table.php index d7098f313f..e36cb1dabd 100644 --- a/src/Appwrite/Utopia/Response/Model/Table.php +++ b/src/Appwrite/Utopia/Response/Model/Table.php @@ -4,6 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; +use Utopia\Database\Document; class Table extends Model { @@ -106,4 +107,41 @@ class Table extends Model { return Response::MODEL_TABLE; } + + /** + * Process Document before returning it to the client for backwards compatibility! + */ + public function filter(Document $document): Document + { + $columns = $document->getAttribute('attributes', []); + if (!empty($columns) && \is_array($columns)) { + $columns = $this->remapNestedRelatedCollections($columns); + } + + $document + ->setAttribute('columns', $columns) + ->removeAttribute('attributes'); + + $related = $document->getAttribute('relatedCollection'); + if ($related !== null) { + $document + ->setAttribute('relatedTable', $related) + ->removeAttribute('relatedCollection'); + } + + return $document; + } + + // 1.7 now sends back `relatedTable` instead of `relatedCollection`. + // This is necessary because the actual database underneath uses `relatedCollection`. + private function remapNestedRelatedCollections(array $columns): array + { + foreach ($columns as $i => $column) { + if (isset($column['relatedCollection'])) { + $columns[$i]['relatedTable'] = $column['relatedCollection']; + unset($columns[$i]['relatedCollection']); + } + } + return $columns; + } } diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php index a0fe421f5f..a3212017a4 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php @@ -16,15 +16,15 @@ class UsageDatabase extends Model 'default' => '', 'example' => '30d', ]) - ->addRule('collectionsTotal', [ + ->addRule('tablesTotal', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of collections.', + 'description' => 'Total aggregated number of tables.', 'default' => 0, 'example' => 0, ]) - ->addRule('documentsTotal', [ + ->addRule('rowsTotal', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of documents.', + 'description' => 'Total aggregated number of rows.', 'default' => 0, 'example' => 0, ]) @@ -46,16 +46,16 @@ class UsageDatabase extends Model 'default' => 0, 'example' => 0, ]) - ->addRule('collections', [ + ->addRule('tables', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of collections per period.', + 'description' => 'Aggregated number of tables per period.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('documents', [ + ->addRule('rows', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of documents per period.', + 'description' => 'Aggregated number of rows per period.', 'default' => [], 'example' => [], 'array' => true diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php index 4e053e5223..11392f6efb 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php @@ -22,15 +22,15 @@ class UsageDatabases extends Model 'default' => 0, 'example' => 0, ]) - ->addRule('collectionsTotal', [ + ->addRule('tablesTotal', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of collections.', + 'description' => 'Total aggregated number of tables.', 'default' => 0, 'example' => 0, ]) - ->addRule('documentsTotal', [ + ->addRule('rowsTotal', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of documents.', + 'description' => 'Total aggregated number of rows.', 'default' => 0, 'example' => 0, ]) @@ -59,16 +59,16 @@ class UsageDatabases extends Model 'example' => [], 'array' => true ]) - ->addRule('collections', [ + ->addRule('tables', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of collections per period.', + 'description' => 'Aggregated number of tables per period.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('documents', [ + ->addRule('rows', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of documents per period.', + 'description' => 'Aggregated number of rows per period.', 'default' => [], 'example' => [], 'array' => true diff --git a/src/Appwrite/Utopia/Response/Model/UsageCollection.php b/src/Appwrite/Utopia/Response/Model/UsageTable.php similarity index 77% rename from src/Appwrite/Utopia/Response/Model/UsageCollection.php rename to src/Appwrite/Utopia/Response/Model/UsageTable.php index b2336d65ba..553a4b5001 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageCollection.php +++ b/src/Appwrite/Utopia/Response/Model/UsageTable.php @@ -5,7 +5,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; -class UsageCollection extends Model +class UsageTable extends Model { public function __construct() { @@ -16,15 +16,15 @@ class UsageCollection extends Model 'default' => '', 'example' => '30d', ]) - ->addRule('documentsTotal', [ + ->addRule('rowsTotal', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of of documents.', + 'description' => 'Total aggregated number of of rows.', 'default' => 0, 'example' => 0, ]) - ->addRule('documents', [ + ->addRule('rows', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of documents per period.', + 'description' => 'Aggregated number of rows per period.', 'default' => [], 'example' => [], 'array' => true @@ -39,7 +39,7 @@ class UsageCollection extends Model */ public function getName(): string { - return 'UsageCollection'; + return 'UsageTable'; } /** @@ -49,6 +49,6 @@ class UsageCollection extends Model */ public function getType(): string { - return Response::MODEL_USAGE_COLLECTION; + return Response::MODEL_USAGE_TABLE; } } From d30fd565733df843c038eb83b7ae418f09ac0901 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 5 May 2025 14:04:39 +0530 Subject: [PATCH 049/343] patch: index module to use/specify `columns` instead of `attributes`. --- src/Appwrite/Utopia/Response/Model/Index.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Utopia/Response/Model/Index.php b/src/Appwrite/Utopia/Response/Model/Index.php index 2d795ad439..e18a9db334 100644 --- a/src/Appwrite/Utopia/Response/Model/Index.php +++ b/src/Appwrite/Utopia/Response/Model/Index.php @@ -4,6 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; +use Utopia\Database\Document; class Index extends Model { @@ -34,7 +35,7 @@ class Index extends Model 'default' => '', 'example' => 'string', ]) - ->addRule('attributes', [ + ->addRule('columns', [ 'type' => self::TYPE_STRING, 'description' => 'Index attributes.', 'default' => [], @@ -78,4 +79,16 @@ class Index extends Model { return Response::MODEL_INDEX; } + + public function filter(Document $document): Document + { + + $columns = $document->getAttribute('attributes', []); + $document + ->removeAttribute('attributes') + ->setAttribute('columns', $columns); + + return $document; + + } } From e2202e9ffa8a9fdbffd93257e251b28d2c25ff2d Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 5 May 2025 14:05:24 +0530 Subject: [PATCH 050/343] remove: old attributes anyway. --- src/Appwrite/Utopia/Response/Model/Table.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Utopia/Response/Model/Table.php b/src/Appwrite/Utopia/Response/Model/Table.php index e36cb1dabd..1855f471b1 100644 --- a/src/Appwrite/Utopia/Response/Model/Table.php +++ b/src/Appwrite/Utopia/Response/Model/Table.php @@ -118,17 +118,18 @@ class Table extends Model $columns = $this->remapNestedRelatedCollections($columns); } - $document - ->setAttribute('columns', $columns) - ->removeAttribute('attributes'); + $document->setAttribute('columns', $columns); $related = $document->getAttribute('relatedCollection'); if ($related !== null) { - $document - ->setAttribute('relatedTable', $related) - ->removeAttribute('relatedCollection'); + $document->setAttribute('relatedTable', $related); } + // remove anyways as they are already copied above. + $document + ->removeAttribute('attributes') + ->removeAttribute('relatedCollection'); + return $document; } From 75c9db8031bd0525053f879dbec13d11f7c5c43e Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 5 May 2025 14:07:34 +0530 Subject: [PATCH 051/343] update: tests to use the 1.7.x changes on databases. --- .../e2e/Services/Databases/DatabasesBase.php | 326 +++++++++--------- .../Databases/DatabasesConsoleClientTest.php | 12 +- .../Databases/DatabasesCustomClientTest.php | 4 +- .../Databases/DatabasesCustomServerTest.php | 172 ++++----- .../DatabasesPermissionsGuestTest.php | 4 +- .../DatabasesPermissionsMemberTest.php | 4 +- .../DatabasesPermissionsTeamTest.php | 2 +- 7 files changed, 262 insertions(+), 262 deletions(-) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 989d1217d3..14713a52ee 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -339,7 +339,7 @@ trait DatabasesBase $this->assertEquals($relationship['headers']['status-code'], 202); $this->assertEquals($relationship['body']['key'], 'starringActors'); $this->assertEquals($relationship['body']['type'], 'relationship'); - $this->assertEquals($relationship['body']['relatedCollection'], $data['actorsId']); + $this->assertEquals($relationship['body']['relatedTable'], $data['actorsId']); $this->assertEquals($relationship['body']['relationType'], 'oneToMany'); $this->assertEquals($relationship['body']['twoWay'], true); $this->assertEquals($relationship['body']['twoWayKey'], 'movie'); @@ -360,17 +360,17 @@ trait DatabasesBase 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertIsArray($movies['body']['attributes']); - $this->assertCount(9, $movies['body']['attributes']); - $this->assertEquals($movies['body']['attributes'][0]['key'], $title['body']['key']); - $this->assertEquals($movies['body']['attributes'][1]['key'], $description['body']['key']); - $this->assertEquals($movies['body']['attributes'][2]['key'], $tagline['body']['key']); - $this->assertEquals($movies['body']['attributes'][3]['key'], $releaseYear['body']['key']); - $this->assertEquals($movies['body']['attributes'][4]['key'], $duration['body']['key']); - $this->assertEquals($movies['body']['attributes'][5]['key'], $actors['body']['key']); - $this->assertEquals($movies['body']['attributes'][6]['key'], $datetime['body']['key']); - $this->assertEquals($movies['body']['attributes'][7]['key'], $relationship['body']['key']); - $this->assertEquals($movies['body']['attributes'][8]['key'], $integers['body']['key']); + $this->assertIsArray($movies['body']['columns']); + $this->assertCount(9, $movies['body']['columns']); + $this->assertEquals($movies['body']['columns'][0]['key'], $title['body']['key']); + $this->assertEquals($movies['body']['columns'][1]['key'], $description['body']['key']); + $this->assertEquals($movies['body']['columns'][2]['key'], $tagline['body']['key']); + $this->assertEquals($movies['body']['columns'][3]['key'], $releaseYear['body']['key']); + $this->assertEquals($movies['body']['columns'][4]['key'], $duration['body']['key']); + $this->assertEquals($movies['body']['columns'][5]['key'], $actors['body']['key']); + $this->assertEquals($movies['body']['columns'][6]['key'], $datetime['body']['key']); + $this->assertEquals($movies['body']['columns'][7]['key'], $relationship['body']['key']); + $this->assertEquals($movies['body']['columns'][8]['key'], $integers['body']['key']); return $data; } @@ -393,7 +393,7 @@ trait DatabasesBase ], ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(2, \count($response['body']['attributes'])); + $this->assertEquals(2, \count($response['body']['columns'])); $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -449,7 +449,7 @@ trait DatabasesBase ]), [ 'key' => 'titleIndex', 'type' => 'key', - 'attributes' => ['title'], + 'columns' => ['title'], ]); $this->assertEquals(202, $index['headers']['status-code']); @@ -763,7 +763,7 @@ trait DatabasesBase $this->assertEquals('relationship', $relationship['body']['type']); $this->assertEquals(false, $relationship['body']['required']); $this->assertEquals(false, $relationship['body']['array']); - $this->assertEquals($data['actorsId'], $relationship['body']['relatedCollection']); + $this->assertEquals($data['actorsId'], $relationship['body']['relatedTable']); $this->assertEquals('oneToMany', $relationship['body']['relationType']); $this->assertEquals(true, $relationship['body']['twoWay']); $this->assertEquals('twoWayKey', $relationship['body']['twoWayKey']); @@ -947,7 +947,7 @@ trait DatabasesBase $this->assertEquals('available', $relationshipResponse['body']['status']); $this->assertEquals($relationship['body']['required'], $relationshipResponse['body']['required']); $this->assertEquals($relationship['body']['array'], $relationshipResponse['body']['array']); - $this->assertEquals($relationship['body']['relatedCollection'], $relationshipResponse['body']['relatedCollection']); + $this->assertEquals($relationship['body']['relatedTable'], $relationshipResponse['body']['relatedTable']); $this->assertEquals($relationship['body']['relationType'], $relationshipResponse['body']['relationType']); $this->assertEquals($relationship['body']['twoWay'], $relationshipResponse['body']['twoWay']); $this->assertEquals($relationship['body']['twoWayKey'], $relationshipResponse['body']['twoWayKey']); @@ -961,7 +961,7 @@ trait DatabasesBase $this->assertEquals(200, $attributes['headers']['status-code']); $this->assertEquals(12, $attributes['body']['total']); - $attributes = $attributes['body']['attributes']; + $attributes = $attributes['body']['columns']; $this->assertIsArray($attributes); $this->assertCount(12, $attributes); @@ -1043,7 +1043,7 @@ trait DatabasesBase $this->assertEquals($relationshipResponse['body']['status'], $attributes[9]['status']); $this->assertEquals($relationshipResponse['body']['required'], $attributes[9]['required']); $this->assertEquals($relationshipResponse['body']['array'], $attributes[9]['array']); - $this->assertEquals($relationshipResponse['body']['relatedCollection'], $attributes[9]['relatedCollection']); + $this->assertEquals($relationshipResponse['body']['relatedTable'], $attributes[9]['relatedTable']); $this->assertEquals($relationshipResponse['body']['relationType'], $attributes[9]['relationType']); $this->assertEquals($relationshipResponse['body']['twoWay'], $attributes[9]['twoWay']); $this->assertEquals($relationshipResponse['body']['twoWayKey'], $attributes[9]['twoWayKey']); @@ -1072,7 +1072,7 @@ trait DatabasesBase $this->assertEquals(200, $collection['headers']['status-code']); - $attributes = $collection['body']['attributes']; + $attributes = $collection['body']['columns']; $this->assertIsArray($attributes); $this->assertCount(12, $attributes); @@ -1155,7 +1155,7 @@ trait DatabasesBase $this->assertEquals($relationshipResponse['body']['status'], $attributes[9]['status']); $this->assertEquals($relationshipResponse['body']['required'], $attributes[9]['required']); $this->assertEquals($relationshipResponse['body']['array'], $attributes[9]['array']); - $this->assertEquals($relationshipResponse['body']['relatedCollection'], $attributes[9]['relatedCollection']); + $this->assertEquals($relationshipResponse['body']['relatedTable'], $attributes[9]['relatedTable']); $this->assertEquals($relationshipResponse['body']['relationType'], $attributes[9]['relationType']); $this->assertEquals($relationshipResponse['body']['twoWay'], $attributes[9]['twoWay']); $this->assertEquals($relationshipResponse['body']['twoWayKey'], $attributes[9]['twoWayKey']); @@ -1210,14 +1210,14 @@ trait DatabasesBase ]), [ 'key' => 'titleIndex', 'type' => 'fulltext', - 'attributes' => ['title'], + 'columns' => ['title'], ]); $this->assertEquals(202, $titleIndex['headers']['status-code']); $this->assertEquals('titleIndex', $titleIndex['body']['key']); $this->assertEquals('fulltext', $titleIndex['body']['type']); - $this->assertCount(1, $titleIndex['body']['attributes']); - $this->assertEquals('title', $titleIndex['body']['attributes'][0]); + $this->assertCount(1, $titleIndex['body']['columns']); + $this->assertEquals('title', $titleIndex['body']['columns'][0]); $releaseYearIndex = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', @@ -1226,14 +1226,14 @@ trait DatabasesBase ]), [ 'key' => 'releaseYear', 'type' => 'key', - 'attributes' => ['releaseYear'], + 'columns' => ['releaseYear'], ]); $this->assertEquals(202, $releaseYearIndex['headers']['status-code']); $this->assertEquals('releaseYear', $releaseYearIndex['body']['key']); $this->assertEquals('key', $releaseYearIndex['body']['type']); - $this->assertCount(1, $releaseYearIndex['body']['attributes']); - $this->assertEquals('releaseYear', $releaseYearIndex['body']['attributes'][0]); + $this->assertCount(1, $releaseYearIndex['body']['columns']); + $this->assertEquals('releaseYear', $releaseYearIndex['body']['columns'][0]); $releaseWithDate1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', @@ -1242,16 +1242,16 @@ trait DatabasesBase ]), [ 'key' => 'releaseYearDated', 'type' => 'key', - 'attributes' => ['releaseYear', '$createdAt', '$updatedAt'], + 'columns' => ['releaseYear', '$createdAt', '$updatedAt'], ]); $this->assertEquals(202, $releaseWithDate1['headers']['status-code']); $this->assertEquals('releaseYearDated', $releaseWithDate1['body']['key']); $this->assertEquals('key', $releaseWithDate1['body']['type']); - $this->assertCount(3, $releaseWithDate1['body']['attributes']); - $this->assertEquals('releaseYear', $releaseWithDate1['body']['attributes'][0]); - $this->assertEquals('$createdAt', $releaseWithDate1['body']['attributes'][1]); - $this->assertEquals('$updatedAt', $releaseWithDate1['body']['attributes'][2]); + $this->assertCount(3, $releaseWithDate1['body']['columns']); + $this->assertEquals('releaseYear', $releaseWithDate1['body']['columns'][0]); + $this->assertEquals('$createdAt', $releaseWithDate1['body']['columns'][1]); + $this->assertEquals('$updatedAt', $releaseWithDate1['body']['columns'][2]); $releaseWithDate2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', @@ -1260,14 +1260,14 @@ trait DatabasesBase ]), [ 'key' => 'birthDay', 'type' => 'key', - 'attributes' => ['birthDay'], + 'columns' => ['birthDay'], ]); $this->assertEquals(202, $releaseWithDate2['headers']['status-code']); $this->assertEquals('birthDay', $releaseWithDate2['body']['key']); $this->assertEquals('key', $releaseWithDate2['body']['type']); - $this->assertCount(1, $releaseWithDate2['body']['attributes']); - $this->assertEquals('birthDay', $releaseWithDate2['body']['attributes'][0]); + $this->assertCount(1, $releaseWithDate2['body']['columns']); + $this->assertEquals('birthDay', $releaseWithDate2['body']['columns'][0]); // Test for failure $fulltextReleaseYear = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ @@ -1277,7 +1277,7 @@ trait DatabasesBase ]), [ 'key' => 'releaseYearDated', 'type' => 'fulltext', - 'attributes' => ['releaseYear'], + 'columns' => ['releaseYear'], ]); $this->assertEquals(400, $fulltextReleaseYear['headers']['status-code']); @@ -1290,7 +1290,7 @@ trait DatabasesBase ]), [ 'key' => 'none', 'type' => 'key', - 'attributes' => [], + 'columns' => [], ]); $this->assertEquals(400, $noAttributes['headers']['status-code']); @@ -1303,7 +1303,7 @@ trait DatabasesBase ]), [ 'key' => 'duplicate', 'type' => 'fulltext', - 'attributes' => ['releaseYear', 'releaseYear'], + 'columns' => ['releaseYear', 'releaseYear'], ]); $this->assertEquals(400, $duplicates['headers']['status-code']); @@ -1316,7 +1316,7 @@ trait DatabasesBase ]), [ 'key' => 'tooLong', 'type' => 'key', - 'attributes' => ['description', 'tagline'], + 'columns' => ['description', 'tagline'], ]); $this->assertEquals(400, $tooLong['headers']['status-code']); @@ -1329,7 +1329,7 @@ trait DatabasesBase ]), [ 'key' => 'ft', 'type' => 'fulltext', - 'attributes' => ['actors'], + 'columns' => ['actors'], ]); $this->assertEquals(400, $fulltextArray['headers']['status-code']); @@ -1342,7 +1342,7 @@ trait DatabasesBase ]), [ 'key' => 'index-actors', 'type' => 'key', - 'attributes' => ['actors'], + 'columns' => ['actors'], ]); $this->assertEquals(202, $actorsArray['headers']['status-code']); @@ -1354,7 +1354,7 @@ trait DatabasesBase ]), [ 'key' => 'index-ip-actors', 'type' => 'key', - 'attributes' => ['releaseYear', 'actors'], // 2 levels + 'columns' => ['releaseYear', 'actors'], // 2 levels 'orders' => ['DESC', 'DESC'], ]); @@ -1369,7 +1369,7 @@ trait DatabasesBase ]), [ 'key' => 'index-unknown', 'type' => 'key', - 'attributes' => ['Unknown'], + 'columns' => ['Unknown'], ]); $this->assertEquals(400, $unknown['headers']['status-code']); @@ -1382,7 +1382,7 @@ trait DatabasesBase ]), [ 'key' => 'integers-order', 'type' => 'key', - 'attributes' => ['integers'], // array attribute + 'columns' => ['integers'], // array attribute 'orders' => ['DESC'], // Check order is removed in API ]); $this->assertEquals(202, $index1['headers']['status-code']); @@ -1394,7 +1394,7 @@ trait DatabasesBase ]), [ 'key' => 'integers-size', 'type' => 'key', - 'attributes' => ['integers'], // array attribute + 'columns' => ['integers'], // array attribute ]); $this->assertEquals(202, $index2['headers']['status-code']); @@ -1612,15 +1612,15 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); - $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); - $this->assertEquals(2019, $documents['body']['documents'][2]['releaseYear']); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][0])); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][1])); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][2])); - $this->assertCount(3, $documents['body']['documents']); + $this->assertEquals(1944, $documents['body']['rows'][0]['releaseYear']); + $this->assertEquals(2017, $documents['body']['rows'][1]['releaseYear']); + $this->assertEquals(2019, $documents['body']['rows'][2]['releaseYear']); + $this->assertFalse(array_key_exists('$internalId', $documents['body']['rows'][0])); + $this->assertFalse(array_key_exists('$internalId', $documents['body']['rows'][1])); + $this->assertFalse(array_key_exists('$internalId', $documents['body']['rows'][2])); + $this->assertCount(3, $documents['body']['rows']); - foreach ($documents['body']['documents'] as $document) { + foreach ($documents['body']['rows'] as $document) { $this->assertEquals($data['moviesId'], $document['$collectionId']); $this->assertArrayNotHasKey('$collection', $document); $this->assertEquals($databaseId, $document['$databaseId']); @@ -1636,10 +1636,10 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(1944, $documents['body']['documents'][2]['releaseYear']); - $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); - $this->assertEquals(2019, $documents['body']['documents'][0]['releaseYear']); - $this->assertCount(3, $documents['body']['documents']); + $this->assertEquals(1944, $documents['body']['rows'][2]['releaseYear']); + $this->assertEquals(2017, $documents['body']['rows'][1]['releaseYear']); + $this->assertEquals(2019, $documents['body']['rows'][0]['releaseYear']); + $this->assertCount(3, $documents['body']['rows']); // changing description attribute to be null by default instead of empty string $patchNull = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string/description', array_merge([ @@ -1685,7 +1685,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - return ['documents' => $documents['body']['documents'], 'databaseId' => $databaseId]; + return ['rows' => $documents['body']['rows'], 'databaseId' => $databaseId]; } @@ -1695,7 +1695,7 @@ trait DatabasesBase public function testGetDocument(array $data): void { $databaseId = $data['databaseId']; - foreach ($data['documents'] as $document) { + foreach ($data['rows'] as $document) { $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1721,7 +1721,7 @@ trait DatabasesBase public function testGetDocumentWithQueries(array $data): void { $databaseId = $data['databaseId']; - $document = $data['documents'][0]; + $document = $data['rows'][0]; $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', @@ -1753,36 +1753,36 @@ trait DatabasesBase ], $this->getHeaders())); $this->assertEquals(200, $base['headers']['status-code']); - $this->assertEquals('Captain America', $base['body']['documents'][0]['title']); - $this->assertEquals('Spider-Man: Far From Home', $base['body']['documents'][1]['title']); - $this->assertEquals('Spider-Man: Homecoming', $base['body']['documents'][2]['title']); - $this->assertCount(3, $base['body']['documents']); + $this->assertEquals('Captain America', $base['body']['rows'][0]['title']); + $this->assertEquals('Spider-Man: Far From Home', $base['body']['rows'][1]['title']); + $this->assertEquals('Spider-Man: Homecoming', $base['body']['rows'][2]['title']); + $this->assertCount(3, $base['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorAfter(new Document(['$id' => $base['body']['documents'][0]['$id']]))->toString() + Query::cursorAfter(new Document(['$id' => $base['body']['rows'][0]['$id']]))->toString() ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals($base['body']['documents'][1]['$id'], $documents['body']['documents'][0]['$id']); - $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][1]['$id']); - $this->assertCount(2, $documents['body']['documents']); + $this->assertEquals($base['body']['rows'][1]['$id'], $documents['body']['rows'][0]['$id']); + $this->assertEquals($base['body']['rows'][2]['$id'], $documents['body']['rows'][1]['$id']); + $this->assertCount(2, $documents['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorAfter(new Document(['$id' => $base['body']['documents'][2]['$id']]))->toString() + Query::cursorAfter(new Document(['$id' => $base['body']['rows'][2]['$id']]))->toString() ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEmpty($documents['body']['documents']); + $this->assertEmpty($documents['body']['rows']); /** * Test with ASC order and after. @@ -1797,24 +1797,24 @@ trait DatabasesBase ]); $this->assertEquals(200, $base['headers']['status-code']); - $this->assertEquals(1944, $base['body']['documents'][0]['releaseYear']); - $this->assertEquals(2017, $base['body']['documents'][1]['releaseYear']); - $this->assertEquals(2019, $base['body']['documents'][2]['releaseYear']); - $this->assertCount(3, $base['body']['documents']); + $this->assertEquals(1944, $base['body']['rows'][0]['releaseYear']); + $this->assertEquals(2017, $base['body']['rows'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['rows'][2]['releaseYear']); + $this->assertCount(3, $base['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorAfter(new Document(['$id' => $base['body']['documents'][1]['$id']]))->toString(), + Query::cursorAfter(new Document(['$id' => $base['body']['rows'][1]['$id']]))->toString(), Query::orderAsc('releaseYear')->toString() ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][0]['$id']); - $this->assertCount(1, $documents['body']['documents']); + $this->assertEquals($base['body']['rows'][2]['$id'], $documents['body']['rows'][0]['$id']); + $this->assertCount(1, $documents['body']['rows']); /** * Test with DESC order and after. @@ -1829,24 +1829,24 @@ trait DatabasesBase ]); $this->assertEquals(200, $base['headers']['status-code']); - $this->assertEquals(1944, $base['body']['documents'][2]['releaseYear']); - $this->assertEquals(2017, $base['body']['documents'][1]['releaseYear']); - $this->assertEquals(2019, $base['body']['documents'][0]['releaseYear']); - $this->assertCount(3, $base['body']['documents']); + $this->assertEquals(1944, $base['body']['rows'][2]['releaseYear']); + $this->assertEquals(2017, $base['body']['rows'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['rows'][0]['releaseYear']); + $this->assertCount(3, $base['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorAfter(new Document(['$id' => $base['body']['documents'][1]['$id']]))->toString(), + Query::cursorAfter(new Document(['$id' => $base['body']['rows'][1]['$id']]))->toString(), Query::orderDesc('releaseYear')->toString() ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][0]['$id']); - $this->assertCount(1, $documents['body']['documents']); + $this->assertEquals($base['body']['rows'][2]['$id'], $documents['body']['rows'][0]['$id']); + $this->assertCount(1, $documents['body']['rows']); /** * Test after with unknown document. @@ -1895,36 +1895,36 @@ trait DatabasesBase ], $this->getHeaders())); $this->assertEquals(200, $base['headers']['status-code']); - $this->assertEquals('Captain America', $base['body']['documents'][0]['title']); - $this->assertEquals('Spider-Man: Far From Home', $base['body']['documents'][1]['title']); - $this->assertEquals('Spider-Man: Homecoming', $base['body']['documents'][2]['title']); - $this->assertCount(3, $base['body']['documents']); + $this->assertEquals('Captain America', $base['body']['rows'][0]['title']); + $this->assertEquals('Spider-Man: Far From Home', $base['body']['rows'][1]['title']); + $this->assertEquals('Spider-Man: Homecoming', $base['body']['rows'][2]['title']); + $this->assertCount(3, $base['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorBefore(new Document(['$id' => $base['body']['documents'][2]['$id']]))->toString(), + Query::cursorBefore(new Document(['$id' => $base['body']['rows'][2]['$id']]))->toString(), ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals($base['body']['documents'][0]['$id'], $documents['body']['documents'][0]['$id']); - $this->assertEquals($base['body']['documents'][1]['$id'], $documents['body']['documents'][1]['$id']); - $this->assertCount(2, $documents['body']['documents']); + $this->assertEquals($base['body']['rows'][0]['$id'], $documents['body']['rows'][0]['$id']); + $this->assertEquals($base['body']['rows'][1]['$id'], $documents['body']['rows'][1]['$id']); + $this->assertCount(2, $documents['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorBefore(new Document(['$id' => $base['body']['documents'][0]['$id']]))->toString(), + Query::cursorBefore(new Document(['$id' => $base['body']['rows'][0]['$id']]))->toString(), ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEmpty($documents['body']['documents']); + $this->assertEmpty($documents['body']['rows']); /** * Test with ASC order and after. @@ -1939,24 +1939,24 @@ trait DatabasesBase ]); $this->assertEquals(200, $base['headers']['status-code']); - $this->assertEquals(1944, $base['body']['documents'][0]['releaseYear']); - $this->assertEquals(2017, $base['body']['documents'][1]['releaseYear']); - $this->assertEquals(2019, $base['body']['documents'][2]['releaseYear']); - $this->assertCount(3, $base['body']['documents']); + $this->assertEquals(1944, $base['body']['rows'][0]['releaseYear']); + $this->assertEquals(2017, $base['body']['rows'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['rows'][2]['releaseYear']); + $this->assertCount(3, $base['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorBefore(new Document(['$id' => $base['body']['documents'][1]['$id']]))->toString(), + Query::cursorBefore(new Document(['$id' => $base['body']['rows'][1]['$id']]))->toString(), Query::orderAsc('releaseYear')->toString(), ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals($base['body']['documents'][0]['$id'], $documents['body']['documents'][0]['$id']); - $this->assertCount(1, $documents['body']['documents']); + $this->assertEquals($base['body']['rows'][0]['$id'], $documents['body']['rows'][0]['$id']); + $this->assertCount(1, $documents['body']['rows']); /** * Test with DESC order and after. @@ -1971,24 +1971,24 @@ trait DatabasesBase ]); $this->assertEquals(200, $base['headers']['status-code']); - $this->assertEquals(1944, $base['body']['documents'][2]['releaseYear']); - $this->assertEquals(2017, $base['body']['documents'][1]['releaseYear']); - $this->assertEquals(2019, $base['body']['documents'][0]['releaseYear']); - $this->assertCount(3, $base['body']['documents']); + $this->assertEquals(1944, $base['body']['rows'][2]['releaseYear']); + $this->assertEquals(2017, $base['body']['rows'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['rows'][0]['releaseYear']); + $this->assertCount(3, $base['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorBefore(new Document(['$id' => $base['body']['documents'][1]['$id']]))->toString(), + Query::cursorBefore(new Document(['$id' => $base['body']['rows'][1]['$id']]))->toString(), Query::orderDesc('releaseYear')->toString(), ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals($base['body']['documents'][0]['$id'], $documents['body']['documents'][0]['$id']); - $this->assertCount(1, $documents['body']['documents']); + $this->assertEquals($base['body']['rows'][0]['$id'], $documents['body']['rows'][0]['$id']); + $this->assertCount(1, $documents['body']['rows']); return []; } @@ -2010,8 +2010,8 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); - $this->assertCount(1, $documents['body']['documents']); + $this->assertEquals(1944, $documents['body']['rows'][0]['releaseYear']); + $this->assertCount(1, $documents['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2025,9 +2025,9 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(2017, $documents['body']['documents'][0]['releaseYear']); - $this->assertEquals(2019, $documents['body']['documents'][1]['releaseYear']); - $this->assertCount(2, $documents['body']['documents']); + $this->assertEquals(2017, $documents['body']['rows'][0]['releaseYear']); + $this->assertEquals(2019, $documents['body']['rows'][1]['releaseYear']); + $this->assertCount(2, $documents['body']['rows']); return []; } @@ -2048,21 +2048,21 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); - $this->assertCount(1, $documents['body']['documents']); + $this->assertEquals(1944, $documents['body']['rows'][0]['releaseYear']); + $this->assertCount(1, $documents['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::equal('$id', [$documents['body']['documents'][0]['$id']])->toString(), + Query::equal('$id', [$documents['body']['rows'][0]['$id']])->toString(), ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); - $this->assertCount(1, $documents['body']['documents']); + $this->assertEquals(1944, $documents['body']['rows'][0]['releaseYear']); + $this->assertCount(1, $documents['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2074,8 +2074,8 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(2017, $documents['body']['documents'][0]['releaseYear']); - $this->assertCount(1, $documents['body']['documents']); + $this->assertEquals(2017, $documents['body']['rows'][0]['releaseYear']); + $this->assertCount(1, $documents['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2087,9 +2087,9 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(2019, $documents['body']['documents'][0]['releaseYear']); - $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); - $this->assertCount(2, $documents['body']['documents']); + $this->assertEquals(2019, $documents['body']['rows'][0]['releaseYear']); + $this->assertEquals(2017, $documents['body']['rows'][1]['releaseYear']); + $this->assertCount(2, $documents['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2124,8 +2124,8 @@ trait DatabasesBase ], ]); - $this->assertCount(1, $documents['body']['documents']); - $this->assertEquals('Captain America', $documents['body']['documents'][0]['title']); + $this->assertCount(1, $documents['body']['rows']); + $this->assertEquals('Captain America', $documents['body']['rows'][0]['title']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2136,9 +2136,9 @@ trait DatabasesBase ], ]); - $this->assertCount(2, $documents['body']['documents']); - $this->assertEquals('Spider-Man: Far From Home', $documents['body']['documents'][0]['title']); - $this->assertEquals('Spider-Man: Homecoming', $documents['body']['documents'][1]['title']); + $this->assertCount(2, $documents['body']['rows']); + $this->assertEquals('Spider-Man: Far From Home', $documents['body']['rows'][0]['title']); + $this->assertEquals('Spider-Man: Homecoming', $documents['body']['rows'][1]['title']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2149,7 +2149,7 @@ trait DatabasesBase ], ]); - $this->assertCount(3, $documents['body']['documents']); + $this->assertCount(3, $documents['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2160,7 +2160,7 @@ trait DatabasesBase ], ]); - $this->assertCount(0, $documents['body']['documents']); + $this->assertCount(0, $documents['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2208,9 +2208,9 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals('1975-06-12T12:12:55.000+00:00', $documents['body']['documents'][0]['birthDay']); - $this->assertEquals('1975-06-12T18:12:55.000+00:00', $documents['body']['documents'][1]['birthDay']); - $this->assertCount(2, $documents['body']['documents']); + $this->assertEquals('1975-06-12T12:12:55.000+00:00', $documents['body']['rows'][0]['birthDay']); + $this->assertEquals('1975-06-12T18:12:55.000+00:00', $documents['body']['rows'][1]['birthDay']); + $this->assertCount(2, $documents['body']['rows']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2682,7 +2682,7 @@ trait DatabasesBase 'x-appwrite-key' => $this->getProject()['apiKey'], ]), []); - $this->assertCount(10, $collection['body']['attributes']); + $this->assertCount(10, $collection['body']['columns']); /** * Test for successful validation @@ -3187,7 +3187,7 @@ trait DatabasesBase ]), [ 'key' => 'key_attribute', 'type' => 'key', - 'attributes' => [$attribute['body']['key']], + 'columns' => [$attribute['body']['key']], ]); $this->assertEquals(202, $index['headers']['status-code']); @@ -3253,7 +3253,7 @@ trait DatabasesBase // Current user has read permission on the collection so can get any document $this->assertEquals(3, $documentsUser1['body']['total']); - $this->assertCount(3, $documentsUser1['body']['documents']); + $this->assertCount(3, $documentsUser1['body']['rows']); $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], array_merge([ 'content-type' => 'application/json', @@ -3315,7 +3315,7 @@ trait DatabasesBase // Current user has no collection permissions but has read permission for one document $this->assertEquals(1, $documentsUser2['body']['total']); - $this->assertCount(1, $documentsUser2['body']['documents']); + $this->assertCount(1, $documentsUser2['body']['rows']); } public function testEnforceCollectionPermissions() @@ -3376,7 +3376,7 @@ trait DatabasesBase ]), [ 'key' => 'key_attribute', 'type' => 'key', - 'attributes' => [$attribute['body']['key']], + 'columns' => [$attribute['body']['key']], ]); $this->assertEquals(202, $index['headers']['status-code']); @@ -3441,7 +3441,7 @@ trait DatabasesBase // Current user has read permission on the collection so can get any document $this->assertEquals(3, $documentsUser1['body']['total']); - $this->assertCount(3, $documentsUser1['body']['documents']); + $this->assertCount(3, $documentsUser1['body']['rows']); $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], array_merge([ 'content-type' => 'application/json', @@ -3513,7 +3513,7 @@ trait DatabasesBase // Current user has no collection permissions read access to one document $this->assertEquals(1, $documentsUser2['body']['total']); - $this->assertCount(1, $documentsUser2['body']['documents']); + $this->assertCount(1, $documentsUser2['body']['rows']); } /** @@ -3529,7 +3529,7 @@ trait DatabasesBase ]), [ 'key' => 'unique_title', 'type' => 'unique', - 'attributes' => ['title'], + 'columns' => ['title'], ]); $this->assertEquals(202, $uniqueIndex['headers']['status-code']); @@ -3929,8 +3929,8 @@ trait DatabasesBase $this->assertEquals(200, $attributes['headers']['status-code']); $this->assertEquals(2, $attributes['body']['total']); - $attributes = $attributes['body']['attributes']; - $this->assertEquals('library', $attributes[1]['relatedCollection']); + $attributes = $attributes['body']['columns']; + $this->assertEquals('library', $attributes[1]['relatedTable']); $this->assertEquals('oneToOne', $attributes[1]['relationType']); $this->assertEquals(true, $attributes[1]['twoWay']); $this->assertEquals('person', $attributes[1]['twoWayKey']); @@ -4019,8 +4019,8 @@ trait DatabasesBase ]); $this->assertEquals(1, $documents['body']['total']); - $this->assertEquals('Library 1', $documents['body']['documents'][0]['library']['libraryName']); - $this->assertArrayHasKey('fullName', $documents['body']['documents'][0]); + $this->assertEquals('Library 1', $documents['body']['rows'][0]['library']['libraryName']); + $this->assertArrayHasKey('fullName', $documents['body']['rows'][0]); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -4068,7 +4068,7 @@ trait DatabasesBase $this->assertEquals(200, $attributes['headers']['status-code']); $this->assertEquals(1, $attributes['body']['total']); - $this->assertEquals('libraryName', $attributes['body']['attributes'][0]['key']); + $this->assertEquals('libraryName', $attributes['body']['columns'][0]['key']); return [ 'databaseId' => $databaseId, @@ -4107,9 +4107,9 @@ trait DatabasesBase 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertIsArray($libraryAttributesResponse['body']['attributes']); + $this->assertIsArray($libraryAttributesResponse['body']['columns']); $this->assertEquals(2, $libraryAttributesResponse['body']['total']); - $this->assertEquals('person_one_to_many', $libraryAttributesResponse['body']['attributes'][1]['key']); + $this->assertEquals('person_one_to_many', $libraryAttributesResponse['body']['columns'][1]['key']); $libraryCollectionResponse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $libraryCollection, array_merge([ 'content-type' => 'application/json', @@ -4117,8 +4117,8 @@ trait DatabasesBase 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertIsArray($libraryCollectionResponse['body']['attributes']); - $this->assertCount(2, $libraryCollectionResponse['body']['attributes']); + $this->assertIsArray($libraryCollectionResponse['body']['columns']); + $this->assertCount(2, $libraryCollectionResponse['body']['columns']); $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$personCollection}/attributes/libraries", array_merge([ 'content-type' => 'application/json', @@ -4541,10 +4541,10 @@ trait DatabasesBase ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(1, count($response['body']['documents'])); - $this->assertEquals('person10', $response['body']['documents'][0]['$id']); - $this->assertEquals('Stevie Wonder', $response['body']['documents'][0]['fullName']); - $this->assertEquals(2, count($response['body']['documents'][0]['libraries'])); + $this->assertEquals(1, count($response['body']['rows'])); + $this->assertEquals('person10', $response['body']['rows'][0]['$id']); + $this->assertEquals('Stevie Wonder', $response['body']['rows'][0]['fullName']); + $this->assertEquals(2, count($response['body']['rows'][0]['libraries'])); $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -4558,11 +4558,11 @@ trait DatabasesBase ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(2, count($response['body']['documents'])); - $this->assertEquals(null, $response['body']['documents'][0]['fullName']); - $this->assertArrayNotHasKey("libraries", $response['body']['documents'][0]); - $this->assertArrayNotHasKey('$databaseId', $response['body']['documents'][0]); - $this->assertArrayNotHasKey('$collectionId', $response['body']['documents'][0]); + $this->assertEquals(2, count($response['body']['rows'])); + $this->assertEquals(null, $response['body']['rows'][0]['fullName']); + $this->assertArrayNotHasKey("libraries", $response['body']['rows'][0]); + $this->assertArrayNotHasKey('$databaseId', $response['body']['rows'][0]); + $this->assertArrayNotHasKey('$collectionId', $response['body']['rows'][0]); } /** @@ -4581,9 +4581,9 @@ trait DatabasesBase ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertArrayNotHasKey('libraries', $response['body']['documents'][0]); - $this->assertArrayNotHasKey('$databaseId', $response['body']['documents'][0]); - $this->assertArrayNotHasKey('$collectionId', $response['body']['documents'][0]); + $this->assertArrayNotHasKey('libraries', $response['body']['rows'][0]); + $this->assertArrayNotHasKey('$databaseId', $response['body']['rows'][0]); + $this->assertArrayNotHasKey('$collectionId', $response['body']['rows'][0]); $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -4593,7 +4593,7 @@ trait DatabasesBase Query::select(['libraries.*', '$id'])->toString(), ], ]); - $document = $response['body']['documents'][0]; + $document = $response['body']['rows'][0]; $this->assertEquals(200, $response['headers']['status-code']); $this->assertArrayHasKey('libraries', $document); $this->assertArrayNotHasKey('$databaseId', $document); @@ -4746,7 +4746,7 @@ trait DatabasesBase ); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertCount(2, $documents['body']['documents']); + $this->assertCount(2, $documents['body']['rows']); } /** diff --git a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php b/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php index 2266c91afe..04daddd47a 100644 --- a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php @@ -226,10 +226,10 @@ class DatabasesConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(11, count($response['body'])); $this->assertEquals('24h', $response['body']['range']); - $this->assertIsNumeric($response['body']['documentsTotal']); - $this->assertIsNumeric($response['body']['collectionsTotal']); - $this->assertIsArray($response['body']['collections']); - $this->assertIsArray($response['body']['documents']); + $this->assertIsNumeric($response['body']['rowsTotal']); + $this->assertIsNumeric($response['body']['tablesTotal']); + $this->assertIsArray($response['body']['tables']); + $this->assertIsArray($response['body']['rows']); } @@ -273,8 +273,8 @@ class DatabasesConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(3, count($response['body'])); $this->assertEquals('24h', $response['body']['range']); - $this->assertIsNumeric($response['body']['documentsTotal']); - $this->assertIsArray($response['body']['documents']); + $this->assertIsNumeric($response['body']['rowsTotal']); + $this->assertIsArray($response['body']['rows']); } /** diff --git a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php index d4a8c87868..6caeb3ca8b 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php @@ -309,11 +309,11 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $collection1RelationAttribute = $collection1Attributes['body']['attributes'][0]; + $collection1RelationAttribute = $collection1Attributes['body']['columns'][0]; $this->assertEquals($relation['body']['side'], $collection1RelationAttribute['side']); $this->assertEquals($relation['body']['twoWayKey'], $collection1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedCollection'], $collection1RelationAttribute['relatedCollection']); + $this->assertEquals($relation['body']['relatedTable'], $collection1RelationAttribute['relatedTable']); $this->assertEquals('restrict', $collection1RelationAttribute['onDelete']); } diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 57e0b93634..7e5da78ccd 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -390,12 +390,12 @@ class DatabasesCustomServerTest extends Scope ], $this->getHeaders())); $this->assertEquals(2, $collections['body']['total']); - $this->assertEquals($test1['body']['$id'], $collections['body']['collections'][0]['$id']); - $this->assertEquals($test1['body']['enabled'], $collections['body']['collections'][0]['enabled']); - $this->assertEquals($test2['body']['$id'], $collections['body']['collections'][1]['$id']); - $this->assertEquals($test1['body']['enabled'], $collections['body']['collections'][0]['enabled']); + $this->assertEquals($test1['body']['$id'], $collections['body']['tables'][0]['$id']); + $this->assertEquals($test1['body']['enabled'], $collections['body']['tables'][0]['enabled']); + $this->assertEquals($test2['body']['$id'], $collections['body']['tables'][1]['$id']); + $this->assertEquals($test1['body']['enabled'], $collections['body']['tables'][0]['enabled']); - $base = array_reverse($collections['body']['collections']); + $base = array_reverse($collections['body']['tables']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', @@ -407,7 +407,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collections['headers']['status-code']); - $this->assertCount(1, $collections['body']['collections']); + $this->assertCount(1, $collections['body']['tables']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', @@ -419,7 +419,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collections['headers']['status-code']); - $this->assertCount(1, $collections['body']['collections']); + $this->assertCount(1, $collections['body']['tables']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', @@ -431,7 +431,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collections['headers']['status-code']); - $this->assertCount(2, $collections['body']['collections']); + $this->assertCount(2, $collections['body']['tables']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', @@ -443,7 +443,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collections['headers']['status-code']); - $this->assertCount(0, $collections['body']['collections']); + $this->assertCount(0, $collections['body']['tables']); /** * Test for Order @@ -458,8 +458,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(2, $collections['body']['total']); - $this->assertEquals($base[0]['$id'], $collections['body']['collections'][0]['$id']); - $this->assertEquals($base[1]['$id'], $collections['body']['collections'][1]['$id']); + $this->assertEquals($base[0]['$id'], $collections['body']['tables'][0]['$id']); + $this->assertEquals($base[1]['$id'], $collections['body']['tables'][1]['$id']); /** * Test for After @@ -474,24 +474,24 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorAfter(new Document(['$id' => $base['body']['collections'][0]['$id']]))->toString(), + Query::cursorAfter(new Document(['$id' => $base['body']['tables'][0]['$id']]))->toString(), ], ]); - $this->assertCount(1, $collections['body']['collections']); - $this->assertEquals($base['body']['collections'][1]['$id'], $collections['body']['collections'][0]['$id']); + $this->assertCount(1, $collections['body']['tables']); + $this->assertEquals($base['body']['tables'][1]['$id'], $collections['body']['tables'][0]['$id']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorAfter(new Document(['$id' => $base['body']['collections'][1]['$id']]))->toString(), + Query::cursorAfter(new Document(['$id' => $base['body']['tables'][1]['$id']]))->toString(), ], ]); - $this->assertCount(0, $collections['body']['collections']); - $this->assertEmpty($collections['body']['collections']); + $this->assertCount(0, $collections['body']['tables']); + $this->assertEmpty($collections['body']['tables']); /** * Test for Before @@ -506,24 +506,24 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorBefore(new Document(['$id' => $base['body']['collections'][1]['$id']]))->toString(), + Query::cursorBefore(new Document(['$id' => $base['body']['tables'][1]['$id']]))->toString(), ], ]); - $this->assertCount(1, $collections['body']['collections']); - $this->assertEquals($base['body']['collections'][0]['$id'], $collections['body']['collections'][0]['$id']); + $this->assertCount(1, $collections['body']['tables']); + $this->assertEquals($base['body']['tables'][0]['$id'], $collections['body']['tables'][0]['$id']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorBefore(new Document(['$id' => $base['body']['collections'][0]['$id']]))->toString(), + Query::cursorBefore(new Document(['$id' => $base['body']['tables'][0]['$id']]))->toString(), ], ]); - $this->assertCount(0, $collections['body']['collections']); - $this->assertEmpty($collections['body']['collections']); + $this->assertCount(0, $collections['body']['tables']); + $this->assertEmpty($collections['body']['tables']); /** * Test for Search @@ -536,7 +536,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(1, $collections['body']['total']); - $this->assertEquals('first', $collections['body']['collections'][0]['$id']); + $this->assertEquals('first', $collections['body']['tables'][0]['$id']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', @@ -546,8 +546,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(2, $collections['body']['total']); - $this->assertEquals('Test 1', $collections['body']['collections'][0]['name']); - $this->assertEquals('Test 2', $collections['body']['collections'][1]['name']); + $this->assertEquals('Test 1', $collections['body']['tables'][0]['name']); + $this->assertEquals('Test 2', $collections['body']['tables'][1]['name']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', @@ -840,7 +840,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'key_lastName', 'type' => 'key', - 'attributes' => [ + 'columns' => [ 'lastName', ], ]); @@ -857,11 +857,11 @@ class DatabasesCustomServerTest extends Scope $unneededId = $unneeded['body']['key']; $this->assertEquals(200, $collection['headers']['status-code']); - $this->assertIsArray($collection['body']['attributes']); - $this->assertCount(3, $collection['body']['attributes']); - $this->assertEquals($collection['body']['attributes'][0]['key'], $firstName['body']['key']); - $this->assertEquals($collection['body']['attributes'][1]['key'], $lastName['body']['key']); - $this->assertEquals($collection['body']['attributes'][2]['key'], $unneeded['body']['key']); + $this->assertIsArray($collection['body']['columns']); + $this->assertCount(3, $collection['body']['columns']); + $this->assertEquals($collection['body']['columns'][0]['key'], $firstName['body']['key']); + $this->assertEquals($collection['body']['columns'][1]['key'], $lastName['body']['key']); + $this->assertEquals($collection['body']['columns'][2]['key'], $unneeded['body']['key']); $this->assertCount(1, $collection['body']['indexes']); $this->assertEquals($collection['body']['indexes'][0]['key'], $index['body']['key']); @@ -892,10 +892,10 @@ class DatabasesCustomServerTest extends Scope ]), []); $this->assertEquals(200, $collection['headers']['status-code']); - $this->assertIsArray($collection['body']['attributes']); - $this->assertCount(2, $collection['body']['attributes']); - $this->assertEquals($collection['body']['attributes'][0]['key'], $firstName['body']['key']); - $this->assertEquals($collection['body']['attributes'][1]['key'], $lastName['body']['key']); + $this->assertIsArray($collection['body']['columns']); + $this->assertCount(2, $collection['body']['columns']); + $this->assertEquals($collection['body']['columns'][0]['key'], $firstName['body']['key']); + $this->assertEquals($collection['body']['columns'][1]['key'], $lastName['body']['key']); return [ 'collectionId' => $actors['body']['$id'], @@ -972,7 +972,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'index1', 'type' => 'key', - 'attributes' => ['attribute1', 'attribute2'], + 'columns' => ['attribute1', 'attribute2'], 'orders' => ['ASC', 'ASC'], ]); @@ -983,7 +983,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'index2', 'type' => 'key', - 'attributes' => ['attribute2'], + 'columns' => ['attribute2'], ]); $this->assertEquals(202, $index1['headers']['status-code']); @@ -1015,9 +1015,9 @@ class DatabasesCustomServerTest extends Scope $this->assertIsArray($collection['body']['indexes']); $this->assertCount(1, $collection['body']['indexes']); $this->assertEquals($index1['body']['key'], $collection['body']['indexes'][0]['key']); - $this->assertIsArray($collection['body']['indexes'][0]['attributes']); - $this->assertCount(1, $collection['body']['indexes'][0]['attributes']); - $this->assertEquals($attribute1['body']['key'], $collection['body']['indexes'][0]['attributes'][0]); + $this->assertIsArray($collection['body']['indexes'][0]['columns']); + $this->assertCount(1, $collection['body']['indexes'][0]['columns']); + $this->assertEquals($attribute1['body']['key'], $collection['body']['indexes'][0]['columns'][0]); // Delete attribute $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/' . $attribute1['body']['key'], array_merge([ @@ -1100,7 +1100,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'index1', 'type' => 'key', - 'attributes' => ['attribute1', 'attribute2'], + 'columns' => ['attribute1', 'attribute2'], 'orders' => ['ASC', 'ASC'], ]); @@ -1111,7 +1111,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'index2', 'type' => 'key', - 'attributes' => ['attribute2'], + 'columns' => ['attribute2'], ]); $this->assertEquals(202, $index1['headers']['status-code']); @@ -1143,9 +1143,9 @@ class DatabasesCustomServerTest extends Scope $this->assertIsArray($collection['body']['indexes']); $this->assertCount(1, $collection['body']['indexes']); $this->assertEquals($index2['body']['key'], $collection['body']['indexes'][0]['key']); - $this->assertIsArray($collection['body']['indexes'][0]['attributes']); - $this->assertCount(1, $collection['body']['indexes'][0]['attributes']); - $this->assertEquals($attribute2['body']['key'], $collection['body']['indexes'][0]['attributes'][0]); + $this->assertIsArray($collection['body']['indexes'][0]['columns']); + $this->assertCount(1, $collection['body']['indexes'][0]['columns']); + $this->assertEquals($attribute2['body']['key'], $collection['body']['indexes'][0]['columns'][0]); // Delete attribute $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $attribute2['body']['key'], array_merge([ @@ -1426,12 +1426,12 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $collection['headers']['status-code']); $this->assertEquals($collection['body']['name'], 'testLimitException'); - $this->assertIsArray($collection['body']['attributes']); + $this->assertIsArray($collection['body']['columns']); $this->assertIsArray($collection['body']['indexes']); - $this->assertCount(64, $collection['body']['attributes']); + $this->assertCount(64, $collection['body']['columns']); $this->assertCount(0, $collection['body']['indexes']); - foreach ($collection['body']['attributes'] as $attribute) { + foreach ($collection['body']['columns'] as $attribute) { $this->assertEquals('available', $attribute['status'], 'attribute: ' . $attribute['key']); } @@ -1446,7 +1446,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => "key_attribute{$i}", 'type' => 'key', - 'attributes' => ["attribute{$i}"], + 'columns' => ["attribute{$i}"], ]); $this->assertEquals(202, $index['headers']['status-code']); @@ -1463,9 +1463,9 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $collection['headers']['status-code']); $this->assertEquals($collection['body']['name'], 'testLimitException'); - $this->assertIsArray($collection['body']['attributes']); + $this->assertIsArray($collection['body']['columns']); $this->assertIsArray($collection['body']['indexes']); - $this->assertCount(64, $collection['body']['attributes']); + $this->assertCount(64, $collection['body']['columns']); $this->assertCount(58, $collection['body']['indexes']); $tooMany = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ @@ -1475,7 +1475,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'tooMany', 'type' => 'key', - 'attributes' => ['attribute61'], + 'columns' => ['attribute61'], ]); $this->assertEquals(400, $tooMany['headers']['status-code']); @@ -1681,7 +1681,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('lorem', $attribute['default']); @@ -1823,7 +1823,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('torsten@appwrite.io', $attribute['default']); @@ -1966,7 +1966,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('127.0.0.1', $attribute['default']); @@ -2108,7 +2108,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('http://appwrite.io', $attribute['default']); @@ -2254,7 +2254,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals(123, $attribute['default']); @@ -2515,7 +2515,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals(123.456, $attribute['default']); @@ -2772,7 +2772,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals(true, $attribute['default']); @@ -2914,7 +2914,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('1975-06-12 14:12:55+02:00', $attribute['default']); @@ -3061,7 +3061,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('lorem', $attribute['default']); @@ -3700,11 +3700,11 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $collection1RelationAttribute = $collection1Attributes['body']['attributes'][0]; + $collection1RelationAttribute = $collection1Attributes['body']['columns'][0]; $this->assertEquals($relation['body']['side'], $collection1RelationAttribute['side']); $this->assertEquals($relation['body']['twoWayKey'], $collection1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedCollection'], $collection1RelationAttribute['relatedCollection']); + $this->assertEquals($relation['body']['relatedTable'], $collection1RelationAttribute['relatedTable']); // Create a document for checking later $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1Id . '/documents', array_merge([ @@ -3764,8 +3764,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection1Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection1Attributes['body']['attributes'])); - $this->assertEquals('new_level_2', $collection1Attributes['body']['attributes'][0]['key']); + $this->assertEquals(1, count($collection1Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $collection1Attributes['body']['columns'][0]['key']); // Check if attribute was renamed on the child's side $collection2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection2Id, [ @@ -3775,8 +3775,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection2Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection2Attributes['body']['attributes'])); - $this->assertEquals('new_level_2', $collection2Attributes['body']['attributes'][0]['twoWayKey']); + $this->assertEquals(1, count($collection2Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $collection2Attributes['body']['columns'][0]['twoWayKey']); $this->cleanupRelationshipCollection(); } @@ -3810,11 +3810,11 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $collection1RelationAttribute = $collection1Attributes['body']['attributes'][0]; + $collection1RelationAttribute = $collection1Attributes['body']['columns'][0]; $this->assertEquals($relation['body']['side'], $collection1RelationAttribute['side']); $this->assertEquals($relation['body']['twoWayKey'], $collection1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedCollection'], $collection1RelationAttribute['relatedCollection']); + $this->assertEquals($relation['body']['relatedTable'], $collection1RelationAttribute['relatedTable']); // Create a document for checking later $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1Id . '/documents', array_merge([ @@ -3874,8 +3874,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection1Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection1Attributes['body']['attributes'])); - $this->assertEquals('new_level_2', $collection1Attributes['body']['attributes'][0]['key']); + $this->assertEquals(1, count($collection1Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $collection1Attributes['body']['columns'][0]['key']); // Check if attribute was renamed on the child's side $collection2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection2Id, [ @@ -3885,8 +3885,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection2Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection2Attributes['body']['attributes'])); - $this->assertEquals('new_level_2', $collection2Attributes['body']['attributes'][0]['twoWayKey']); + $this->assertEquals(1, count($collection2Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $collection2Attributes['body']['columns'][0]['twoWayKey']); $this->cleanupRelationshipCollection(); } @@ -3920,11 +3920,11 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $collection1RelationAttribute = $collection1Attributes['body']['attributes'][0]; + $collection1RelationAttribute = $collection1Attributes['body']['columns'][0]; $this->assertEquals($relation['body']['side'], $collection1RelationAttribute['side']); $this->assertEquals($relation['body']['twoWayKey'], $collection1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedCollection'], $collection1RelationAttribute['relatedCollection']); + $this->assertEquals($relation['body']['relatedTable'], $collection1RelationAttribute['relatedTable']); // Create a document for checking later $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1Id . '/documents', array_merge([ @@ -3984,8 +3984,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection1Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection1Attributes['body']['attributes'])); - $this->assertEquals('new_level_2', $collection1Attributes['body']['attributes'][0]['key']); + $this->assertEquals(1, count($collection1Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $collection1Attributes['body']['columns'][0]['key']); // Check if attribute was renamed on the child's side $collection2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection2Id, [ @@ -3995,8 +3995,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection2Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection2Attributes['body']['attributes'])); - $this->assertEquals('new_level_2', $collection2Attributes['body']['attributes'][0]['twoWayKey']); + $this->assertEquals(1, count($collection2Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $collection2Attributes['body']['columns'][0]['twoWayKey']); $this->cleanupRelationshipCollection(); } @@ -4030,11 +4030,11 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $collection1RelationAttribute = $collection1Attributes['body']['attributes'][0]; + $collection1RelationAttribute = $collection1Attributes['body']['columns'][0]; $this->assertEquals($relation['body']['side'], $collection1RelationAttribute['side']); $this->assertEquals($relation['body']['twoWayKey'], $collection1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedCollection'], $collection1RelationAttribute['relatedCollection']); + $this->assertEquals($relation['body']['relatedTable'], $collection1RelationAttribute['relatedTable']); // Create a document for checking later $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1Id . '/documents', array_merge([ @@ -4094,8 +4094,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection1Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection1Attributes['body']['attributes'])); - $this->assertEquals('new_level_2', $collection1Attributes['body']['attributes'][0]['key']); + $this->assertEquals(1, count($collection1Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $collection1Attributes['body']['columns'][0]['key']); // Check if attribute was renamed on the child's side $collection2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection2Id, [ @@ -4105,8 +4105,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection2Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection2Attributes['body']['attributes'])); - $this->assertEquals('new_level_2', $collection2Attributes['body']['attributes'][0]['twoWayKey']); + $this->assertEquals(1, count($collection2Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $collection2Attributes['body']['columns'][0]['twoWayKey']); $this->cleanupRelationshipCollection(); } diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php index ca8753f374..9e20e13c2a 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php @@ -124,11 +124,11 @@ class DatabasesPermissionsGuestTest extends Scope ]); $this->assertEquals(1, $publicDocuments['body']['total']); - $this->assertEquals($permissions, $publicDocuments['body']['documents'][0]['$permissions']); + $this->assertEquals($permissions, $publicDocuments['body']['rows'][0]['$permissions']); if (\in_array(Permission::read(Role::any()), $permissions)) { $this->assertEquals(1, $privateDocuments['body']['total']); - $this->assertEquals($permissions, $privateDocuments['body']['documents'][0]['$permissions']); + $this->assertEquals($permissions, $privateDocuments['body']['rows'][0]['$permissions']); } else { $this->assertEquals(0, $privateDocuments['body']['total']); } diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php index 860fb7fb12..239fa58c99 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php @@ -186,7 +186,7 @@ class DatabasesPermissionsMemberTest extends Scope return [ 'users' => $this->users, - 'collections' => $this->collections, + 'tables' => $this->collections, 'databaseId' => $databaseId ]; } @@ -199,7 +199,7 @@ class DatabasesPermissionsMemberTest extends Scope public function testReadDocuments($permissions, $anyCount, $usersCount, $docOnlyCount, $data) { $users = $data['users']; - $collections = $data['collections']; + $collections = $data['tables']; $databaseId = $data['databaseId']; $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['public'] . '/documents', $this->getServerHeader(), [ diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php index 066d83a7ee..9b0a04ac27 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php @@ -174,7 +174,7 @@ class DatabasesPermissionsTeamTest extends Scope ]); if ($success) { - $this->assertCount(1, $documents['body']['documents']); + $this->assertCount(1, $documents['body']['rows']); } else { $this->assertEquals(401, $documents['headers']['status-code']); } From 37fb34ae1207275892cf7116d0a18f840c75d4cf Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 5 May 2025 14:33:27 +0530 Subject: [PATCH 052/343] wip: events compat based on version. --- app/controllers/shared/api.php | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 8c15f27acc..ba695acff4 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -483,10 +483,26 @@ App::init() /* * Background Jobs */ + $events = $route->getLabel('event', ''); $queueForEvents - ->setEvent($route->getLabel('event', '')) - ->setProject($project) - ->setUser($user); + ->setUser($user) + ->setEvent($events) + ->setProject($project); + + if (str_contains($events, '.tables.')) { + $requestFormat = $request->getHeader('x-appwrite-response-format', System::getEnv('_APP_SYSTEM_RESPONSE_FORMAT', '')); + if ($requestFormat && version_compare($requestFormat, '1.7.0', '<')) { + $map = [ + 'rows' => 'documents', + 'tables' => 'collections', + 'columns' => 'attributes', + ]; + + $compatibleEvents = str_replace(array_keys($map), array_values($map), $events); + // override the events + $queueForEvents->setEvent($compatibleEvents); + } + } $queueForAudits ->setMode($mode) From b905af91af8f55071328e46ab59dbeb8ca63eeb0 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 5 May 2025 14:43:09 +0530 Subject: [PATCH 053/343] fix: project usage `documents` to `rows`. --- app/controllers/api/project.php | 2 +- src/Appwrite/Utopia/Response/Model/UsageProject.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 047179b888..97475c743a 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -353,7 +353,7 @@ App::get('/v1/project/usage') 'executionsTotal' => $total[METRIC_EXECUTIONS], 'executionsMbSecondsTotal' => $total[METRIC_EXECUTIONS_MB_SECONDS], 'buildsMbSecondsTotal' => $total[METRIC_BUILDS_MB_SECONDS], - 'documentsTotal' => $total[METRIC_DOCUMENTS], + 'rowsTotal' => $total[METRIC_DOCUMENTS], 'databasesTotal' => $total[METRIC_DATABASES], 'databasesStorageTotal' => $total[METRIC_DATABASES_STORAGE], 'usersTotal' => $total[METRIC_USERS], diff --git a/src/Appwrite/Utopia/Response/Model/UsageProject.php b/src/Appwrite/Utopia/Response/Model/UsageProject.php index 395b19b7cd..b79cd85bed 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageProject.php +++ b/src/Appwrite/Utopia/Response/Model/UsageProject.php @@ -16,9 +16,9 @@ class UsageProject extends Model 'default' => 0, 'example' => 0, ]) - ->addRule('documentsTotal', [ + ->addRule('rowsTotal', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of documents.', + 'description' => 'Total aggregated number of rows.', 'default' => 0, 'example' => 0, ]) From 67a8f522e5d9ae147807a9fcd8b2c74bdfd08313 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 5 May 2025 14:45:55 +0530 Subject: [PATCH 054/343] fix: project and general usage tests. --- tests/e2e/General/UsageTest.php | 48 +++++++++---------- .../Projects/ProjectsConsoleClientTest.php | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/e2e/General/UsageTest.php b/tests/e2e/General/UsageTest.php index 5549ef800d..0c27a76311 100644 --- a/tests/e2e/General/UsageTest.php +++ b/tests/e2e/General/UsageTest.php @@ -416,8 +416,8 @@ class UsageTest extends Scope $requestsTotal = $data['requestsTotal']; $databasesTotal = 0; - $collectionsTotal = 0; - $documentsTotal = 0; + $tablesTotal = 0; + $rowsTotal = 0; for ($i = 0; $i < self::CREATE; $i++) { $name = uniqid() . ' database'; @@ -470,7 +470,7 @@ class UsageTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'collectionId' => 'unique()', + 'tableId' => 'unique()', 'name' => $name, 'documentSecurity' => false, 'permissions' => [ @@ -486,7 +486,7 @@ class UsageTest extends Scope $this->assertNotEmpty($response['body']['$id']); $requestsTotal += 1; - $collectionsTotal += 1; + $tablesTotal += 1; $collectionId = $response['body']['$id']; @@ -501,7 +501,7 @@ class UsageTest extends Scope $this->assertEmpty($response['body']); - $collectionsTotal -= 1; + $tablesTotal -= 1; $requestsTotal += 1; } } @@ -546,7 +546,7 @@ class UsageTest extends Scope $this->assertNotEmpty($response['body']['$id']); $requestsTotal += 1; - $documentsTotal += 1; + $rowsTotal += 1; $documentId = $response['body']['$id']; @@ -561,18 +561,18 @@ class UsageTest extends Scope $this->assertEmpty($response['body']); - $documentsTotal -= 1; + $rowsTotal -= 1; $requestsTotal += 1; } } return array_merge($data, [ 'databaseId' => $databaseId, - 'collectionId' => $collectionId, + 'tableId' => $collectionId, 'requestsTotal' => $requestsTotal, 'databasesTotal' => $databasesTotal, - 'collectionsTotal' => $collectionsTotal, - 'documentsTotal' => $documentsTotal, + 'tablesTotal' => $tablesTotal, + 'rowsTotal' => $rowsTotal, ]); } @@ -581,11 +581,11 @@ class UsageTest extends Scope public function testDatabaseStats(array $data): array { $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $requestsTotal = $data['requestsTotal']; $databasesTotal = $data['databasesTotal']; - $collectionsTotal = $data['collectionsTotal']; - $documentsTotal = $data['documentsTotal']; + $tablesTotal = $data['tablesTotal']; + $rowsTotal = $data['rowsTotal']; sleep(self::WAIT); @@ -606,7 +606,7 @@ class UsageTest extends Scope $this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']); $this->validateDates($response['body']['requests']); $this->assertEquals($databasesTotal, $response['body']['databasesTotal']); - $this->assertEquals($documentsTotal, $response['body']['documentsTotal']); + $this->assertEquals($rowsTotal, $response['body']['rowsTotal']); $response = $this->client->call( Client::METHOD_GET, @@ -616,10 +616,10 @@ class UsageTest extends Scope $this->assertEquals($databasesTotal, $response['body']['databases'][array_key_last($response['body']['databases'])]['value']); $this->validateDates($response['body']['databases']); - $this->assertEquals($collectionsTotal, $response['body']['collections'][array_key_last($response['body']['collections'])]['value']); - $this->validateDates($response['body']['collections']); - $this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']); - $this->validateDates($response['body']['documents']); + $this->assertEquals($tablesTotal, $response['body']['tables'][array_key_last($response['body']['tables'])]['value']); + $this->validateDates($response['body']['tables']); + $this->assertEquals($rowsTotal, $response['body']['rows'][array_key_last($response['body']['rows'])]['value']); + $this->validateDates($response['body']['rows']); $response = $this->client->call( Client::METHOD_GET, @@ -627,11 +627,11 @@ class UsageTest extends Scope $this->getConsoleHeaders() ); - $this->assertEquals($collectionsTotal, $response['body']['collections'][array_key_last($response['body']['collections'])]['value']); - $this->validateDates($response['body']['collections']); + $this->assertEquals($tablesTotal, $response['body']['tables'][array_key_last($response['body']['tables'])]['value']); + $this->validateDates($response['body']['tables']); - $this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']); - $this->validateDates($response['body']['documents']); + $this->assertEquals($rowsTotal, $response['body']['rows'][array_key_last($response['body']['rows'])]['value']); + $this->validateDates($response['body']['rows']); $response = $this->client->call( Client::METHOD_GET, @@ -639,8 +639,8 @@ class UsageTest extends Scope $this->getConsoleHeaders() ); - $this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']); - $this->validateDates($response['body']['documents']); + $this->assertEquals($rowsTotal, $response['body']['rows'][array_key_last($response['body']['rows'])]['value']); + $this->validateDates($response['body']['rows']); return $data; } diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index c66a581b1a..c864773535 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -483,7 +483,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertIsArray($response['body']['requests']); $this->assertIsArray($response['body']['network']); $this->assertIsNumeric($response['body']['executionsTotal']); - $this->assertIsNumeric($response['body']['documentsTotal']); + $this->assertIsNumeric($response['body']['rowsTotal']); $this->assertIsNumeric($response['body']['databasesTotal']); $this->assertIsNumeric($response['body']['bucketsTotal']); $this->assertIsNumeric($response['body']['usersTotal']); From 565e6b2ad8bfb8fb2685fad630cd5115708e0a70 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 5 May 2025 17:03:17 +0530 Subject: [PATCH 055/343] fix: migrations test <> csv imports. --- tests/e2e/Services/Migrations/MigrationsBase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Migrations/MigrationsBase.php b/tests/e2e/Services/Migrations/MigrationsBase.php index c241b38e3d..208bd58731 100644 --- a/tests/e2e/Services/Migrations/MigrationsBase.php +++ b/tests/e2e/Services/Migrations/MigrationsBase.php @@ -1176,7 +1176,7 @@ trait MigrationsBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertIsArray($documents['body']['documents']); + $this->assertIsArray($documents['body']['rows']); $this->assertIsNumeric($documents['body']['total']); $this->assertEquals($documentsCountInCSV, $documents['body']['total']); } From 56077d59f72398369dda3771f23a3f8fb0cd3d31 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 10:51:11 +0530 Subject: [PATCH 056/343] fix: graphql tests. --- app/init/resources.php | 8 ++-- src/Appwrite/GraphQL/Types/Mapper.php | 26 ++++++------- .../Modules/Databases/Http/Tables/XList.php | 2 +- .../Request/Filters/DatabaseAliases.php | 3 +- tests/e2e/Services/GraphQL/Base.php | 38 +++++++++---------- 5 files changed, 39 insertions(+), 38 deletions(-) diff --git a/app/init/resources.php b/app/init/resources.php index 3a1539e59b..7657b9ea69 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -721,8 +721,8 @@ App::setResource('schema', function ($utopia, $dbForProject) { // Order must be the same as the route params return [ 'databaseId' => $databaseId, - 'documentId' => $id, - 'collectionId' => $collectionId, + 'rowId' => $id, + 'tableId' => $collectionId, 'data' => $args, 'permissions' => $permissions, ]; @@ -737,8 +737,8 @@ App::setResource('schema', function ($utopia, $dbForProject) { // Order must be the same as the route params return [ 'databaseId' => $databaseId, - 'collectionId' => $collectionId, - 'documentId' => $documentId, + 'tableId' => $collectionId, + 'rowId' => $documentId, 'data' => $args, 'permissions' => $permissions, ]; diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index e5056d0abc..8cfad823af 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -418,8 +418,8 @@ class Mapper // TODO: Find a better way to do this switch ($name) { - case 'Attributes': - return static::getAttributeImplementation($object); + case 'Columns': + return static::getColumnImplementation($object); case 'HashOptions': return static::getHashOptionsImplementation($object); } @@ -427,29 +427,29 @@ class Mapper throw new Exception('Unknown union type: ' . $name); } - private static function getAttributeImplementation(array $object): Type + private static function getColumnImplementation(array $object): Type { switch ($object['type']) { case 'string': return match ($object['format'] ?? '') { - 'email' => static::model('AttributeEmail'), - 'url' => static::model('AttributeUrl'), - 'ip' => static::model('AttributeIp'), - default => static::model('AttributeString'), + 'email' => static::model('ColumnEmail'), + 'url' => static::model('ColumnUrl'), + 'ip' => static::model('ColumnIp'), + default => static::model('ColumnString'), }; case 'integer': - return static::model('AttributeInteger'); + return static::model('ColumnInteger'); case 'double': - return static::model('AttributeFloat'); + return static::model('ColumnFloat'); case 'boolean': - return static::model('AttributeBoolean'); + return static::model('ColumnBoolean'); case 'datetime': - return static::model('AttributeDatetime'); + return static::model('ColumnDatetime'); case 'relationship': - return static::model('AttributeRelationship'); + return static::model('ColumnRelationship'); } - throw new Exception('Unknown attribute implementation'); + throw new Exception('Unknown column implementation'); } private static function getHashOptionsImplementation(array $object): Type diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php index 86107cc533..055102415d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php @@ -49,7 +49,7 @@ class XList extends Action responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_TABLE, + model: UtopiaResponse::MODEL_TABLE_LIST, ) ], contentType: ContentType::JSON diff --git a/src/Appwrite/Utopia/Request/Filters/DatabaseAliases.php b/src/Appwrite/Utopia/Request/Filters/DatabaseAliases.php index b2b772be11..0ee2754475 100644 --- a/src/Appwrite/Utopia/Request/Filters/DatabaseAliases.php +++ b/src/Appwrite/Utopia/Request/Filters/DatabaseAliases.php @@ -12,7 +12,8 @@ class DatabaseAliases extends Filter 'attributes' => 'columns', 'collectionId' => 'tableId', 'attributeId' => 'columnId', - 'relatedCollectionId' => 'relatedTableId' + 'relatedCollection' => 'relatedTable', + 'relatedCollectionId' => 'relatedTableId', ]; public function parse(array $content, string $model): array diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 95f446cf6f..7c91cf67f7 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -259,8 +259,8 @@ trait Base // Fragments public static string $FRAGMENT_COLUMNS = ' - fragment attributeProperties on Attributes { - ... on AttributeString { + fragment columnProperties on Columns { + ... on ColumnString { key required array @@ -268,7 +268,7 @@ trait Base default size } - ... on AttributeInteger { + ... on ColumnInteger { key required array @@ -277,7 +277,7 @@ trait Base intMin: min intMax: max } - ... on AttributeFloat { + ... on ColumnFloat { key required array @@ -286,35 +286,35 @@ trait Base floatMin: min floatMax: max } - ... on AttributeBoolean { + ... on ColumnBoolean { key required array status boolDefault:default } - ... on AttributeUrl { + ... on ColumnUrl { key required array status default } - ... on AttributeEmail { + ... on ColumnEmail { key required array status default } - ... on AttributeIp { + ... on ColumnIp { key required array status default } - ... on AttributeEnum { + ... on ColumnEnum { key required array @@ -322,7 +322,7 @@ trait Base default elements } - ... on AttributeDatetime { + ... on ColumnDatetime { key required array @@ -406,7 +406,7 @@ trait Base return 'query listTables($databaseId: String!) { databasesListTables(databaseId: $databaseId) { total - collections { + tables { _id _permissions documentSecurity @@ -527,7 +527,7 @@ trait Base case self::$CREATE_RELATIONSHIP_COLUMN: return 'mutation createRelationshipColumn($databaseId: String!, $tableId: String!, $relatedTableId: String!, $type: String!, $twoWay: Boolean, $key: String, $twoWayKey: String, $onDelete: String){ databasesCreateRelationshipColumn(databaseId: $databaseId, tableId: $tableId, relatedTableId: $relatedTableId, type: $type, twoWay: $twoWay, key: $key, twoWayKey: $twoWayKey, onDelete: $onDelete) { - relatedCollection + relatedTable relationType twoWay key @@ -606,7 +606,7 @@ trait Base case self::$UPDATE_RELATIONSHIP_COLUMN: return 'mutation updateRelationshipColumn($databaseId: String!, $tableId: String!, $key: String!, $onDelete: String){ databasesUpdateRelationshipColumn(databaseId: $databaseId, tableId: $tableId, key: $key, onDelete: $onDelete) { - relatedCollection + relatedTable relationType twoWay key @@ -651,15 +651,15 @@ trait Base return 'query listColumns($databaseId: String!, $tableId: String!) { databasesListColumns(databaseId: $databaseId, tableId: $tableId) { total - attributes { - ...attributeProperties + columns { + ...columnProperties } } }' . PHP_EOL . self::$FRAGMENT_COLUMNS; case self::$GET_COLUMN: return 'query getColumn($databaseId: String!, $tableId: String!, $key: String!) { databasesGetColumn(databaseId: $databaseId, tableId: $tableId, key: $key) { - ...attributeProperties + ...columnProperties } }' . PHP_EOL . self::$FRAGMENT_COLUMNS; case self::$DELETE_COLUMN: @@ -681,7 +681,7 @@ trait Base return 'query listRows($databaseId: String!, $tableId: String!){ databasesListRows(databaseId: $databaseId, tableId: $tableId) { total - documents { + rows { _id _collectionId _permissions @@ -2259,8 +2259,8 @@ trait Base _databaseId name documentSecurity - attributes { - ...attributeProperties + columns { + ...columnProperties } indexes { key From 9e1105b61f71b357adf5871bf57bebc9dff40061 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 11:29:56 +0530 Subject: [PATCH 057/343] update: tests. --- tests/e2e/General/AbuseTest.php | 16 +- tests/e2e/General/UsageTest.php | 2 +- .../e2e/Services/Databases/DatabasesBase.php | 152 +++++++++--------- .../Databases/DatabasesConsoleClientTest.php | 4 +- .../Databases/DatabasesCustomClientTest.php | 62 +++---- .../Databases/DatabasesCustomServerTest.php | 120 +++++++------- .../DatabasesPermissionsGuestTest.php | 18 +-- .../DatabasesPermissionsMemberTest.php | 12 +- .../DatabasesPermissionsTeamTest.php | 10 +- tests/e2e/Services/GraphQL/AbuseTest.php | 14 +- tests/e2e/Services/GraphQL/Base.php | 8 +- .../Services/Migrations/MigrationsBase.php | 14 +- .../Realtime/RealtimeConsoleClientTest.php | 4 +- .../Realtime/RealtimeCustomClientTest.php | 14 +- tests/e2e/Services/Webhooks/WebhooksBase.php | 12 +- .../Webhooks/WebhooksCustomServerTest.php | 4 +- 16 files changed, 233 insertions(+), 233 deletions(-) diff --git a/tests/e2e/General/AbuseTest.php b/tests/e2e/General/AbuseTest.php index 898fbd4aff..2ef351f43e 100644 --- a/tests/e2e/General/AbuseTest.php +++ b/tests/e2e/General/AbuseTest.php @@ -30,7 +30,7 @@ class AbuseTest extends Scope { $data = $this->createCollection(); $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $max = 120; for ($i = 0; $i <= $max + 1; $i++) { @@ -38,7 +38,7 @@ class AbuseTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'The Hulk ' . $i, ], @@ -56,7 +56,7 @@ class AbuseTest extends Scope { $data = $this->createCollection(); $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $max = 120; $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ @@ -64,7 +64,7 @@ class AbuseTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'The Hulk', ], @@ -94,7 +94,7 @@ class AbuseTest extends Scope { $data = $this->createCollection(); $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $max = 60; for ($i = 0; $i <= $max + 1; $i++) { @@ -103,7 +103,7 @@ class AbuseTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'The Hulk', ], @@ -232,7 +232,7 @@ class AbuseTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::read(Role::any()), @@ -258,7 +258,7 @@ class AbuseTest extends Scope return [ 'databaseId' => $databaseId, - 'collectionId' => $collectionId, + 'tableId' => $collectionId, ]; } diff --git a/tests/e2e/General/UsageTest.php b/tests/e2e/General/UsageTest.php index 0c27a76311..54b8597204 100644 --- a/tests/e2e/General/UsageTest.php +++ b/tests/e2e/General/UsageTest.php @@ -537,7 +537,7 @@ class UsageTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'documentId' => 'unique()', + 'rowId' => 'unique()', 'data' => ['name' => $name] ] ); diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 14713a52ee..3df5dd4387 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -51,7 +51,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Movies', 'documentSecurity' => true, 'permissions' => [ @@ -67,7 +67,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Actors', 'documentSecurity' => true, 'permissions' => [ @@ -148,7 +148,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Captain America', ], @@ -275,7 +275,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $data['actorsId'], + 'relatedTableId' => $data['actorsId'], 'type' => 'oneToMany', 'twoWay' => true, 'key' => 'starringActors', @@ -417,7 +417,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'patch', 'documentSecurity' => true, 'permissions' => [ @@ -488,7 +488,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Players', 'documentSecurity' => true, 'permissions' => [ @@ -540,7 +540,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Response Models', // 'permissions' missing on purpose to make sure it's optional 'documentSecurity' => true, @@ -654,7 +654,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $data['actorsId'], + 'relatedTableId' => $data['actorsId'], 'type' => 'oneToMany', 'twoWay' => true, 'key' => 'relationship', @@ -1463,7 +1463,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Captain America', 'releaseYear' => 1944, @@ -1484,7 +1484,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Spider-Man: Far From Home', 'releaseYear' => 2019, @@ -1507,7 +1507,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Spider-Man: Homecoming', 'releaseYear' => 2017, @@ -1530,7 +1530,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'releaseYear' => 2020, // Missing title, expect an 400 error ], @@ -1655,7 +1655,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Dummy', 'releaseYear' => 1944, @@ -2287,7 +2287,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Thor: Ragnaroc', 'releaseYear' => 2017, @@ -2413,7 +2413,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Thor: Ragnarok', 'releaseYear' => 2017, @@ -2474,7 +2474,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'invalidDocumentStructure', 'permissions' => [ Permission::create(Role::any()), @@ -2692,7 +2692,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'email' => 'user@example.com', ], @@ -2707,7 +2707,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'enum' => 'yes', ], @@ -2722,7 +2722,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'ip' => '1.1.1.1', ], @@ -2737,7 +2737,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'url' => 'http://www.example.com', ], @@ -2752,7 +2752,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'range' => 3, ], @@ -2767,7 +2767,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'floatRange' => 1.4, ], @@ -2782,7 +2782,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'probability' => 0.99999, ], @@ -2797,7 +2797,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'upperBound' => 8, ], @@ -2812,7 +2812,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'lowerBound' => 8, ], @@ -2841,7 +2841,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'email' => 'user@@example.com', ], @@ -2856,7 +2856,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'enum' => 'badEnum', ], @@ -2871,7 +2871,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'ip' => '1.1.1.1.1', ], @@ -2886,7 +2886,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'url' => 'example...com', ], @@ -2901,7 +2901,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'range' => 11, ], @@ -2916,7 +2916,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'floatRange' => 2.5, ], @@ -2931,7 +2931,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'probability' => 1.1, ], @@ -2946,7 +2946,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'upperBound' => 11, ], @@ -2961,7 +2961,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'lowerBound' => 3, ], @@ -2976,7 +2976,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => 'unique()', + 'rowId' => 'unique()', 'data' => [ 'birthDay' => '2020-10-10 27:30:10+01:00', ], @@ -3015,7 +3015,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Captain America', 'releaseYear' => 1944, @@ -3145,7 +3145,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'enforceCollectionAndDocumentPermissions', 'documentSecurity' => true, 'permissions' => [ @@ -3200,7 +3200,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'attribute' => 'one', ], @@ -3217,7 +3217,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'attribute' => 'one', ], @@ -3234,7 +3234,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'attribute' => 'one', ], @@ -3338,7 +3338,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'enforceCollectionPermissions', 'permissions' => [ Permission::read(Role::user($user)), @@ -3388,7 +3388,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'attribute' => 'one', ], @@ -3405,7 +3405,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'attribute' => 'one', ], @@ -3422,7 +3422,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'attribute' => 'one', ], @@ -3541,7 +3541,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Captain America', 'releaseYear' => 1944, @@ -3564,7 +3564,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Captain America 5', 'releaseYear' => 1944, @@ -3587,7 +3587,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Captain America', 'releaseYear' => 1944, @@ -3623,7 +3623,7 @@ trait DatabasesBase ]; $document = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/collections/' . $data['moviesId'] . '/documents', $headers, [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Creation Date Test', 'releaseYear' => 2000 @@ -3691,7 +3691,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::create(Role::user(ID::custom($this->getUser()['$id']))), @@ -3728,7 +3728,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Captain America', ], @@ -3802,7 +3802,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Boolean' ]); @@ -3847,7 +3847,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => 'person', + 'tableId' => 'person', 'name' => 'person', 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), @@ -3865,7 +3865,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => 'library', + 'tableId' => 'library', 'name' => 'library', 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), @@ -3894,7 +3894,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => 'library', + 'relatedTableId' => 'library', 'type' => Database::RELATION_ONE_TO_ONE, 'key' => 'library', 'twoWay' => true, @@ -3957,7 +3957,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'library' => [ '$id' => 'library1', @@ -3981,7 +3981,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'library' => [ 'libraryName' => 'Library 2', @@ -4092,7 +4092,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => 'library', + 'relatedTableId' => 'library', 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => true, 'key' => 'libraries', @@ -4141,7 +4141,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => 'person10', + 'rowId' => 'person10', 'data' => [ 'fullName' => 'Stevie Wonder', 'libraries' => [ @@ -4237,7 +4237,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Albums', 'documentSecurity' => true, 'permissions' => [ @@ -4263,7 +4263,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Artists', 'documentSecurity' => true, 'permissions' => [ @@ -4289,7 +4289,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $artists['body']['$id'], + 'relatedTableId' => $artists['body']['$id'], 'type' => Database::RELATION_MANY_TO_ONE, 'twoWay' => true, 'key' => 'artist', @@ -4318,7 +4318,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => 'album1', + 'rowId' => 'album1', 'permissions' => $permissions, 'data' => [ 'name' => 'Album 1', @@ -4381,7 +4381,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Sports', 'documentSecurity' => true, 'permissions' => [ @@ -4407,7 +4407,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Players', 'documentSecurity' => true, 'permissions' => [ @@ -4433,7 +4433,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $players['body']['$id'], + 'relatedTableId' => $players['body']['$id'], 'type' => Database::RELATION_MANY_TO_MANY, 'twoWay' => true, 'key' => 'players', @@ -4463,7 +4463,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => 'sport1', + 'rowId' => 'sport1', 'permissions' => $permissions, 'data' => [ 'name' => 'Sport 1', @@ -4641,7 +4641,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'USA Presidents', 'documentSecurity' => true, 'permissions' => [ @@ -4683,7 +4683,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'first_name' => 'Donald', 'last_name' => 'Trump', @@ -4698,7 +4698,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'first_name' => 'George', 'last_name' => 'Bush', @@ -4713,7 +4713,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'first_name' => 'Joe', 'last_name' => 'Biden', @@ -4764,7 +4764,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Collection1', 'documentSecurity' => true, 'permissions' => [ @@ -4778,7 +4778,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Collection2', 'documentSecurity' => true, 'permissions' => [ @@ -4815,7 +4815,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection2, + 'relatedTableId' => $collection2, 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => true, 'key' => 'collection2' @@ -4827,7 +4827,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'name' => 'Document 1', 'collection2' => [ @@ -4860,7 +4860,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Slow Queries', 'documentSecurity' => true, 'permissions' => [ @@ -4893,7 +4893,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'longtext' => file_get_contents(__DIR__ . '/../../../resources/longtext.txt'), ], diff --git a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php b/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php index 04daddd47a..e9dca1d674 100644 --- a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php @@ -38,7 +38,7 @@ class DatabasesConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::read(Role::any()), @@ -69,7 +69,7 @@ class DatabasesConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'TvShows', 'permissions' => [ Permission::read(Role::any()), diff --git a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php index 6caeb3ca8b..b192cd04a1 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php @@ -40,7 +40,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Movies', 'documentSecurity' => true, 'permissions' => [ @@ -73,7 +73,7 @@ class DatabasesCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Captain America', ], @@ -95,7 +95,7 @@ class DatabasesCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Captain America', ], @@ -138,7 +138,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::custom('permissionCheck'), + 'tableId' => ID::custom('permissionCheck'), 'name' => 'permissionCheck', 'permissions' => [], 'documentSecurity' => true, @@ -166,7 +166,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => ID::custom('permissionCheckDocument'), + 'rowId' => ID::custom('permissionCheckDocument'), 'data' => [ 'name' => 'AppwriteBeginner', ], @@ -247,7 +247,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'level1', 'documentSecurity' => false, 'permissions' => [ @@ -264,7 +264,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'level2', 'documentSecurity' => false, 'permissions' => [ @@ -283,7 +283,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection2['body']['$id'], + 'relatedTableId' => $collection2['body']['$id'], 'type' => 'oneToMany', 'twoWay' => true, 'onDelete' => 'cascade', @@ -335,7 +335,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'c1', 'documentSecurity' => false, 'permissions' => [ @@ -351,7 +351,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'c2', 'documentSecurity' => false, 'permissions' => [ @@ -369,7 +369,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection2['body']['$id'], + 'relatedTableId' => $collection2['body']['$id'], 'type' => Database::RELATION_ONE_TO_ONE, 'twoWay' => false, 'onDelete' => 'cascade', @@ -387,7 +387,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection2['body']['$id'], + 'relatedTableId' => $collection2['body']['$id'], 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => false, 'onDelete' => 'cascade', @@ -406,7 +406,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection2['body']['$id'], + 'relatedTableId' => $collection2['body']['$id'], 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => false, 'onDelete' => 'cascade', @@ -424,7 +424,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection2['body']['$id'], + 'relatedTableId' => $collection2['body']['$id'], 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => false, 'onDelete' => 'cascade', @@ -442,7 +442,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection2['body']['$id'], + 'relatedTableId' => $collection2['body']['$id'], 'type' => Database::RELATION_MANY_TO_MANY, 'twoWay' => true, 'onDelete' => 'setNull', @@ -461,7 +461,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection2['body']['$id'], + 'relatedTableId' => $collection2['body']['$id'], 'type' => Database::RELATION_MANY_TO_MANY, 'twoWay' => true, 'onDelete' => 'setNull', @@ -495,7 +495,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::custom('collection1'), + 'tableId' => ID::custom('collection1'), 'name' => ID::custom('collection1'), 'documentSecurity' => false, 'permissions' => [ @@ -511,7 +511,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::custom('collection2'), + 'tableId' => ID::custom('collection2'), 'name' => ID::custom('collection2'), 'documentSecurity' => false, 'permissions' => [ @@ -524,7 +524,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::custom('collection3'), + 'tableId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), 'documentSecurity' => false, 'permissions' => [ @@ -539,7 +539,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::custom('collection4'), + 'tableId' => ID::custom('collection4'), 'name' => ID::custom('collection4'), 'documentSecurity' => false, 'permissions' => [ @@ -552,7 +552,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::custom('collection5'), + 'tableId' => ID::custom('collection5'), 'name' => ID::custom('collection5'), 'documentSecurity' => false, 'permissions' => [ @@ -568,7 +568,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection2['body']['$id'], + 'relatedTableId' => $collection2['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', @@ -581,7 +581,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection3['body']['$id'], + 'relatedTableId' => $collection3['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', @@ -594,7 +594,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection4['body']['$id'], + 'relatedTableId' => $collection4['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', @@ -607,7 +607,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection5['body']['$id'], + 'relatedTableId' => $collection5['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', @@ -681,7 +681,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => ID::custom($collection1['body']['$id']), + 'rowId' => ID::custom($collection1['body']['$id']), 'data' => [ 'Title' => 'Captain America', $collection2['body']['$id'] => [ @@ -709,7 +709,7 @@ class DatabasesCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::custom($collection1['body']['$id']), + 'rowId' => ID::custom($collection1['body']['$id']), 'data' => [ 'Title' => 'Captain America', $collection2['body']['$id'] => [ @@ -739,7 +739,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::custom('collection3'), + 'tableId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), 'documentSecurity' => false, 'permissions' => [ @@ -814,7 +814,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::custom('collection3'), + 'tableId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), 'documentSecurity' => false, 'permissions' => [ @@ -830,7 +830,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::custom('collection2'), + 'tableId' => ID::custom('collection2'), 'name' => ID::custom('collection2'), 'documentSecurity' => false, 'permissions' => [ @@ -847,7 +847,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => ID::custom('collection3Doc1'), + 'rowId' => ID::custom('collection3Doc1'), 'data' => [ 'Rating' => '20' ] diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 7e5da78ccd..508578f149 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -358,7 +358,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test 1', - 'collectionId' => ID::custom('first'), + 'tableId' => ID::custom('first'), 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), @@ -374,7 +374,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test 2', - 'collectionId' => ID::custom('second'), + 'tableId' => ID::custom('second'), 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), @@ -579,7 +579,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test 1', - 'collectionId' => ID::custom('first'), + 'tableId' => ID::custom('first'), 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), @@ -592,7 +592,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(409, $response['headers']['status-code']); return [ 'databaseId' => $databaseId, - 'collectionId' => $test1['body']['$id'], + 'tableId' => $test1['body']['$id'], ]; } @@ -602,7 +602,7 @@ class DatabasesCustomServerTest extends Scope public function testGetCollection(array $data): void { $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', @@ -622,7 +622,7 @@ class DatabasesCustomServerTest extends Scope public function testUpdateCollection(array $data) { $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $collection = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', @@ -657,7 +657,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Encrypted Actors Data', 'permissions' => [ Permission::read(Role::any()), @@ -719,7 +719,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'firstName' => 'Jonah', 'lastName' => 'Jameson', @@ -767,7 +767,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Actors', 'permissions' => [ Permission::read(Role::any()), @@ -820,7 +820,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'firstName' => 'lorem', 'lastName' => 'ipsum', @@ -898,7 +898,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($collection['body']['columns'][1]['key'], $lastName['body']['key']); return [ - 'collectionId' => $actors['body']['$id'], + 'tableId' => $actors['body']['$id'], 'key' => $index['body']['key'], 'databaseId' => $databaseId ]; @@ -910,7 +910,7 @@ class DatabasesCustomServerTest extends Scope public function testDeleteIndex($data): array { $databaseId = $data['databaseId']; - $index = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/indexes/' . $data['key'], array_merge([ + $index = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/indexes/' . $data['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -921,7 +921,7 @@ class DatabasesCustomServerTest extends Scope // Wait for database worker to finish deleting index sleep(2); - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['collectionId'], array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['tableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -938,7 +938,7 @@ class DatabasesCustomServerTest extends Scope public function testDeleteIndexOnDeleteAttribute($data) { $databaseId = $data['databaseId']; - $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/string', array_merge([ + $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -948,7 +948,7 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/string', array_merge([ + $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -965,7 +965,7 @@ class DatabasesCustomServerTest extends Scope sleep(2); - $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/indexes', array_merge([ + $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -976,7 +976,7 @@ class DatabasesCustomServerTest extends Scope 'orders' => ['ASC', 'ASC'], ]); - $index2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/indexes', array_merge([ + $index2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -994,7 +994,7 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Expected behavior: deleting attribute2 will cause index2 to be dropped, and index1 rebuilt with a single key - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/' . $attribute2['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/attributes/' . $attribute2['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1005,7 +1005,7 @@ class DatabasesCustomServerTest extends Scope // wait for database worker to complete sleep(2); - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['collectionId'], array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['tableId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1020,7 +1020,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($attribute1['body']['key'], $collection['body']['indexes'][0]['columns'][0]); // Delete attribute - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/' . $attribute1['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/attributes/' . $attribute1['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1050,7 +1050,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'TestCleanupDuplicateIndexOnDeleteAttribute', 'permissions' => [ Permission::read(Role::any()), @@ -1163,14 +1163,14 @@ class DatabasesCustomServerTest extends Scope public function testDeleteCollection($data) { $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; // Add Documents to the collection $document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'firstName' => 'Tom', 'lastName' => 'Holland', @@ -1186,7 +1186,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'firstName' => 'Samuel', 'lastName' => 'Jackson', @@ -1249,7 +1249,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Collection1', 'documentSecurity' => false, 'permissions' => [], @@ -1260,7 +1260,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Collection2', 'documentSecurity' => false, 'permissions' => [], @@ -1274,7 +1274,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'relatedCollectionId' => $collection2, + 'relatedTableId' => $collection2, 'type' => Database::RELATION_MANY_TO_ONE, 'twoWay' => false, 'key' => 'collection2' @@ -1318,7 +1318,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::custom('attributeRowWidthLimit'), + 'tableId' => ID::custom('attributeRowWidthLimit'), 'name' => 'attributeRowWidthLimit', 'permissions' => [ Permission::read(Role::any()), @@ -1384,7 +1384,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::custom('testLimitException'), + 'tableId' => ID::custom('testLimitException'), 'name' => 'testLimitException', 'permissions' => [ Permission::read(Role::any()), @@ -1508,7 +1508,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::custom('updateAttributes'), + 'tableId' => ID::custom('updateAttributes'), 'name' => 'updateAttributes' ]); @@ -1642,7 +1642,7 @@ class DatabasesCustomServerTest extends Scope return [ 'databaseId' => $databaseId, - 'collectionId' => $collectionId + 'tableId' => $collectionId ]; } @@ -1653,7 +1653,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'string'; $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ 'content-type' => 'application/json', @@ -1795,7 +1795,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'email'; $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ 'content-type' => 'application/json', @@ -1938,7 +1938,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'ip'; $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2080,7 +2080,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'url'; $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2222,7 +2222,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'integer'; $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2483,7 +2483,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'float'; $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2744,7 +2744,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'boolean'; $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2886,7 +2886,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'datetime'; $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ 'content-type' => 'application/json', @@ -3028,7 +3028,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'enum'; $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', @@ -3244,7 +3244,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'string'; $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $document = $this->client->call( Client::METHOD_POST, @@ -3255,7 +3255,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => 'unique()', + 'rowId' => 'unique()', 'data' => [ 'string' => 'string' ], @@ -3287,7 +3287,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => 'unique()', + 'rowId' => 'unique()', 'data' => [ 'string' => str_repeat('a', 2048) ], @@ -3373,7 +3373,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => 'unique()', + 'rowId' => 'unique()', 'data' => [ 'string' => str_repeat('a', 10) ], @@ -3408,7 +3408,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => 'unique()', + 'rowId' => 'unique()', 'data' => [ 'string' => str_repeat('a', 11) ], @@ -3426,7 +3426,7 @@ class DatabasesCustomServerTest extends Scope public function testAttributeUpdateNotFound(array $data) { $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $attributes = [ 'string' => [ @@ -3514,7 +3514,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'string'; $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; // Create document to test against $document = $this->client->call( @@ -3526,7 +3526,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => 'unique()', + 'rowId' => 'unique()', 'data' => [ 'string' => 'string' ], @@ -3578,7 +3578,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => 'unique()', + 'rowId' => 'unique()', 'data' => [ 'new_string' => 'string' ], @@ -3600,7 +3600,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => 'unique()', + 'rowId' => 'unique()', 'data' => [ 'string' => 'string' ], @@ -3630,7 +3630,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => 'collection1', + 'tableId' => 'collection1', 'name' => 'level1', 'documentSecurity' => false, 'permissions' => [ @@ -3646,7 +3646,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => 'collection2', + 'tableId' => 'collection2', 'name' => 'level2', 'documentSecurity' => false, 'permissions' => [ @@ -3684,7 +3684,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection2Id, + 'relatedTableId' => $collection2Id, 'type' => 'oneToMany', 'twoWay' => true, 'onDelete' => 'cascade', @@ -3712,7 +3712,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => 'unique()', + 'rowId' => 'unique()', 'data' => [ 'level2' => [[ '$id' => 'unique()', @@ -3794,7 +3794,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection2Id, + 'relatedTableId' => $collection2Id, 'type' => 'oneToOne', 'twoWay' => true, 'onDelete' => 'cascade', @@ -3822,7 +3822,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => 'unique()', + 'rowId' => 'unique()', 'data' => [ 'level2' => [ '$id' => 'unique()', @@ -3904,7 +3904,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection2Id, + 'relatedTableId' => $collection2Id, 'type' => 'manyToOne', 'twoWay' => true, 'onDelete' => 'cascade', @@ -3932,7 +3932,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => 'unique()', + 'rowId' => 'unique()', 'data' => [ 'level2' => [ '$id' => 'unique()', @@ -4014,7 +4014,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedCollectionId' => $collection2Id, + 'relatedTableId' => $collection2Id, 'type' => 'manyToOne', 'twoWay' => true, 'onDelete' => 'cascade', @@ -4042,7 +4042,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'documentId' => 'unique()', + 'rowId' => 'unique()', 'data' => [ 'level2' => [ '$id' => 'unique()', diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php index 9e20e13c2a..64413c2fab 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php @@ -32,7 +32,7 @@ class DatabasesPermissionsGuestTest extends Scope $databaseId = $database['body']['$id']; $publicMovies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::read(Role::any()), @@ -42,7 +42,7 @@ class DatabasesPermissionsGuestTest extends Scope ], ]); $privateMovies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Movies', 'permissions' => [], 'documentSecurity' => true, @@ -94,14 +94,14 @@ class DatabasesPermissionsGuestTest extends Scope $databaseId = $data['databaseId']; $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', $this->getServerHeader(), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], 'permissions' => $permissions, ]); $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents', $this->getServerHeader(), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], @@ -152,7 +152,7 @@ class DatabasesPermissionsGuestTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ] @@ -165,7 +165,7 @@ class DatabasesPermissionsGuestTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], @@ -175,7 +175,7 @@ class DatabasesPermissionsGuestTest extends Scope // Create a document in private collection with API key so we can test that update and delete are also not allowed $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents', $this->getServerHeader(), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], @@ -241,7 +241,7 @@ class DatabasesPermissionsGuestTest extends Scope $databaseId = $database['body']['$id']; $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::create(Role::any()), @@ -263,7 +263,7 @@ class DatabasesPermissionsGuestTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Thor: Ragnarok', ], diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php index 239fa58c99..2b959344fe 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php @@ -125,7 +125,7 @@ class DatabasesPermissionsMemberTest extends Scope $databaseId = $db['body']['$id']; $public = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::read(Role::any()), @@ -146,7 +146,7 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(202, $response['headers']['status-code']); $private = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Private Movies', 'permissions' => [ Permission::read(Role::users()), @@ -167,7 +167,7 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(202, $response['headers']['status-code']); $doconly = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Document Only Movies', 'permissions' => [], 'documentSecurity' => true, @@ -203,7 +203,7 @@ class DatabasesPermissionsMemberTest extends Scope $databaseId = $data['databaseId']; $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['public'] . '/documents', $this->getServerHeader(), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], @@ -212,7 +212,7 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['private'] . '/documents', $this->getServerHeader(), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], @@ -221,7 +221,7 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['doconly'] . '/documents', $this->getServerHeader(), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php index 9b0a04ac27..5a160a25b8 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php @@ -45,7 +45,7 @@ class DatabasesPermissionsTeamTest extends Scope $this->assertEquals(201, $db['headers']['status-code']); $collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections', $this->getServerHeader(), [ - 'collectionId' => ID::custom('collection1'), + 'tableId' => ID::custom('collection1'), 'name' => 'Collection 1', 'permissions' => [ Permission::read(Role::team($teams['team1']['$id'])), @@ -64,7 +64,7 @@ class DatabasesPermissionsTeamTest extends Scope ]); $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections', $this->getServerHeader(), [ - 'collectionId' => ID::custom('collection2'), + 'tableId' => ID::custom('collection2'), 'name' => 'Collection 2', 'permissions' => [ Permission::read(Role::team($teams['team2']['$id'])), @@ -141,7 +141,7 @@ class DatabasesPermissionsTeamTest extends Scope $this->createCollections($this->teams); $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $this->collections['collection1'] . '/documents', $this->getServerHeader(), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], @@ -149,7 +149,7 @@ class DatabasesPermissionsTeamTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $this->collections['collection2'] . '/documents', $this->getServerHeader(), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Ipsum', ], @@ -192,7 +192,7 @@ class DatabasesPermissionsTeamTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users[$user]['session'], ], [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'title' => 'Ipsum', ], diff --git a/tests/e2e/Services/GraphQL/AbuseTest.php b/tests/e2e/Services/GraphQL/AbuseTest.php index 7137123757..10b8421b04 100644 --- a/tests/e2e/Services/GraphQL/AbuseTest.php +++ b/tests/e2e/Services/GraphQL/AbuseTest.php @@ -30,7 +30,7 @@ class AbuseTest extends Scope { $data = $this->createCollection(); $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_ROW); $max = 120; @@ -40,8 +40,8 @@ class AbuseTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $databaseId, - 'collectionId' => $collectionId, - 'documentId' => ID::unique(), + 'tableId' => $collectionId, + 'rowId' => ID::unique(), 'data' => [ 'name' => 'John Doe', ], @@ -73,7 +73,7 @@ class AbuseTest extends Scope 'password' => 'password', 'databaseId' => 'database', 'databaseName' => 'database', - 'collectionId' => 'collection', + 'tableId' => 'collection', 'collectionName' => 'collection', 'collectionPermissions' => [ Permission::read(Role::users()), @@ -138,7 +138,7 @@ class AbuseTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $databaseId, - 'collectionId' => 'actors', + 'tableId' => 'actors', 'name' => 'Actors', 'documentSecurity' => false, 'permissions' => [ @@ -161,7 +161,7 @@ class AbuseTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $databaseId, - 'collectionId' => $collectionId, + 'tableId' => $collectionId, 'key' => 'name', 'size' => 256, 'required' => true, @@ -178,7 +178,7 @@ class AbuseTest extends Scope return [ 'databaseId' => $databaseId, - 'collectionId' => $collectionId, + 'tableId' => $collectionId, ]; } } diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 7c91cf67f7..22112d2e12 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -672,7 +672,7 @@ trait Base return 'query getRow($databaseId: String!, $tableId: String!, $rowId: String!) { databasesGetRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId) { _id - _collectionId + _tableId _permissions data } @@ -683,7 +683,7 @@ trait Base total rows { _id - _collectionId + _tableId _permissions data } @@ -693,7 +693,7 @@ trait Base return 'mutation createRow($databaseId: String!, $tableId: String!, $rowId: String!, $data: Json!, $permissions: [String!]){ databasesCreateRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId, data: $data, permissions: $permissions) { _id - _collectionId + _tableId _permissions } }'; @@ -760,7 +760,7 @@ trait Base return 'mutation updateRow($databaseId: String!, $tableId: String!, $rowId: String!, $data: Json!, $permissions: [String!]){ databasesUpdateRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId, data: $data, permissions: $permissions) { _id - _collectionId + _tableId data } }'; diff --git a/tests/e2e/Services/Migrations/MigrationsBase.php b/tests/e2e/Services/Migrations/MigrationsBase.php index 208bd58731..a40a2156ea 100644 --- a/tests/e2e/Services/Migrations/MigrationsBase.php +++ b/tests/e2e/Services/Migrations/MigrationsBase.php @@ -445,7 +445,7 @@ trait MigrationsBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Test Collection', ]); @@ -536,7 +536,7 @@ trait MigrationsBase return [ 'databaseId' => $databaseId, - 'collectionId' => $collectionId, + 'tableId' => $collectionId, ]; } @@ -546,14 +546,14 @@ trait MigrationsBase public function testAppwriteMigrationDatabasesDocument(array $data): void { $databaseId = $data['databaseId']; - $collectionId = $data['collectionId']; + $collectionId = $data['tableId']; $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'name' => 'Test Document', ] @@ -927,7 +927,7 @@ trait MigrationsBase 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test collection', - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -1131,7 +1131,7 @@ trait MigrationsBase return [ 'databaseId' => $databaseId, - 'collectionId' => $collectionId, + 'tableId' => $collectionId, 'migrationId' => $migration['body']['$id'], ]; } @@ -1142,7 +1142,7 @@ trait MigrationsBase public function testImportSuccessful(array $response): void { $databaseId = $response['databaseId']; - $collectionId = $response['collectionId']; + $collectionId = $response['tableId']; $migrationId = $response['migrationId']; $documentsCountInCSV = 100; diff --git a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php index a206692ea2..bb21ef8619 100644 --- a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php @@ -162,7 +162,7 @@ class RealtimeConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Actors', 'permissions' => [ Permission::read(Role::any()), @@ -272,7 +272,7 @@ class RealtimeConsoleClientTest extends Scope ], $this->getHeaders()), [ 'key' => 'key_name', 'type' => 'key', - 'attributes' => [ + 'columns' => [ 'name', ], ]); diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index d279bb45c7..671bc491f4 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -714,7 +714,7 @@ class RealtimeCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Actors', 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), @@ -749,7 +749,7 @@ class RealtimeCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'name' => 'Chris Evans' ], @@ -795,7 +795,7 @@ class RealtimeCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'name' => 'Chris Evans 2' ], @@ -840,7 +840,7 @@ class RealtimeCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'name' => 'Bradley Cooper' ], @@ -934,7 +934,7 @@ class RealtimeCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Actors', 'permissions' => [ Permission::read(Role::any()), @@ -971,7 +971,7 @@ class RealtimeCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'name' => 'Chris Evans' ], @@ -1053,7 +1053,7 @@ class RealtimeCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'name' => 'Bradley Cooper' ], diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index 5cd95c220d..feb43d17ab 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -61,7 +61,7 @@ trait WebhooksBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Actors', 'permissions' => [ Permission::read(Role::any()), @@ -211,7 +211,7 @@ trait WebhooksBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'firstName' => 'Chris', 'lastName' => 'Evans', @@ -254,7 +254,7 @@ trait WebhooksBase $this->assertIsArray($webhook['data']['$permissions']); $this->assertCount(3, $webhook['data']['$permissions']); - $data['documentId'] = $document['body']['$id']; + $data['rowId'] = $document['body']['$id']; return $data; } @@ -270,7 +270,7 @@ trait WebhooksBase /** * Test for SUCCESS */ - $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $data['documentId'], array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $data['rowId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -335,7 +335,7 @@ trait WebhooksBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), + 'rowId' => ID::unique(), 'data' => [ 'firstName' => 'Bradly', 'lastName' => 'Cooper', @@ -1119,7 +1119,7 @@ trait WebhooksBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'newCollection' . $i, 'permissions' => [ Permission::read(Role::any()), diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php index 14188a807b..83a29b741f 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php @@ -79,7 +79,7 @@ class WebhooksCustomServerTest extends Scope ]), [ 'key' => 'fullname', 'type' => 'key', - 'attributes' => ['lastName', 'firstName'], + 'columns' => ['lastName', 'firstName'], 'orders' => ['ASC', 'ASC'], ]); @@ -159,7 +159,7 @@ class WebhooksCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'collectionId' => ID::unique(), + 'tableId' => ID::unique(), 'name' => 'Demo', 'permissions' => [ Permission::read(Role::any()), From 253c428ca226de5c777f87d56f6877ec3d42949d Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 11:30:15 +0530 Subject: [PATCH 058/343] remove: filter. --- app/controllers/general.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index f07fb2f178..6f46f529ce 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -18,7 +18,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Transformation\Adapter\Preview; use Appwrite\Transformation\Transformation; use Appwrite\Utopia\Request; -use Appwrite\Utopia\Request\Filters\DatabaseAliases; use Appwrite\Utopia\Request\Filters\V16 as RequestV16; use Appwrite\Utopia\Request\Filters\V17 as RequestV17; use Appwrite\Utopia\Request\Filters\V18 as RequestV18; @@ -835,9 +834,6 @@ App::init() } } - // process on all databases endpoints! - $request->addFilter(new DatabaseAliases()); - $domain = $request->getHostname(); $domains = Config::getParam('domains', []); if (!array_key_exists($domain, $domains)) { From 3a8f097c173c2860aeb2b7f454839cf4545c678f Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 11:31:05 +0530 Subject: [PATCH 059/343] fix: realtime channels; update: row model. --- src/Appwrite/Messaging/Adapter/Realtime.php | 4 ++-- src/Appwrite/Utopia/Response/Model/Row.php | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index 400589f677..2657ecccaa 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -312,8 +312,8 @@ class Realtime extends Adapter } $channels[] = 'rows'; - $channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$collectionId') . '.rows'; - $channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$collectionId') . '.rows.' . $payload->getId(); + $channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$tableId') . '.rows'; + $channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$tableId') . '.rows.' . $payload->getId(); $roles = $table->getAttribute('documentSecurity', false) ? \array_merge($table->getRead(), $payload->getRead()) diff --git a/src/Appwrite/Utopia/Response/Model/Row.php b/src/Appwrite/Utopia/Response/Model/Row.php index 49325bdc81..c84a81738d 100644 --- a/src/Appwrite/Utopia/Response/Model/Row.php +++ b/src/Appwrite/Utopia/Response/Model/Row.php @@ -36,7 +36,7 @@ class Row extends Any 'default' => '', 'example' => '5e5ea5c16897e', ]) - ->addRule('$collectionId', [ + ->addRule('$tableId', [ 'type' => self::TYPE_STRING, 'description' => 'Table ID.', 'default' => '', @@ -75,6 +75,11 @@ class Row extends Any $document->removeAttribute('$collection'); $document->removeAttribute('$tenant'); + $collectionId = $document->getAttribute('$collectionId'); + $document + ->removeAttribute('$collectionId') + ->setAttribute('$tableId', $collectionId); + foreach ($document->getAttributes() as $column) { if (\is_array($column)) { foreach ($column as $subAttribute) { From 86d195c1c0a49d7c351dac4e9dfd9be4defb9f7c Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 11:31:35 +0530 Subject: [PATCH 060/343] update: request, response filters. --- src/Appwrite/Utopia/Request/Filters/V19.php | 32 +++++++++++++++----- src/Appwrite/Utopia/Response/Filters/V19.php | 2 ++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/Appwrite/Utopia/Request/Filters/V19.php b/src/Appwrite/Utopia/Request/Filters/V19.php index ee04cea038..01d2da01a2 100644 --- a/src/Appwrite/Utopia/Request/Filters/V19.php +++ b/src/Appwrite/Utopia/Request/Filters/V19.php @@ -6,20 +6,36 @@ use Appwrite\Utopia\Request\Filter; class V19 extends Filter { + // Map old params to new + private const PARAMS_MAP = [ + 'documentId' => 'rowId', + 'attributes' => 'columns', + 'collectionId' => 'tableId', + 'attributeId' => 'columnId', + '$collectionId' => '$tableId', + 'relatedCollection' => 'relatedTable', + 'relatedCollectionId' => 'relatedTableId', + ]; + // Convert 1.6 params to 1.7 public function parse(array $content, string $model): array { - return match ($model) { - 'databases.createRelationshipColumn' => $this->convertV16RelationshipParams($content), - default => $content - }; + $content = $this->overrideDatabaseParams($content, $model); + + return $content; } - protected function convertV16RelationshipParams(array $content): array + protected function overrideDatabaseParams(array $content, string $model): array { - if (isset($content['relatedCollectionId'])) { - $content['relatedTableId'] = $content['relatedCollectionId']; - unset($content['relatedCollectionId']); + if (!str_starts_with($model, 'databases.')) { + return $content; + } + + $intersect = array_intersect_key(self::PARAMS_MAP, $content); + + foreach ($intersect as $oldKey => $newKey) { + $content[$newKey] = $content[$oldKey]; + unset($content[$oldKey]); } return $content; diff --git a/src/Appwrite/Utopia/Response/Filters/V19.php b/src/Appwrite/Utopia/Response/Filters/V19.php index 5e1a7e40e7..24cb07889f 100644 --- a/src/Appwrite/Utopia/Response/Filters/V19.php +++ b/src/Appwrite/Utopia/Response/Filters/V19.php @@ -10,8 +10,10 @@ class V19 extends Filter private const DATABASE_MAPPINGS = [ 'table' => 'collection', 'tables' => 'collections', + '$tableId' => '$collectionId', 'tablesTotal' => 'collectionsTotal', 'relatedTable' => 'relatedCollection', + 'relatedTableId' => 'relatedCollectionId', 'column' => 'attribute', 'columns' => 'attributes', From 9ec897f7d606ca7c431655a0fadbfe9e3f14ff63 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 12:05:06 +0530 Subject: [PATCH 061/343] fix: filtering --- src/Appwrite/Utopia/Response/Model/Row.php | 10 +++--- .../e2e/Services/Databases/DatabasesBase.php | 31 ++++++++++--------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/Appwrite/Utopia/Response/Model/Row.php b/src/Appwrite/Utopia/Response/Model/Row.php index c84a81738d..c30984ab7a 100644 --- a/src/Appwrite/Utopia/Response/Model/Row.php +++ b/src/Appwrite/Utopia/Response/Model/Row.php @@ -75,10 +75,12 @@ class Row extends Any $document->removeAttribute('$collection'); $document->removeAttribute('$tenant'); - $collectionId = $document->getAttribute('$collectionId'); - $document - ->removeAttribute('$collectionId') - ->setAttribute('$tableId', $collectionId); + $collectionId = $document->getAttribute('$collectionId', ''); + if (!empty($collectionId)) { + $document + ->removeAttribute('$collectionId') + ->setAttribute('$tableId', $collectionId); + } foreach ($document->getAttributes() as $column) { if (\is_array($column)) { diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 3df5dd4387..186f906252 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -1542,7 +1542,7 @@ trait DatabasesBase ]); $this->assertEquals(201, $document1['headers']['status-code']); - $this->assertEquals($data['moviesId'], $document1['body']['$collectionId']); + $this->assertEquals($data['moviesId'], $document1['body']['$tableId']); $this->assertArrayNotHasKey('$collection', $document1['body']); $this->assertEquals($databaseId, $document1['body']['$databaseId']); $this->assertEquals($document1['body']['title'], 'Captain America'); @@ -1555,7 +1555,7 @@ trait DatabasesBase $this->assertEquals($document1['body']['birthDay'], '1975-06-12T12:12:55.000+00:00'); $this->assertEquals(201, $document2['headers']['status-code']); - $this->assertEquals($data['moviesId'], $document2['body']['$collectionId']); + $this->assertEquals($data['moviesId'], $document2['body']['$tableId']); $this->assertArrayNotHasKey('$collection', $document2['body']); $this->assertEquals($databaseId, $document2['body']['$databaseId']); $this->assertEquals($document2['body']['title'], 'Spider-Man: Far From Home'); @@ -1572,7 +1572,7 @@ trait DatabasesBase $this->assertEquals($document2['body']['integers'][1], 60); $this->assertEquals(201, $document3['headers']['status-code']); - $this->assertEquals($data['moviesId'], $document3['body']['$collectionId']); + $this->assertEquals($data['moviesId'], $document3['body']['$tableId']); $this->assertArrayNotHasKey('$collection', $document3['body']); $this->assertEquals($databaseId, $document3['body']['$databaseId']); $this->assertEquals($document3['body']['title'], 'Spider-Man: Homecoming'); @@ -1621,7 +1621,8 @@ trait DatabasesBase $this->assertCount(3, $documents['body']['rows']); foreach ($documents['body']['rows'] as $document) { - $this->assertEquals($data['moviesId'], $document['$collectionId']); + print_r($document); + $this->assertEquals($data['moviesId'], $document['$tableId']); $this->assertArrayNotHasKey('$collection', $document); $this->assertEquals($databaseId, $document['$databaseId']); } @@ -1696,14 +1697,14 @@ trait DatabasesBase { $databaseId = $data['databaseId']; foreach ($data['rows'] as $document) { - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$tableId'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals($response['body']['$id'], $document['$id']); - $this->assertEquals($document['$collectionId'], $response['body']['$collectionId']); + $this->assertEquals($document['$tableId'], $response['body']['$tableId']); $this->assertArrayNotHasKey('$collection', $response['body']); $this->assertEquals($document['$databaseId'], $response['body']['$databaseId']); $this->assertEquals($response['body']['title'], $document['title']); @@ -1723,7 +1724,7 @@ trait DatabasesBase $databaseId = $data['databaseId']; $document = $data['rows'][0]; - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$tableId'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -2305,7 +2306,7 @@ trait DatabasesBase $id = $document['body']['$id']; $this->assertEquals(201, $document['headers']['status-code']); - $this->assertEquals($data['moviesId'], $document['body']['$collectionId']); + $this->assertEquals($data['moviesId'], $document['body']['$tableId']); $this->assertArrayNotHasKey('$collection', $document['body']); $this->assertEquals($databaseId, $document['body']['$databaseId']); $this->assertEquals($document['body']['title'], 'Thor: Ragnaroc'); @@ -2333,7 +2334,7 @@ trait DatabasesBase $this->assertEquals(200, $document['headers']['status-code']); $this->assertEquals($document['body']['$id'], $id); - $this->assertEquals($data['moviesId'], $document['body']['$collectionId']); + $this->assertEquals($data['moviesId'], $document['body']['$tableId']); $this->assertArrayNotHasKey('$collection', $document['body']); $this->assertEquals($databaseId, $document['body']['$databaseId']); $this->assertEquals($document['body']['title'], 'Thor: Ragnarok'); @@ -2350,7 +2351,7 @@ trait DatabasesBase $id = $document['body']['$id']; $this->assertEquals(200, $document['headers']['status-code']); - $this->assertEquals($data['moviesId'], $document['body']['$collectionId']); + $this->assertEquals($data['moviesId'], $document['body']['$tableId']); $this->assertArrayNotHasKey('$collection', $document['body']); $this->assertEquals($databaseId, $document['body']['$databaseId']); $this->assertEquals($document['body']['title'], 'Thor: Ragnarok'); @@ -4000,8 +4001,8 @@ trait DatabasesBase $this->assertEquals($databaseId, $person1['body']['$databaseId']); $this->assertEquals($databaseId, $person1['body']['library']['$databaseId']); - $this->assertEquals($person['body']['$id'], $person1['body']['$collectionId']); - $this->assertEquals($library['body']['$id'], $person1['body']['library']['$collectionId']); + $this->assertEquals($person['body']['$id'], $person1['body']['$tableId']); + $this->assertEquals($library['body']['$id'], $person1['body']['library']['$tableId']); $this->assertArrayNotHasKey('$collection', $person1['body']); $this->assertArrayNotHasKey('$collection', $person1['body']['library']); @@ -4562,7 +4563,7 @@ trait DatabasesBase $this->assertEquals(null, $response['body']['rows'][0]['fullName']); $this->assertArrayNotHasKey("libraries", $response['body']['rows'][0]); $this->assertArrayNotHasKey('$databaseId', $response['body']['rows'][0]); - $this->assertArrayNotHasKey('$collectionId', $response['body']['rows'][0]); + $this->assertArrayNotHasKey('$tableId', $response['body']['rows'][0]); } /** @@ -4583,7 +4584,7 @@ trait DatabasesBase $this->assertEquals(200, $response['headers']['status-code']); $this->assertArrayNotHasKey('libraries', $response['body']['rows'][0]); $this->assertArrayNotHasKey('$databaseId', $response['body']['rows'][0]); - $this->assertArrayNotHasKey('$collectionId', $response['body']['rows'][0]); + $this->assertArrayNotHasKey('$tableId', $response['body']['rows'][0]); $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -4597,7 +4598,7 @@ trait DatabasesBase $this->assertEquals(200, $response['headers']['status-code']); $this->assertArrayHasKey('libraries', $document); $this->assertArrayNotHasKey('$databaseId', $document); - $this->assertArrayNotHasKey('$collectionId', $document); + $this->assertArrayNotHasKey('$tableId', $document); $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', From b1735ef9452a9a16baaa55d4fe6c488b3149dcb5 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 12:14:54 +0530 Subject: [PATCH 062/343] remove: aliasing filter. --- .../Request/Filters/DatabaseAliases.php | 39 ------------------- 1 file changed, 39 deletions(-) delete mode 100644 src/Appwrite/Utopia/Request/Filters/DatabaseAliases.php diff --git a/src/Appwrite/Utopia/Request/Filters/DatabaseAliases.php b/src/Appwrite/Utopia/Request/Filters/DatabaseAliases.php deleted file mode 100644 index 0ee2754475..0000000000 --- a/src/Appwrite/Utopia/Request/Filters/DatabaseAliases.php +++ /dev/null @@ -1,39 +0,0 @@ - 'rowId', - 'attributes' => 'columns', - 'collectionId' => 'tableId', - 'attributeId' => 'columnId', - 'relatedCollection' => 'relatedTable', - 'relatedCollectionId' => 'relatedTableId', - ]; - - public function parse(array $content, string $model): array - { - return $this->overrideDatabaseParams($content, $model); - } - - protected function overrideDatabaseParams(array $content, string $model): array - { - if (!str_starts_with($model, 'databases.')) { - return $content; - } - - $intersect = array_intersect_key(self::PARAMS_MAP, $content); - - foreach ($intersect as $oldKey => $newKey) { - $content[$newKey] = $content[$oldKey]; - unset($content[$oldKey]); - } - - return $content; - } -} From d70d001f5ab14a9d4b4437ea67d29d0797ef797a Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 12:52:05 +0530 Subject: [PATCH 063/343] add: backported channels. --- src/Appwrite/Messaging/Adapter/Realtime.php | 6 ++++++ .../Services/Realtime/RealtimeCustomClientTest.php | 12 ++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index 2657ecccaa..b775078c61 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -311,10 +311,16 @@ class Realtime extends Adapter throw new \Exception('Table needs to be passed to Realtime for Row events in the Database.'); } + // 1.7.x $channels[] = 'rows'; $channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$tableId') . '.rows'; $channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$tableId') . '.rows.' . $payload->getId(); + // 1.6.x + $channels[] = 'documents'; + $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$tableId') . '.documents'; + $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$tableId') . '.documents.' . $payload->getId(); + $roles = $table->getAttribute('documentSecurity', false) ? \array_merge($table->getRead(), $payload->getRead()) : $table->getRead(); diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index 671bc491f4..eef7978a0e 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -769,7 +769,7 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(3, $response['data']['channels']); + $this->assertCount(6, $response['data']['channels']); // includes old and new channels $this->assertContains('rows', $response['data']['channels']); $this->assertContains('databases.' . $databaseId . '.tables.' . $actorsId . '.rows.' . $documentId, $response['data']['channels']); $this->assertContains('databases.' . $databaseId . '.tables.' . $actorsId . '.rows', $response['data']['channels']); @@ -813,7 +813,7 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(3, $response['data']['channels']); + $this->assertCount(6, $response['data']['channels']); // includes old and new channels $this->assertContains('rows', $response['data']['channels']); $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); @@ -867,7 +867,7 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(3, $response['data']['channels']); + $this->assertCount(6, $response['data']['channels']); // includes old and new channels $this->assertContains('rows', $response['data']['channels']); $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); @@ -987,7 +987,7 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(3, $response['data']['channels']); + $this->assertCount(6, $response['data']['channels']); // includes old and new channels $this->assertContains('rows', $response['data']['channels']); $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); @@ -1026,7 +1026,7 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(3, $response['data']['channels']); + $this->assertCount(6, $response['data']['channels']); // includes old and new channels $this->assertContains('rows', $response['data']['channels']); $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); @@ -1076,7 +1076,7 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(3, $response['data']['channels']); + $this->assertCount(6, $response['data']['channels']); // includes old and new channels $this->assertContains('rows', $response['data']['channels']); $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); From 59e5ce0664e3bbe039e307acbc70c192610f68fe Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 16:44:19 +0530 Subject: [PATCH 064/343] update: `collections` <> `tables` errors. --- app/config/errors.php | 20 +++++++++---------- app/controllers/general.php | 2 +- src/Appwrite/Extend/Exception.php | 6 +++--- .../Modules/Databases/Http/Columns/Action.php | 6 +++--- .../Modules/Databases/Http/Columns/Delete.php | 4 ++-- .../Modules/Databases/Http/Columns/Get.php | 2 +- .../Http/Columns/Relationship/Create.php | 4 ++-- .../Modules/Databases/Http/Columns/XList.php | 2 +- .../Modules/Databases/Http/Indexes/Create.php | 2 +- .../Modules/Databases/Http/Indexes/Delete.php | 2 +- .../Modules/Databases/Http/Indexes/Get.php | 2 +- .../Modules/Databases/Http/Indexes/XList.php | 2 +- .../Modules/Databases/Http/Rows/Create.php | 4 ++-- .../Modules/Databases/Http/Rows/Delete.php | 4 ++-- .../Modules/Databases/Http/Rows/Get.php | 2 +- .../Databases/Http/Rows/Logs/XList.php | 2 +- .../Modules/Databases/Http/Rows/Update.php | 4 ++-- .../Modules/Databases/Http/Rows/XList.php | 2 +- .../Modules/Databases/Http/Tables/Create.php | 4 ++-- .../Modules/Databases/Http/Tables/Delete.php | 2 +- .../Modules/Databases/Http/Tables/Get.php | 2 +- .../Databases/Http/Tables/Logs/XList.php | 2 +- .../Modules/Databases/Http/Tables/Update.php | 2 +- .../Databases/Http/Tables/Usage/Get.php | 2 +- .../Databases/DatabasesCustomServerTest.php | 2 +- 25 files changed, 44 insertions(+), 44 deletions(-) diff --git a/app/config/errors.php b/app/config/errors.php index 9d30170c2d..6923090ee1 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -657,20 +657,20 @@ return [ 'code' => 400, ], - /** Collections */ - Exception::COLLECTION_NOT_FOUND => [ - 'name' => Exception::COLLECTION_NOT_FOUND, - 'description' => 'Collection with the requested ID could not be found.', + /** Tables */ + Exception::TABLE_NOT_FOUND => [ + 'name' => Exception::TABLE_NOT_FOUND, + 'description' => 'Table with the requested ID could not be found.', 'code' => 404, ], - Exception::COLLECTION_ALREADY_EXISTS => [ - 'name' => Exception::COLLECTION_ALREADY_EXISTS, - 'description' => 'A collection with the requested ID already exists. Try again with a different ID or use ID.unique() to generate a unique ID.', + Exception::TABLE_ALREADY_EXISTS => [ + 'name' => Exception::TABLE_ALREADY_EXISTS, + 'description' => 'A table with the requested ID already exists. Try again with a different ID or use ID.unique() to generate a unique ID.', 'code' => 409, ], - Exception::COLLECTION_LIMIT_EXCEEDED => [ - 'name' => Exception::COLLECTION_LIMIT_EXCEEDED, - 'description' => 'The maximum number of collections has been reached.', + Exception::TABLE_LIMIT_EXCEEDED => [ + 'name' => Exception::TABLE_LIMIT_EXCEEDED, + 'description' => 'The maximum number of tables has been reached.', 'code' => 400, ], diff --git a/app/controllers/general.php b/app/controllers/general.php index 6f46f529ce..a0e707ea2f 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1185,7 +1185,7 @@ App::error() $error = new AppwriteException(AppwriteException::RELATIONSHIP_VALUE_INVALID, $error->getMessage(), previous: $error); break; case 'Utopia\Database\Exception\NotFound': - $error = new AppwriteException(AppwriteException::COLLECTION_NOT_FOUND, $error->getMessage(), previous: $error); + $error = new AppwriteException(AppwriteException::TABLE_NOT_FOUND, $error->getMessage(), previous: $error); break; case 'Utopia\Database\Exception\Dependency': $error = new AppwriteException(AppwriteException::INDEX_DEPENDENCY, null, previous: $error); diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 7df9134c9f..0ea0c16174 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -192,9 +192,9 @@ class Exception extends \Exception public const DATABASE_QUERY_ORDER_NULL = 'database_query_order_null'; /** Collections */ - public const COLLECTION_NOT_FOUND = 'collection_not_found'; - public const COLLECTION_ALREADY_EXISTS = 'collection_already_exists'; - public const COLLECTION_LIMIT_EXCEEDED = 'collection_limit_exceeded'; + public const TABLE_NOT_FOUND = 'table_not_found'; + public const TABLE_ALREADY_EXISTS = 'table_already_exists'; + public const TABLE_LIMIT_EXCEEDED = 'table_limit_exceeded'; /** Documents */ public const DOCUMENT_NOT_FOUND = 'document_not_found'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php index 70c26594a3..109844534b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php @@ -78,7 +78,7 @@ class Action extends UtopiaAction $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } if (!empty($format)) { @@ -100,7 +100,7 @@ class Action extends UtopiaAction $options['side'] = Database::RELATION_SIDE_PARENT; $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection'] ?? ''); if ($relatedTable->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND, 'The related table was not found.'); + throw new Exception(Exception::TABLE_NOT_FOUND, 'The related table was not found.'); } } @@ -229,7 +229,7 @@ class Action extends UtopiaAction $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $column = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php index 945097e66b..c4c681b080 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php @@ -81,7 +81,7 @@ class Delete extends Action $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $column = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); @@ -109,7 +109,7 @@ class Delete extends Action if ($options['twoWay']) { $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection']); if ($relatedTable->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $relatedColumn = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $options['twoWayKey']); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php index 160ab60868..091b778eb8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php @@ -75,7 +75,7 @@ class Get extends Action $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $column = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $table->getInternalId() . '_' . $key); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php index d063c8e055..9628d79a92 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php @@ -105,13 +105,13 @@ class Create extends ColumnAction $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId()); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $relatedTableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId); $relatedTable = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $relatedTableDocument->getInternalId()); if ($relatedTable->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $columns = $table->getAttribute('attributes', []); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php index e9800e71a0..2b212e2be3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php @@ -68,7 +68,7 @@ class XList extends Action $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $queries = Query::parseQueries($queries); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php index 49cb7157b0..1b45f58a2f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php @@ -85,7 +85,7 @@ class Create extends Action $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $count = $dbForProject->count('indexes', [ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Delete.php index eeb772e0c3..78e1799164 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Delete.php @@ -74,7 +74,7 @@ class Delete extends Action $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $index = $dbForProject->getDocument('indexes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Get.php index 72ab1a02b1..b1689481ed 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Get.php @@ -67,7 +67,7 @@ class Get extends Action $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $index = $table->find('key', $key, 'indexes'); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/XList.php index 4920b679c1..53c623f9f4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/XList.php @@ -73,7 +73,7 @@ class XList extends Action $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $queries = Query::parseQueries($queries); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php index 55efbc3632..adf481c1c4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php @@ -106,7 +106,7 @@ class Create extends Action $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $allowedPermissions = [ @@ -246,7 +246,7 @@ class Create extends Action } catch (DuplicateException) { throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); } catch (NotFoundException) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php index bba042bca5..16e16b7d73 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php @@ -84,7 +84,7 @@ class Delete extends Action $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } // Read permission should not be required for delete @@ -102,7 +102,7 @@ class Delete extends Action ); }); } catch (NotFoundException) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } // Add $tableId and $databaseId for all rows diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php index 85b6127bd3..f2da5e69f4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php @@ -79,7 +79,7 @@ class Get extends Action $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } try { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php index 02358be8f2..43e61c1434 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php @@ -81,7 +81,7 @@ class XList extends Action $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $row = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php index c9ed71d569..6de7e6ae92 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php @@ -101,7 +101,7 @@ class Update extends Action $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } // Read permission should not be required for update @@ -243,7 +243,7 @@ class Update extends Action } catch (StructureException $e) { throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); } catch (NotFoundException) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } // Add $tableId and $databaseId for all rows diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php index 4396c2b112..95410507bf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php @@ -79,7 +79,7 @@ class XList extends Action $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } try { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php index 9acd248190..dc3f7b8574 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php @@ -99,9 +99,9 @@ class Create extends Action $dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), permissions: $permissions, documentSecurity: $documentSecurity); } catch (DuplicateException) { - throw new Exception(Exception::COLLECTION_ALREADY_EXISTS); + throw new Exception(Exception::TABLE_ALREADY_EXISTS); } catch (LimitException) { - throw new Exception(Exception::COLLECTION_LIMIT_EXCEEDED); + throw new Exception(Exception::TABLE_LIMIT_EXCEEDED); } $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php index 6fe7228ed9..b7e8f6ecf7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php @@ -71,7 +71,7 @@ class Delete extends Action $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $tableId)) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php index 63bc1fa48c..4c76c1f89d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php @@ -66,7 +66,7 @@ class Get extends Action $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $response->dynamic($table, UtopiaResponse::MODEL_TABLE); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php index 44a850424f..1dba2493cf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php @@ -81,7 +81,7 @@ class XList extends Action $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $tableDocument->getInternalId()); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } try { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php index d5f8d388ab..f5621feab3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php @@ -77,7 +77,7 @@ class Update extends Action $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $permissions ??= $table->getPermissions() ?? []; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php index 4c591bff1a..b528fee7cf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php @@ -68,7 +68,7 @@ class Get extends Action $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $tableDocument->getInternalId()); if ($table->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + throw new Exception(Exception::TABLE_NOT_FOUND); } $periods = Config::getParam('usage', []); diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 508578f149..a5beb77bf3 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -3491,7 +3491,7 @@ class DatabasesCustomServerTest extends Scope ]), $payload); $this->assertEquals(404, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLLECTION_NOT_FOUND, $update['body']['type']); + $this->assertEquals(AppwriteException::TABLE_NOT_FOUND, $update['body']['type']); /** * Check if Attribute exists From 6e8dbfc6749bd44a53bbe4ad07dc8c27087f5554 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 16:48:04 +0530 Subject: [PATCH 065/343] update: `documents` <> `rows` errors. --- app/config/errors.php | 44 +++++++++---------- app/controllers/general.php | 8 ++-- src/Appwrite/Extend/Exception.php | 16 +++---- .../Modules/Databases/Http/Rows/Create.php | 8 ++-- .../Modules/Databases/Http/Rows/Delete.php | 2 +- .../Modules/Databases/Http/Rows/Get.php | 2 +- .../Databases/Http/Rows/Logs/XList.php | 2 +- .../Modules/Databases/Http/Rows/Update.php | 8 ++-- .../e2e/Services/Databases/DatabasesBase.php | 2 +- .../Databases/DatabasesCustomServerTest.php | 2 +- 10 files changed, 47 insertions(+), 47 deletions(-) diff --git a/app/config/errors.php b/app/config/errors.php index 6923090ee1..12d494faf6 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -674,40 +674,40 @@ return [ 'code' => 400, ], - /** Documents */ - Exception::DOCUMENT_NOT_FOUND => [ - 'name' => Exception::DOCUMENT_NOT_FOUND, - 'description' => 'Document with the requested ID could not be found.', + /** Rows */ + Exception::ROW_NOT_FOUND => [ + 'name' => Exception::ROW_NOT_FOUND, + 'description' => 'Row with the requested ID could not be found.', 'code' => 404, ], - Exception::DOCUMENT_INVALID_STRUCTURE => [ - 'name' => Exception::DOCUMENT_INVALID_STRUCTURE, - 'description' => 'The document structure is invalid. Please ensure the attributes match the collection definition.', + Exception::ROW_INVALID_STRUCTURE => [ + 'name' => Exception::ROW_INVALID_STRUCTURE, + 'description' => 'The row structure is invalid. Please ensure the columns match the table definition.', 'code' => 400, ], - Exception::DOCUMENT_MISSING_DATA => [ - 'name' => Exception::DOCUMENT_MISSING_DATA, - 'description' => 'The document data is missing. Try again with document data populated', + Exception::ROW_MISSING_DATA => [ + 'name' => Exception::ROW_MISSING_DATA, + 'description' => 'The row data is missing. Try again with row data populated', 'code' => 400, ], - Exception::DOCUMENT_MISSING_PAYLOAD => [ - 'name' => Exception::DOCUMENT_MISSING_PAYLOAD, - 'description' => 'The document data and permissions are missing. You must provide either document data or permissions to be updated.', + Exception::ROW_MISSING_PAYLOAD => [ + 'name' => Exception::ROW_MISSING_PAYLOAD, + 'description' => 'The row data and permissions are missing. You must provide either row data or permissions to be updated.', 'code' => 400, ], - Exception::DOCUMENT_ALREADY_EXISTS => [ - 'name' => Exception::DOCUMENT_ALREADY_EXISTS, - 'description' => 'Document with the requested ID already exists. Try again with a different ID or use ID.unique() to generate a unique ID.', + Exception::ROW_ALREADY_EXISTS => [ + 'name' => Exception::ROW_ALREADY_EXISTS, + 'description' => 'Row with the requested ID already exists. Try again with a different ID or use ID.unique() to generate a unique ID.', 'code' => 409, ], - Exception::DOCUMENT_UPDATE_CONFLICT => [ - 'name' => Exception::DOCUMENT_UPDATE_CONFLICT, - 'description' => 'Remote document is newer than local.', + Exception::ROW_UPDATE_CONFLICT => [ + 'name' => Exception::ROW_UPDATE_CONFLICT, + 'description' => 'Remote row is newer than local.', 'code' => 409, ], - Exception::DOCUMENT_DELETE_RESTRICTED => [ - 'name' => Exception::DOCUMENT_DELETE_RESTRICTED, - 'description' => 'Document cannot be deleted because it is referenced by another document.', + Exception::ROW_DELETE_RESTRICTED => [ + 'name' => Exception::ROW_DELETE_RESTRICTED, + 'description' => 'Row cannot be deleted because it is referenced by another document.', 'code' => 403, ], diff --git a/app/controllers/general.php b/app/controllers/general.php index a0e707ea2f..cc6739e790 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1161,7 +1161,7 @@ App::error() } break; case 'Utopia\Database\Exception\Conflict': - $error = new AppwriteException(AppwriteException::DOCUMENT_UPDATE_CONFLICT, previous: $error); + $error = new AppwriteException(AppwriteException::ROW_UPDATE_CONFLICT, previous: $error); break; case 'Utopia\Database\Exception\Timeout': $error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error); @@ -1170,13 +1170,13 @@ App::error() $error = new AppwriteException(AppwriteException::GENERAL_QUERY_INVALID, $error->getMessage(), previous: $error); break; case 'Utopia\Database\Exception\Structure': - $error = new AppwriteException(AppwriteException::DOCUMENT_INVALID_STRUCTURE, $error->getMessage(), previous: $error); + $error = new AppwriteException(AppwriteException::ROW_INVALID_STRUCTURE, $error->getMessage(), previous: $error); break; case 'Utopia\Database\Exception\Duplicate': - $error = new AppwriteException(AppwriteException::DOCUMENT_ALREADY_EXISTS); + $error = new AppwriteException(AppwriteException::ROW_ALREADY_EXISTS); break; case 'Utopia\Database\Exception\Restricted': - $error = new AppwriteException(AppwriteException::DOCUMENT_DELETE_RESTRICTED); + $error = new AppwriteException(AppwriteException::ROW_DELETE_RESTRICTED); break; case 'Utopia\Database\Exception\Authorization': $error = new AppwriteException(AppwriteException::USER_UNAUTHORIZED); diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 0ea0c16174..6468a774ce 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -196,14 +196,14 @@ class Exception extends \Exception public const TABLE_ALREADY_EXISTS = 'table_already_exists'; public const TABLE_LIMIT_EXCEEDED = 'table_limit_exceeded'; - /** Documents */ - public const DOCUMENT_NOT_FOUND = 'document_not_found'; - public const DOCUMENT_INVALID_STRUCTURE = 'document_invalid_structure'; - public const DOCUMENT_MISSING_DATA = 'document_missing_data'; - public const DOCUMENT_MISSING_PAYLOAD = 'document_missing_payload'; - public const DOCUMENT_ALREADY_EXISTS = 'document_already_exists'; - public const DOCUMENT_UPDATE_CONFLICT = 'document_update_conflict'; - public const DOCUMENT_DELETE_RESTRICTED = 'document_delete_restricted'; + /** Rows */ + public const ROW_NOT_FOUND = 'row_not_found'; + public const ROW_INVALID_STRUCTURE = 'row_invalid_structure'; + public const ROW_MISSING_DATA = 'row_missing_data'; + public const ROW_MISSING_PAYLOAD = 'row_missing_payload'; + public const ROW_ALREADY_EXISTS = 'row_already_exists'; + public const ROW_UPDATE_CONFLICT = 'row_update_conflict'; + public const ROW_DELETE_RESTRICTED = 'row_delete_restricted'; /** Attribute */ public const ATTRIBUTE_NOT_FOUND = 'attribute_not_found'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php index adf481c1c4..df36696d80 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php @@ -87,11 +87,11 @@ class Create extends Action $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array if (empty($data)) { - throw new Exception(Exception::DOCUMENT_MISSING_DATA); + throw new Exception(Exception::ROW_MISSING_DATA); } if (isset($data['$id'])) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is not allowed for creating new rows, try update instead'); + throw new Exception(Exception::ROW_INVALID_STRUCTURE, '$id is not allowed for creating new rows, try update instead'); } $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -242,9 +242,9 @@ class Create extends Action try { $row = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $row); } catch (StructureException $e) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); + throw new Exception(Exception::ROW_INVALID_STRUCTURE, $e->getMessage()); } catch (DuplicateException) { - throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); + throw new Exception(Exception::ROW_ALREADY_EXISTS); } catch (NotFoundException) { throw new Exception(Exception::TABLE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php index 16e16b7d73..8c68f23bfb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php @@ -91,7 +91,7 @@ class Delete extends Action $row = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); if ($row->isEmpty()) { - throw new Exception(Exception::DOCUMENT_NOT_FOUND); + throw new Exception(Exception::ROW_NOT_FOUND); } try { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php index f2da5e69f4..69127ca238 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php @@ -92,7 +92,7 @@ class Get extends Action } if ($row->isEmpty()) { - throw new Exception(Exception::DOCUMENT_NOT_FOUND); + throw new Exception(Exception::ROW_NOT_FOUND); } $operations = 0; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php index 43e61c1434..238815d849 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php @@ -87,7 +87,7 @@ class XList extends Action $row = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId); if ($row->isEmpty()) { - throw new Exception(Exception::DOCUMENT_NOT_FOUND); + throw new Exception(Exception::ROW_NOT_FOUND); } try { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php index 6de7e6ae92..7dcd1f8fcb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php @@ -86,7 +86,7 @@ class Update extends Action $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array if (empty($data) && \is_null($permissions)) { - throw new Exception(Exception::DOCUMENT_MISSING_PAYLOAD); + throw new Exception(Exception::ROW_MISSING_PAYLOAD); } $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -109,7 +109,7 @@ class Update extends Action $row = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); if ($row->isEmpty()) { - throw new Exception(Exception::DOCUMENT_NOT_FOUND); + throw new Exception(Exception::ROW_NOT_FOUND); } // Map aggregate permissions into the multiple permissions they represent. @@ -239,9 +239,9 @@ class Update extends Action } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } catch (DuplicateException) { - throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); + throw new Exception(Exception::ROW_ALREADY_EXISTS); } catch (StructureException $e) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); + throw new Exception(Exception::ROW_INVALID_STRUCTURE, $e->getMessage()); } catch (NotFoundException) { throw new Exception(Exception::TABLE_NOT_FOUND); } diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 186f906252..3c2a2c4186 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -2399,7 +2399,7 @@ trait DatabasesBase $this->assertEquals(409, $response['headers']['status-code']); $this->assertEquals('Remote document is newer than local.', $response['body']['message']); - $this->assertEquals(Exception::DOCUMENT_UPDATE_CONFLICT, $response['body']['type']); + $this->assertEquals(Exception::ROW_UPDATE_CONFLICT, $response['body']['type']); return []; } diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index a5beb77bf3..314e3e1ae1 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -3417,7 +3417,7 @@ class DatabasesCustomServerTest extends Scope ); $this->assertEquals(400, $newDoc['headers']['status-code']); - $this->assertEquals(AppwriteException::DOCUMENT_INVALID_STRUCTURE, $newDoc['body']['type']); + $this->assertEquals(AppwriteException::ROW_INVALID_STRUCTURE, $newDoc['body']['type']); } /** From 7a52ace9b25c952d7d1b801ad0e76dde3f80c159 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 16:53:20 +0530 Subject: [PATCH 066/343] update: `attributes` <> `columns` errors. --- app/config/errors.php | 66 +++++++++---------- src/Appwrite/Extend/Exception.php | 22 +++---- .../Modules/Databases/Http/Columns/Action.php | 44 ++++++------- .../Modules/Databases/Http/Columns/Delete.php | 4 +- .../Databases/Http/Columns/Enum/Create.php | 2 +- .../Databases/Http/Columns/Float/Create.php | 4 +- .../Modules/Databases/Http/Columns/Get.php | 2 +- .../Databases/Http/Columns/Integer/Create.php | 4 +- .../Http/Columns/Relationship/Create.php | 6 +- .../Databases/Http/Columns/String/Create.php | 2 +- .../Modules/Databases/Http/Indexes/Create.php | 6 +- .../Databases/DatabasesCustomServerTest.php | 38 +++++------ 12 files changed, 100 insertions(+), 100 deletions(-) diff --git a/app/config/errors.php b/app/config/errors.php index 12d494faf6..979bf43f7d 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -71,7 +71,7 @@ return [ ], Exception::GENERAL_QUERY_LIMIT_EXCEEDED => [ 'name' => Exception::GENERAL_QUERY_LIMIT_EXCEEDED, - 'description' => 'Query limit exceeded for the current attribute. Usage of more than 100 query values on a single attribute is prohibited.', + 'description' => 'Query limit exceeded for the current column. Usage of more than 100 query values on a single column is prohibited.', 'code' => 400, ], Exception::GENERAL_QUERY_INVALID => [ @@ -653,7 +653,7 @@ return [ ], Exception::DATABASE_QUERY_ORDER_NULL => [ 'name' => Exception::DATABASE_QUERY_ORDER_NULL, - 'description' => 'The order attribute had a null value. Cursor pagination requires all documents order attribute values are non-null.', + 'description' => 'The order column had a null value. Cursor pagination requires all rows order column values are non-null.', 'code' => 400, ], @@ -707,54 +707,54 @@ return [ ], Exception::ROW_DELETE_RESTRICTED => [ 'name' => Exception::ROW_DELETE_RESTRICTED, - 'description' => 'Row cannot be deleted because it is referenced by another document.', + 'description' => 'Row cannot be deleted because it is referenced by another row.', 'code' => 403, ], - /** Attributes */ - Exception::ATTRIBUTE_NOT_FOUND => [ - 'name' => Exception::ATTRIBUTE_NOT_FOUND, - 'description' => 'Attribute with the requested ID could not be found.', + /** Columns */ + Exception::COLUMN_NOT_FOUND => [ + 'name' => Exception::COLUMN_NOT_FOUND, + 'description' => 'Column with the requested ID could not be found.', 'code' => 404, ], - Exception::ATTRIBUTE_UNKNOWN => [ - 'name' => Exception::ATTRIBUTE_UNKNOWN, - 'description' => 'The attribute required for the index could not be found. Please confirm all your attributes are in the available state.', + Exception::COLUMN_UNKNOWN => [ + 'name' => Exception::COLUMN_UNKNOWN, + 'description' => 'The column required for the index could not be found. Please confirm all your columns are in the available state.', 'code' => 400, ], - Exception::ATTRIBUTE_NOT_AVAILABLE => [ - 'name' => Exception::ATTRIBUTE_NOT_AVAILABLE, - 'description' => 'The requested attribute is not yet available. Please try again later.', + Exception::COLUMN_NOT_AVAILABLE => [ + 'name' => Exception::COLUMN_NOT_AVAILABLE, + 'description' => 'The requested column is not yet available. Please try again later.', 'code' => 400, ], - Exception::ATTRIBUTE_FORMAT_UNSUPPORTED => [ - 'name' => Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, - 'description' => 'The requested attribute format is not supported.', + Exception::COLUMN_FORMAT_UNSUPPORTED => [ + 'name' => Exception::COLUMN_FORMAT_UNSUPPORTED, + 'description' => 'The requested column format is not supported.', 'code' => 400, ], - Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED => [ - 'name' => Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, - 'description' => 'Default values cannot be set for array or required attributes.', + Exception::COLUMN_DEFAULT_UNSUPPORTED => [ + 'name' => Exception::COLUMN_DEFAULT_UNSUPPORTED, + 'description' => 'Default values cannot be set for array or required columns.', 'code' => 400, ], - Exception::ATTRIBUTE_ALREADY_EXISTS => [ - 'name' => Exception::ATTRIBUTE_ALREADY_EXISTS, - 'description' => 'Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.', + Exception::COLUMN_ALREADY_EXISTS => [ + 'name' => Exception::COLUMN_ALREADY_EXISTS, + 'description' => 'Column with the requested key already exists. Column keys must be unique, try again with a different key.', 'code' => 409, ], - Exception::ATTRIBUTE_LIMIT_EXCEEDED => [ - 'name' => Exception::ATTRIBUTE_LIMIT_EXCEEDED, - 'description' => 'The maximum number or size of attributes for this collection has been reached.', + Exception::COLUMN_LIMIT_EXCEEDED => [ + 'name' => Exception::COLUMN_LIMIT_EXCEEDED, + 'description' => 'The maximum number or size of columns for this table has been reached.', 'code' => 400, ], - Exception::ATTRIBUTE_VALUE_INVALID => [ - 'name' => Exception::ATTRIBUTE_VALUE_INVALID, - 'description' => 'The attribute value is invalid. Please check the type, range and value of the attribute.', + Exception::COLUMN_VALUE_INVALID => [ + 'name' => Exception::COLUMN_VALUE_INVALID, + 'description' => 'The column value is invalid. Please check the type, range and value of the column.', 'code' => 400, ], - Exception::ATTRIBUTE_TYPE_INVALID => [ - 'name' => Exception::ATTRIBUTE_TYPE_INVALID, - 'description' => 'The attribute type is invalid.', + Exception::COLUMN_TYPE_INVALID => [ + 'name' => Exception::COLUMN_TYPE_INVALID, + 'description' => 'The column type is invalid.', 'code' => 400, ], Exception::RELATIONSHIP_VALUE_INVALID => [ @@ -762,8 +762,8 @@ return [ 'description' => 'The relationship value is invalid.', 'code' => 400, ], - Exception::ATTRIBUTE_INVALID_RESIZE => [ - 'name' => Exception::ATTRIBUTE_INVALID_RESIZE, + Exception::COLUMN_INVALID_RESIZE => [ + 'name' => Exception::COLUMN_INVALID_RESIZE, 'description' => "Existing data is too large for new size, truncate your existing data then try again.", 'code' => 400, ], diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 6468a774ce..31a52a6a04 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -205,17 +205,17 @@ class Exception extends \Exception public const ROW_UPDATE_CONFLICT = 'row_update_conflict'; public const ROW_DELETE_RESTRICTED = 'row_delete_restricted'; - /** Attribute */ - public const ATTRIBUTE_NOT_FOUND = 'attribute_not_found'; - public const ATTRIBUTE_UNKNOWN = 'attribute_unknown'; - public const ATTRIBUTE_NOT_AVAILABLE = 'attribute_not_available'; - public const ATTRIBUTE_FORMAT_UNSUPPORTED = 'attribute_format_unsupported'; - public const ATTRIBUTE_DEFAULT_UNSUPPORTED = 'attribute_default_unsupported'; - public const ATTRIBUTE_ALREADY_EXISTS = 'attribute_already_exists'; - public const ATTRIBUTE_LIMIT_EXCEEDED = 'attribute_limit_exceeded'; - public const ATTRIBUTE_VALUE_INVALID = 'attribute_value_invalid'; - public const ATTRIBUTE_TYPE_INVALID = 'attribute_type_invalid'; - public const ATTRIBUTE_INVALID_RESIZE = 'attribute_invalid_resize'; + /** Columns */ + public const COLUMN_NOT_FOUND = 'column_not_found'; + public const COLUMN_UNKNOWN = 'column_unknown'; + public const COLUMN_NOT_AVAILABLE = 'column_not_available'; + public const COLUMN_FORMAT_UNSUPPORTED = 'column_format_unsupported'; + public const COLUMN_DEFAULT_UNSUPPORTED = 'column_default_unsupported'; + public const COLUMN_ALREADY_EXISTS = 'column_already_exists'; + public const COLUMN_LIMIT_EXCEEDED = 'column_limit_exceeded'; + public const COLUMN_VALUE_INVALID = 'column_value_invalid'; + public const COLUMN_TYPE_INVALID = 'column_type_invalid'; + public const COLUMN_INVALID_RESIZE = 'column_invalid_resize'; /** Relationship */ public const RELATIONSHIP_VALUE_INVALID = 'relationship_value_invalid'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php index 109844534b..a9415fded3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php @@ -83,17 +83,17 @@ class Action extends UtopiaAction if (!empty($format)) { if (!Structure::hasFormat($format, $type)) { - throw new Exception(Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, "Format {$format} not available for {$type} columns."); + throw new Exception(Exception::COLUMN_FORMAT_UNSUPPORTED, "Format {$format} not available for {$type} columns."); } } // Must throw here since dbForProject->createAttribute is performed by db worker if ($required && isset($default)) { - throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for required column'); + throw new Exception(Exception::COLUMN_DEFAULT_UNSUPPORTED, 'Cannot set default value for required column'); } if ($array && isset($default)) { - throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array columns'); + throw new Exception(Exception::COLUMN_DEFAULT_UNSUPPORTED, 'Cannot set default value for array columns'); } if ($type === Database::VAR_RELATIONSHIP) { @@ -128,9 +128,9 @@ class Action extends UtopiaAction $dbForProject->checkAttribute($table, $column); $column = $dbForProject->createDocument('attributes', $column); } catch (DuplicateException) { - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); + throw new Exception(Exception::COLUMN_ALREADY_EXISTS); } catch (LimitException) { - throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); + throw new Exception(Exception::COLUMN_LIMIT_EXCEEDED); } catch (Throwable $e) { $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $table->getInternalId()); @@ -171,10 +171,10 @@ class Action extends UtopiaAction $dbForProject->createDocument('attributes', $twoWayAttribute); } catch (DuplicateException) { $dbForProject->deleteDocument('attributes', $column->getId()); - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); + throw new Exception(Exception::COLUMN_ALREADY_EXISTS); } catch (LimitException) { $dbForProject->deleteDocument('attributes', $column->getId()); - throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); + throw new Exception(Exception::COLUMN_LIMIT_EXCEEDED); } catch (Throwable $e) { $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); @@ -235,27 +235,27 @@ class Action extends UtopiaAction $column = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); if ($column->isEmpty()) { - throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + throw new Exception(Exception::COLUMN_NOT_FOUND); } if ($column->getAttribute('status') !== 'available') { - throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE); + throw new Exception(Exception::COLUMN_NOT_AVAILABLE); } if ($column->getAttribute(('type') !== $type)) { - throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID); + throw new Exception(Exception::COLUMN_TYPE_INVALID); } if ($column->getAttribute('type') === Database::VAR_STRING && $column->getAttribute(('filter') !== $filter)) { - throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID); + throw new Exception(Exception::COLUMN_TYPE_INVALID); } if ($required && isset($default)) { - throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for required column'); + throw new Exception(Exception::COLUMN_DEFAULT_UNSUPPORTED, 'Cannot set default value for required column'); } if ($column->getAttribute('array', false) && isset($default)) { - throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array columns'); + throw new Exception(Exception::COLUMN_DEFAULT_UNSUPPORTED, 'Cannot set default value for array columns'); } $tableId = 'database_' . $db->getInternalId() . '_collection_' . $table->getInternalId(); @@ -275,7 +275,7 @@ class Action extends UtopiaAction $max ??= $column->getAttribute('formatOptions')['max']; if ($min > $max) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); + throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); } if ($column->getAttribute('format') === APP_DATABASE_ATTRIBUTE_INT_RANGE) { @@ -289,7 +289,7 @@ class Action extends UtopiaAction } if (!is_null($default) && !$validator->isValid($default)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); + throw new Exception(Exception::COLUMN_VALUE_INVALID, $validator->getDescription()); } $options = [ @@ -301,17 +301,17 @@ class Action extends UtopiaAction break; case APP_DATABASE_ATTRIBUTE_ENUM: if (empty($elements)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Enum elements must not be empty'); + throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Enum elements must not be empty'); } foreach ($elements as $element) { if (\strlen($element) === 0) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Each enum element must not be empty'); + throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Each enum element must not be empty'); } } if (!is_null($default) && !in_array($default, $elements)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements'); + throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Default value not found in elements'); } $options = [ @@ -334,7 +334,7 @@ class Action extends UtopiaAction onDelete: $primaryRowOptions['onDelete'], ); } catch (NotFoundException) { - throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + throw new Exception(Exception::COLUMN_NOT_FOUND); } if ($primaryRowOptions['twoWay']) { @@ -364,11 +364,11 @@ class Action extends UtopiaAction newKey: $newKey ?? null ); } catch (TruncateException) { - throw new Exception(Exception::ATTRIBUTE_INVALID_RESIZE); + throw new Exception(Exception::COLUMN_INVALID_RESIZE); } catch (NotFoundException) { - throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + throw new Exception(Exception::COLUMN_NOT_FOUND); } catch (LimitException) { - throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); + throw new Exception(Exception::COLUMN_LIMIT_EXCEEDED); } catch (IndexException $e) { throw new Exception(Exception::INDEX_INVALID, $e->getMessage()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php index c4c681b080..717e8f958c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php @@ -86,7 +86,7 @@ class Delete extends Action $column = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); if ($column->isEmpty()) { - throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + throw new Exception(Exception::COLUMN_NOT_FOUND); } $validator = new IndexDependencyValidator( @@ -114,7 +114,7 @@ class Delete extends Action $relatedColumn = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $options['twoWayKey']); if ($relatedColumn->isEmpty()) { - throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + throw new Exception(Exception::COLUMN_NOT_FOUND); } if ($relatedColumn->getAttribute('status') === 'available') { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php index 5c5c7da071..c57d451743 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php @@ -84,7 +84,7 @@ class Create extends ColumnAction Event $queueForEvents ): void { if (!is_null($default) && !in_array($default, $elements, true)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements'); + throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Default value not found in elements'); } $column = $this->createColumn( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php index 150ce8d25e..a0a16fafec 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php @@ -89,12 +89,12 @@ class Create extends ColumnAction $max ??= PHP_FLOAT_MAX; if ($min > $max) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); + throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); } $validator = new Range($min, $max, Database::VAR_FLOAT); if (!\is_null($default) && !$validator->isValid($default)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); + throw new Exception(Exception::COLUMN_VALUE_INVALID, $validator->getDescription()); } $column = $this->createColumn($databaseId, $tableId, new Document([ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php index 091b778eb8..4390f0841c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php @@ -80,7 +80,7 @@ class Get extends Action $column = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $table->getInternalId() . '_' . $key); if ($column->isEmpty()) { - throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + throw new Exception(Exception::COLUMN_NOT_FOUND); } $type = $column->getAttribute('type'); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php index d58b79d597..cf2244bf1f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php @@ -89,12 +89,12 @@ class Create extends ColumnAction $max ??= \PHP_INT_MAX; if ($min > $max) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); + throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); } $validator = new Range($min, $max, Database::VAR_INTEGER); if (!\is_null($default) && !$validator->isValid($default)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); + throw new Exception(Exception::COLUMN_VALUE_INVALID, $validator->getDescription()); } $size = $max > 2147483647 ? 8 : 4; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php index 9628d79a92..8b3ec616a3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php @@ -121,14 +121,14 @@ class Create extends ColumnAction } if (\strtolower($column->getId()) === \strtolower($key)) { - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); + throw new Exception(Exception::COLUMN_ALREADY_EXISTS); } if ( \strtolower($column->getAttribute('options')['twoWayKey']) === \strtolower($twoWayKey) && $column->getAttribute('options')['relatedCollection'] === $relatedTable->getId() ) { - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.'); + throw new Exception(Exception::COLUMN_ALREADY_EXISTS, 'Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.'); } if ( @@ -136,7 +136,7 @@ class Create extends ColumnAction $column->getAttribute('options')['relationType'] === Database::RELATION_MANY_TO_MANY && $column->getAttribute('options')['relatedCollection'] === $relatedTable->getId() ) { - throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS, 'Creating more than one "manyToMany" relationship on the same table is currently not permitted.'); + throw new Exception(Exception::COLUMN_ALREADY_EXISTS, 'Creating more than one "manyToMany" relationship on the same table is currently not permitted.'); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php index caafdbc32f..e768fda1d6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php @@ -89,7 +89,7 @@ class Create extends ColumnAction // Ensure default fits in the given size $validator = new Text($size, 0); if (!is_null($default) && !$validator->isValid($default)) { - throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); + throw new Exception(Exception::COLUMN_VALUE_INVALID, $validator->getDescription()); } $filters = []; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php index 1b45f58a2f..537d8e27f0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php @@ -142,7 +142,7 @@ class Create extends Action $columnIndex = \array_search($column, array_column($oldColumns, 'key')); if ($columnIndex === false) { - throw new Exception(Exception::ATTRIBUTE_UNKNOWN, 'Unknown column: ' . $column . '. Verify the column name or create the column.'); + throw new Exception(Exception::COLUMN_UNKNOWN, 'Unknown column: ' . $column . '. Verify the column name or create the column.'); } $columnStatus = $oldColumns[$columnIndex]['status']; @@ -150,12 +150,12 @@ class Create extends Action $columnArray = $oldColumns[$columnIndex]['array'] ?? false; if ($columnType === Database::VAR_RELATIONSHIP) { - throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Cannot create an index for a relationship column: ' . $oldColumns[$columnIndex]['key']); + throw new Exception(Exception::COLUMN_TYPE_INVALID, 'Cannot create an index for a relationship column: ' . $oldColumns[$columnIndex]['key']); } // ensure attribute is available if ($columnStatus !== 'available') { - throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Column not available: ' . $oldColumns[$columnIndex]['key']); + throw new Exception(Exception::COLUMN_NOT_AVAILABLE, 'Column not available: ' . $oldColumns[$columnIndex]['key']); } $lengths[$i] = null; diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 314e3e1ae1..874aa5623e 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -1785,7 +1785,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -1928,7 +1928,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -2070,7 +2070,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -2212,7 +2212,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -2430,7 +2430,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2444,7 +2444,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2458,7 +2458,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ @@ -2473,7 +2473,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); } /** @@ -2691,7 +2691,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2705,7 +2705,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2719,7 +2719,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ @@ -2734,7 +2734,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); } /** @@ -2876,7 +2876,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -3018,7 +3018,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -3133,7 +3133,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', @@ -3146,7 +3146,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', @@ -3234,7 +3234,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -3324,7 +3324,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $attribute['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_INVALID_RESIZE, $attribute['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_INVALID_RESIZE, $attribute['body']['type']); // original documents to original size, remove new document $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document['body']['$id'], array_merge([ @@ -3503,7 +3503,7 @@ class DatabasesCustomServerTest extends Scope ]), $payload); $this->assertEquals(404, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::ATTRIBUTE_NOT_FOUND, $update['body']['type']); + $this->assertEquals(AppwriteException::COLUMN_NOT_FOUND, $update['body']['type']); } } From 6eb1c3ae686ad9c549522a70aef5aa587103194c Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 16:58:56 +0530 Subject: [PATCH 067/343] update: rename remaining variables. --- .../Platform/Modules/Databases/Http/Rows/Create.php | 8 ++++---- .../Platform/Modules/Databases/Http/Rows/Delete.php | 6 +++--- src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php | 2 +- .../Platform/Modules/Databases/Http/Rows/Update.php | 8 ++++---- .../Platform/Modules/Databases/Http/Rows/XList.php | 2 +- .../Platform/Modules/Databases/Workers/Databases.php | 6 +++--- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php index df36696d80..87078a5d3d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php @@ -175,7 +175,7 @@ class Create extends Action $relationships = \array_filter( $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -257,7 +257,7 @@ class Create extends Action $relationships = \array_filter( $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -296,10 +296,10 @@ class Create extends Action ->dynamic($row, UtopiaResponse::MODEL_ROW); $relationships = \array_map( - fn ($document) => $document->getAttribute('key'), + fn ($row) => $row->getAttribute('key'), \array_filter( $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP ) ); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php index 8c68f23bfb..61cd4d218a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php @@ -112,7 +112,7 @@ class Delete extends Action $relationships = \array_filter( $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -147,10 +147,10 @@ class Delete extends Action $response->addHeader('X-Debug-Operations', 1); $relationships = \array_map( - fn ($document) => $document->getAttribute('key'), + fn ($row) => $row->getAttribute('key'), \array_filter( $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP ) ); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php index 69127ca238..fb600f5a7f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php @@ -110,7 +110,7 @@ class Get extends Action $relationships = \array_filter( $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php index 7dcd1f8fcb..5590aa6c67 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php @@ -156,7 +156,7 @@ class Update extends Action $relationships = \array_filter( $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -253,7 +253,7 @@ class Update extends Action $relationships = \array_filter( $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -284,10 +284,10 @@ class Update extends Action $response->dynamic($row, UtopiaResponse::MODEL_ROW); $relationships = \array_map( - fn ($document) => $document->getAttribute('key'), + fn ($row) => $row->getAttribute('key'), \array_filter( $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP ) ); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php index 95410507bf..781c0d7c83 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php @@ -136,7 +136,7 @@ class XList extends Action $relationships = \array_filter( $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { diff --git a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php index 6564239630..37fa7cf0cc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php +++ b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php @@ -539,9 +539,9 @@ class Databases extends Action Query::contains('options', ['"relatedCollection":"'. $collectionId .'"']), ], $dbForProject, - function ($attribute) use ($dbForProject, $databaseInternalId) { - $dbForProject->purgeCachedDocument('database_' . $databaseInternalId, $attribute->getAttribute('collectionId')); - $dbForProject->purgeCachedCollection('database_' . $databaseInternalId . '_collection_' . $attribute->getAttribute('collectionInternalId')); + function ($column) use ($dbForProject, $databaseInternalId) { + $dbForProject->purgeCachedDocument('database_' . $databaseInternalId, $column->getAttribute('collectionId')); + $dbForProject->purgeCachedCollection('database_' . $databaseInternalId . '_collection_' . $column->getAttribute('collectionInternalId')); } ); From 3e813f6cba68f057bbb70318f49b0708530f7370 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 17:00:12 +0530 Subject: [PATCH 068/343] update: change filter name for collections <> tables. --- src/Appwrite/GraphQL/Types/Mapper.php | 2 +- src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php | 4 ++-- src/Appwrite/Specification/Format/OpenAPI3.php | 2 +- .../Validator/Queries/{Collections.php => Tables.php} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename src/Appwrite/Utopia/Database/Validator/Queries/{Collections.php => Tables.php} (91%) diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index 8cfad823af..e763c3b42c 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -284,7 +284,7 @@ class Mapper case 'Utopia\Database\Validator\Authorization': case 'Appwrite\Utopia\Database\Validator\Queries\Base': case 'Appwrite\Utopia\Database\Validator\Queries\Buckets': - case 'Appwrite\Utopia\Database\Validator\Queries\Collections': + case 'Appwrite\Utopia\Database\Validator\Queries\Tables': case 'Appwrite\Utopia\Database\Validator\Queries\Attributes': case 'Appwrite\Utopia\Database\Validator\Queries\Indexes': case 'Appwrite\Utopia\Database\Validator\Queries\Databases': diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php index 055102415d..e6d2a2d02a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php @@ -7,7 +7,7 @@ use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; -use Appwrite\Utopia\Database\Validator\Queries\Collections; +use Appwrite\Utopia\Database\Validator\Queries\Tables; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; @@ -55,7 +55,7 @@ class XList extends Action contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('queries', [], new Collections(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Collections::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new Tables(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Tables::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index 4452f63f0f..9497110950 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -409,7 +409,7 @@ class OpenAPI3 extends Format break; case 'Appwrite\Utopia\Database\Validator\Queries\Attributes': case 'Appwrite\Utopia\Database\Validator\Queries\Buckets': - case 'Appwrite\Utopia\Database\Validator\Queries\Collections': + case 'Appwrite\Utopia\Database\Validator\Queries\Tables': case 'Appwrite\Utopia\Database\Validator\Queries\Databases': case 'Appwrite\Utopia\Database\Validator\Queries\Deployments': case 'Appwrite\Utopia\Database\Validator\Queries\Executions': diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php b/src/Appwrite/Utopia/Database/Validator/Queries/Tables.php similarity index 91% rename from src/Appwrite/Utopia/Database/Validator/Queries/Collections.php rename to src/Appwrite/Utopia/Database/Validator/Queries/Tables.php index 6e8fcb8339..5a1fc4ec6d 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Tables.php @@ -2,7 +2,7 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -class Collections extends Base +class Tables extends Base { public const ALLOWED_ATTRIBUTES = [ 'name', From ed9306ef8d1a56101548d08c59247d9bbf642dd2 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 6 May 2025 17:00:57 +0530 Subject: [PATCH 069/343] update: change filter name for attributes <> columns. --- src/Appwrite/GraphQL/Types/Mapper.php | 2 +- .../Platform/Modules/Databases/Http/Columns/XList.php | 4 ++-- src/Appwrite/Specification/Format/OpenAPI3.php | 2 +- .../Validator/Queries/{Attributes.php => Columns.php} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename src/Appwrite/Utopia/Database/Validator/Queries/{Attributes.php => Columns.php} (93%) diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index e763c3b42c..45aa9e0085 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -285,7 +285,7 @@ class Mapper case 'Appwrite\Utopia\Database\Validator\Queries\Base': case 'Appwrite\Utopia\Database\Validator\Queries\Buckets': case 'Appwrite\Utopia\Database\Validator\Queries\Tables': - case 'Appwrite\Utopia\Database\Validator\Queries\Attributes': + case 'Appwrite\Utopia\Database\Validator\Queries\Columns': case 'Appwrite\Utopia\Database\Validator\Queries\Indexes': case 'Appwrite\Utopia\Database\Validator\Queries\Databases': case 'Appwrite\Utopia\Database\Validator\Queries\Deployments': diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php index e9800e71a0..b23fafcbd0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php @@ -6,7 +6,7 @@ use Appwrite\Extend\Exception; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; -use Appwrite\Utopia\Database\Validator\Queries\Attributes; +use Appwrite\Utopia\Database\Validator\Queries\Columns; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; @@ -53,7 +53,7 @@ class XList extends Action )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID.') - ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new Columns(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Columns::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') ->callback([$this, 'action']); diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index 9497110950..088a20ff98 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -407,7 +407,7 @@ class OpenAPI3 extends Format 'type' => $validator->getValidator()->getType(), ]; break; - case 'Appwrite\Utopia\Database\Validator\Queries\Attributes': + case 'Appwrite\Utopia\Database\Validator\Queries\Columns': case 'Appwrite\Utopia\Database\Validator\Queries\Buckets': case 'Appwrite\Utopia\Database\Validator\Queries\Tables': case 'Appwrite\Utopia\Database\Validator\Queries\Databases': diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Columns.php similarity index 93% rename from src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php rename to src/Appwrite/Utopia/Database/Validator/Queries/Columns.php index 4a35c82b73..3c2742bfdd 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Columns.php @@ -2,7 +2,7 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -class Attributes extends Base +class Columns extends Base { public const ALLOWED_ATTRIBUTES = [ 'key', From ee117b816a7ecc4c2bbf4a2f7245825dc7907c7c Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 7 May 2025 10:33:54 +0530 Subject: [PATCH 070/343] manage: events and channels. --- app/controllers/shared/api.php | 22 +++------------------ src/Appwrite/Event/Realtime.php | 6 ++++-- src/Appwrite/Messaging/Adapter/Realtime.php | 14 ++++++------- 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index ba695acff4..8c15f27acc 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -483,26 +483,10 @@ App::init() /* * Background Jobs */ - $events = $route->getLabel('event', ''); $queueForEvents - ->setUser($user) - ->setEvent($events) - ->setProject($project); - - if (str_contains($events, '.tables.')) { - $requestFormat = $request->getHeader('x-appwrite-response-format', System::getEnv('_APP_SYSTEM_RESPONSE_FORMAT', '')); - if ($requestFormat && version_compare($requestFormat, '1.7.0', '<')) { - $map = [ - 'rows' => 'documents', - 'tables' => 'collections', - 'columns' => 'attributes', - ]; - - $compatibleEvents = str_replace(array_keys($map), array_values($map), $events); - // override the events - $queueForEvents->setEvent($compatibleEvents); - } - } + ->setEvent($route->getLabel('event', '')) + ->setProject($project) + ->setUser($user); $queueForAudits ->setMode($mode) diff --git a/src/Appwrite/Event/Realtime.php b/src/Appwrite/Event/Realtime.php index e1ec891e67..67d51e5c52 100644 --- a/src/Appwrite/Event/Realtime.php +++ b/src/Appwrite/Event/Realtime.php @@ -76,16 +76,18 @@ class Realtime extends Event $payload = new Document($this->getPayload()); $db = $this->getContext('database'); - $table = $this->getContext('table'); $bucket = $this->getContext('bucket'); + // can be Tables API or Collections API, generated channels include both! + $tableOrCollection = $this->getContext('table') ?? $this->getContext('collection'); + $target = RealtimeAdapter::fromPayload( // Pass first, most verbose event pattern event: $allEvents[0], payload: $payload, project: $this->getProject(), database: $db, - table: $table, + table: $tableOrCollection, bucket: $bucket, ); diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index b775078c61..5cb908464f 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -303,23 +303,23 @@ class Realtime extends Adapter $channels[] = 'projects.' . $project->getId(); $projectId = 'console'; $roles = [Role::team($project->getAttribute('teamId'))->toString()]; - } elseif (($parts[4] ?? '') === 'rows') { + } elseif (($parts[4] ?? '') === 'rows' || ($parts[4] ?? '') === 'documents') { if ($database->isEmpty()) { - throw new \Exception('Database needs to be passed to Realtime for Row events in the Database.'); + throw new \Exception('Database needs to be passed to Realtime for Document/Row events in the Database.'); } if ($table->isEmpty()) { - throw new \Exception('Table needs to be passed to Realtime for Row events in the Database.'); + throw new \Exception('Collection or the Table needs to be passed to Realtime for Document/Row events in the Database.'); } - // 1.7.x + // 1.7.x - Tables API $channels[] = 'rows'; $channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$tableId') . '.rows'; $channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$tableId') . '.rows.' . $payload->getId(); - // 1.6.x + // 1.6.x - Collections API $channels[] = 'documents'; - $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$tableId') . '.documents'; - $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$tableId') . '.documents.' . $payload->getId(); + $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents'; + $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents.' . $payload->getId(); $roles = $table->getAttribute('documentSecurity', false) ? \array_merge($table->getRead(), $payload->getRead()) From 46ccf6f5370dd7c7a871fed143a257e2736c84d1 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 7 May 2025 11:13:15 +0530 Subject: [PATCH 071/343] update: re-add legacy models; remove: filters. --- app/config/events.php | 50 ++++++++ app/controllers/api/project.php | 2 +- app/init/resources.php | 9 +- src/Appwrite/GraphQL/Types/Mapper.php | 43 ++++--- .../Specification/Format/OpenAPI3.php | 2 + .../Database/Validator/Queries/Attributes.php | 25 ++++ .../Validator/Queries/Collections.php | 21 ++++ src/Appwrite/Utopia/Request/Filters/V19.php | 35 ++---- src/Appwrite/Utopia/Response.php | 53 +++++++++ src/Appwrite/Utopia/Response/Filters/V19.php | 77 +------------ .../Utopia/Response/Model/Attribute.php | 85 ++++++++++++++ .../Response/Model/AttributeBoolean.php | 59 ++++++++++ .../Response/Model/AttributeDatetime.php | 67 +++++++++++ .../Utopia/Response/Model/AttributeEmail.php | 66 +++++++++++ .../Utopia/Response/Model/AttributeEnum.php | 73 ++++++++++++ .../Utopia/Response/Model/AttributeFloat.php | 73 ++++++++++++ .../Utopia/Response/Model/AttributeIP.php | 66 +++++++++++ .../Response/Model/AttributeInteger.php | 72 ++++++++++++ .../Utopia/Response/Model/AttributeList.php | 58 ++++++++++ .../Response/Model/AttributeRelationship.php | 96 +++++++++++++++ .../Utopia/Response/Model/AttributeString.php | 53 +++++++++ .../Utopia/Response/Model/AttributeURL.php | 66 +++++++++++ .../Utopia/Response/Model/BaseList.php | 8 +- .../Utopia/Response/Model/Collection.php | 109 ++++++++++++++++++ .../Utopia/Response/Model/Document.php | 92 +++++++++++++++ .../Utopia/Response/Model/UsageCollection.php | 54 +++++++++ 26 files changed, 1283 insertions(+), 131 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Collections.php create mode 100644 src/Appwrite/Utopia/Response/Model/Attribute.php create mode 100644 src/Appwrite/Utopia/Response/Model/AttributeBoolean.php create mode 100644 src/Appwrite/Utopia/Response/Model/AttributeDatetime.php create mode 100644 src/Appwrite/Utopia/Response/Model/AttributeEmail.php create mode 100644 src/Appwrite/Utopia/Response/Model/AttributeEnum.php create mode 100644 src/Appwrite/Utopia/Response/Model/AttributeFloat.php create mode 100644 src/Appwrite/Utopia/Response/Model/AttributeIP.php create mode 100644 src/Appwrite/Utopia/Response/Model/AttributeInteger.php create mode 100644 src/Appwrite/Utopia/Response/Model/AttributeList.php create mode 100644 src/Appwrite/Utopia/Response/Model/AttributeRelationship.php create mode 100644 src/Appwrite/Utopia/Response/Model/AttributeString.php create mode 100644 src/Appwrite/Utopia/Response/Model/AttributeURL.php create mode 100644 src/Appwrite/Utopia/Response/Model/Collection.php create mode 100644 src/Appwrite/Utopia/Response/Model/Document.php create mode 100644 src/Appwrite/Utopia/Response/Model/UsageCollection.php diff --git a/app/config/events.php b/app/config/events.php index 4523b56206..182aa91363 100644 --- a/app/config/events.php +++ b/app/config/events.php @@ -145,6 +145,56 @@ return [ '$description' => 'This event triggers when a table is updated.', ] ], + 'collections' => [ + '$model' => Response::MODEL_COLLECTION, + '$resource' => true, + '$description' => 'This event triggers on any collection event.', + 'documents' => [ + '$model' => Response::MODEL_DOCUMENT, + '$resource' => true, + '$description' => 'This event triggers on any document event.', + 'create' => [ + '$description' => 'This event triggers when a document is created.', + ], + 'delete' => [ + '$description' => 'This event triggers when a document is deleted.' + ], + 'update' => [ + '$description' => 'This event triggers when a document is updated.' + ], + ], + 'indexes' => [ + '$model' => Response::MODEL_INDEX, + '$resource' => true, + '$description' => 'This event triggers on any indexes event.', + 'create' => [ + '$description' => 'This event triggers when an index is created.', + ], + 'delete' => [ + '$description' => 'This event triggers when an index is deleted.' + ] + ], + 'attributes' => [ + '$model' => Response::MODEL_ATTRIBUTE, + '$resource' => true, + '$description' => 'This event triggers on any attributes event.', + 'create' => [ + '$description' => 'This event triggers when an attribute is created.', + ], + 'delete' => [ + '$description' => 'This event triggers when an attribute is deleted.' + ] + ], + 'create' => [ + '$description' => 'This event triggers when a collection is created.' + ], + 'delete' => [ + '$description' => 'This event triggers when a collection is deleted.', + ], + 'update' => [ + '$description' => 'This event triggers when a collection is updated.', + ] + ], 'create' => [ '$description' => 'This event triggers when a database is created.' ], diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 97475c743a..047179b888 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -353,7 +353,7 @@ App::get('/v1/project/usage') 'executionsTotal' => $total[METRIC_EXECUTIONS], 'executionsMbSecondsTotal' => $total[METRIC_EXECUTIONS_MB_SECONDS], 'buildsMbSecondsTotal' => $total[METRIC_BUILDS_MB_SECONDS], - 'rowsTotal' => $total[METRIC_DOCUMENTS], + 'documentsTotal' => $total[METRIC_DOCUMENTS], 'databasesTotal' => $total[METRIC_DATABASES], 'databasesStorageTotal' => $total[METRIC_DATABASES_STORAGE], 'usersTotal' => $total[METRIC_USERS], diff --git a/app/init/resources.php b/app/init/resources.php index 7657b9ea69..5ac26281a2 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -707,6 +707,7 @@ App::setResource('schema', function ($utopia, $dbForProject) { }, ]; + // NOTE: `params` and `urls` are not used internally in the `Schema::build` function below! $params = [ 'list' => function (string $databaseId, string $collectionId, array $args) { return [ 'queries' => $args['queries']]; @@ -721,8 +722,8 @@ App::setResource('schema', function ($utopia, $dbForProject) { // Order must be the same as the route params return [ 'databaseId' => $databaseId, - 'rowId' => $id, - 'tableId' => $collectionId, + 'documentId' => $id, + 'collectionId' => $collectionId, 'data' => $args, 'permissions' => $permissions, ]; @@ -737,8 +738,8 @@ App::setResource('schema', function ($utopia, $dbForProject) { // Order must be the same as the route params return [ 'databaseId' => $databaseId, - 'tableId' => $collectionId, - 'rowId' => $documentId, + 'collectionId' => $collectionId, + 'documentId' => $documentId, 'data' => $args, 'permissions' => $permissions, ]; diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index 45aa9e0085..a56b7f2f8a 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -285,7 +285,9 @@ class Mapper case 'Appwrite\Utopia\Database\Validator\Queries\Base': case 'Appwrite\Utopia\Database\Validator\Queries\Buckets': case 'Appwrite\Utopia\Database\Validator\Queries\Tables': + case 'Appwrite\Utopia\Database\Validator\Queries\Collections': case 'Appwrite\Utopia\Database\Validator\Queries\Columns': + case 'Appwrite\Utopia\Database\Validator\Queries\Attributes': case 'Appwrite\Utopia\Database\Validator\Queries\Indexes': case 'Appwrite\Utopia\Database\Validator\Queries\Databases': case 'Appwrite\Utopia\Database\Validator\Queries\Deployments': @@ -418,8 +420,10 @@ class Mapper // TODO: Find a better way to do this switch ($name) { - case 'Columns': + case 'Attributes': return static::getColumnImplementation($object); + case 'Columns': + return static::getColumnImplementation($object, true); case 'HashOptions': return static::getHashOptionsImplementation($object); } @@ -427,29 +431,24 @@ class Mapper throw new Exception('Unknown union type: ' . $name); } - private static function getColumnImplementation(array $object): Type + private static function getColumnImplementation(array $object, bool $isColumns = false): Type { - switch ($object['type']) { - case 'string': - return match ($object['format'] ?? '') { - 'email' => static::model('ColumnEmail'), - 'url' => static::model('ColumnUrl'), - 'ip' => static::model('ColumnIp'), - default => static::model('ColumnString'), - }; - case 'integer': - return static::model('ColumnInteger'); - case 'double': - return static::model('ColumnFloat'); - case 'boolean': - return static::model('ColumnBoolean'); - case 'datetime': - return static::model('ColumnDatetime'); - case 'relationship': - return static::model('ColumnRelationship'); - } + $prefix = $isColumns ? 'Column' : 'Attribute'; - throw new Exception('Unknown column implementation'); + return match ($object['type']) { + 'string' => match ($object['format'] ?? '') { + 'email' => static::model("{$prefix}Email"), + 'url' => static::model("{$prefix}Url"), + 'ip' => static::model("{$prefix}Ip"), + default => static::model("{$prefix}String"), + }, + 'integer' => static::model("{$prefix}Integer"), + 'double' => static::model("{$prefix}Float"), + 'boolean' => static::model("{$prefix}Boolean"), + 'datetime' => static::model("{$prefix}Datetime"), + 'relationship' => static::model("{$prefix}Relationship"), + default => throw new Exception('Unknown ' . strtolower($prefix) . ' implementation'), + }; } private static function getHashOptionsImplementation(array $object): Type diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index 088a20ff98..9c906d3ebc 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -408,8 +408,10 @@ class OpenAPI3 extends Format ]; break; case 'Appwrite\Utopia\Database\Validator\Queries\Columns': + case 'Appwrite\Utopia\Database\Validator\Queries\Attributes': case 'Appwrite\Utopia\Database\Validator\Queries\Buckets': case 'Appwrite\Utopia\Database\Validator\Queries\Tables': + case 'Appwrite\Utopia\Database\Validator\Queries\Collections': case 'Appwrite\Utopia\Database\Validator\Queries\Databases': case 'Appwrite\Utopia\Database\Validator\Queries\Deployments': case 'Appwrite\Utopia\Database\Validator\Queries\Executions': diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php new file mode 100644 index 0000000000..4a35c82b73 --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php @@ -0,0 +1,25 @@ + 'rowId', - 'attributes' => 'columns', - 'collectionId' => 'tableId', - 'attributeId' => 'columnId', - '$collectionId' => '$tableId', - 'relatedCollection' => 'relatedTable', - 'relatedCollectionId' => 'relatedTableId', - ]; - // Convert 1.6 params to 1.7 public function parse(array $content, string $model): array { - $content = $this->overrideDatabaseParams($content, $model); - - return $content; - } - - protected function overrideDatabaseParams(array $content, string $model): array - { - if (!str_starts_with($model, 'databases.')) { - return $content; - } - - $intersect = array_intersect_key(self::PARAMS_MAP, $content); - - foreach ($intersect as $oldKey => $newKey) { - $content[$newKey] = $content[$oldKey]; - unset($content[$oldKey]); + /* + Uncomment with first request filter; current is just a copy of V18 + switch ($model) { + case 'functions.create': + $content['something'] = $content['somethingElse'] ?? ""; + unset($content['something']); + break; } + */ return $content; } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 62822e9956..c72a01c79a 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -15,10 +15,23 @@ use Appwrite\Utopia\Response\Model\AlgoScrypt; use Appwrite\Utopia\Response\Model\AlgoScryptModified; use Appwrite\Utopia\Response\Model\AlgoSha; use Appwrite\Utopia\Response\Model\Any; +use Appwrite\Utopia\Response\Model\Attribute; +use Appwrite\Utopia\Response\Model\AttributeBoolean; +use Appwrite\Utopia\Response\Model\AttributeDatetime; +use Appwrite\Utopia\Response\Model\AttributeEmail; +use Appwrite\Utopia\Response\Model\AttributeEnum; +use Appwrite\Utopia\Response\Model\AttributeFloat; +use Appwrite\Utopia\Response\Model\AttributeInteger; +use Appwrite\Utopia\Response\Model\AttributeIP; +use Appwrite\Utopia\Response\Model\AttributeList; +use Appwrite\Utopia\Response\Model\AttributeRelationship; +use Appwrite\Utopia\Response\Model\AttributeString; +use Appwrite\Utopia\Response\Model\AttributeURL; use Appwrite\Utopia\Response\Model\AuthProvider; use Appwrite\Utopia\Response\Model\BaseList; use Appwrite\Utopia\Response\Model\Branch; use Appwrite\Utopia\Response\Model\Bucket; +use Appwrite\Utopia\Response\Model\Collection; use Appwrite\Utopia\Response\Model\Column; use Appwrite\Utopia\Response\Model\ColumnBoolean; use Appwrite\Utopia\Response\Model\ColumnDatetime; @@ -40,6 +53,7 @@ use Appwrite\Utopia\Response\Model\Deployment; use Appwrite\Utopia\Response\Model\DetectionFramework; use Appwrite\Utopia\Response\Model\DetectionRuntime; use Appwrite\Utopia\Response\Model\DevKey; +use Appwrite\Utopia\Response\Model\Document as ModelDocument; use Appwrite\Utopia\Response\Model\Error; use Appwrite\Utopia\Response\Model\ErrorDev; use Appwrite\Utopia\Response\Model\Execution; @@ -106,6 +120,7 @@ use Appwrite\Utopia\Response\Model\TemplateVariable; use Appwrite\Utopia\Response\Model\Token; use Appwrite\Utopia\Response\Model\Topic; use Appwrite\Utopia\Response\Model\UsageBuckets; +use Appwrite\Utopia\Response\Model\UsageCollection; use Appwrite\Utopia\Response\Model\UsageDatabase; use Appwrite\Utopia\Response\Model\UsageDatabases; use Appwrite\Utopia\Response\Model\UsageFunction; @@ -148,6 +163,7 @@ class Response extends SwooleResponse public const MODEL_USAGE_DATABASES = 'usageDatabases'; public const MODEL_USAGE_DATABASE = 'usageDatabase'; public const MODEL_USAGE_TABLE = 'usageTable'; + public const MODEL_USAGE_COLLECTION = 'usageCollection'; public const MODEL_USAGE_USERS = 'usageUsers'; public const MODEL_USAGE_BUCKETS = 'usageBuckets'; public const MODEL_USAGE_STORAGE = 'usageStorage'; @@ -160,14 +176,32 @@ class Response extends SwooleResponse // Database public const MODEL_DATABASE = 'database'; public const MODEL_DATABASE_LIST = 'databaseList'; + public const MODEL_COLLECTION = 'collection'; + public const MODEL_COLLECTION_LIST = 'collectionList'; public const MODEL_TABLE = 'table'; public const MODEL_TABLE_LIST = 'tableList'; public const MODEL_INDEX = 'index'; public const MODEL_INDEX_LIST = 'indexList'; + public const MODEL_DOCUMENT = 'document'; + public const MODEL_DOCUMENT_LIST = 'documentList'; public const MODEL_ROW = 'row'; public const MODEL_ROW_LIST = 'rowList'; // Database Attributes + public const MODEL_ATTRIBUTE = 'attribute'; + public const MODEL_ATTRIBUTE_LIST = 'attributeList'; + public const MODEL_ATTRIBUTE_STRING = 'attributeString'; + public const MODEL_ATTRIBUTE_INTEGER = 'attributeInteger'; + public const MODEL_ATTRIBUTE_FLOAT = 'attributeFloat'; + public const MODEL_ATTRIBUTE_BOOLEAN = 'attributeBoolean'; + public const MODEL_ATTRIBUTE_EMAIL = 'attributeEmail'; + public const MODEL_ATTRIBUTE_ENUM = 'attributeEnum'; + public const MODEL_ATTRIBUTE_IP = 'attributeIp'; + public const MODEL_ATTRIBUTE_URL = 'attributeUrl'; + public const MODEL_ATTRIBUTE_DATETIME = 'attributeDatetime'; + public const MODEL_ATTRIBUTE_RELATIONSHIP = 'attributeRelationship'; + + // Database Columns public const MODEL_COLUMN = 'column'; public const MODEL_COLUMN_LIST = 'columnList'; public const MODEL_COLUMN_STRING = 'columnString'; @@ -377,7 +411,9 @@ class Response extends SwooleResponse ->setModel(new ErrorDev()) // Lists ->setModel(new BaseList('Rows List', self::MODEL_ROW_LIST, 'rows', self::MODEL_ROW)) + ->setModel(new BaseList('Documents List', self::MODEL_DOCUMENT_LIST, 'documents', self::MODEL_DOCUMENT)) ->setModel(new BaseList('Tables List', self::MODEL_TABLE_LIST, 'tables', self::MODEL_TABLE)) + ->setModel(new BaseList('Collections List', self::MODEL_COLLECTION_LIST, 'collections', self::MODEL_COLLECTION)) ->setModel(new BaseList('Databases List', self::MODEL_DATABASE_LIST, 'databases', self::MODEL_DATABASE)) ->setModel(new BaseList('Indexes List', self::MODEL_INDEX_LIST, 'indexes', self::MODEL_INDEX)) ->setModel(new BaseList('Users List', self::MODEL_USER_LIST, 'users', self::MODEL_USER)) @@ -428,6 +464,21 @@ class Response extends SwooleResponse ->setModel(new BaseList('VCS Content List', self::MODEL_VCS_CONTENT_LIST, 'contents', self::MODEL_VCS_CONTENT)) // Entities ->setModel(new Database()) + // Collection API Models + ->setModel(new Collection()) + ->setModel(new Attribute()) + ->setModel(new AttributeList()) + ->setModel(new AttributeString()) + ->setModel(new AttributeInteger()) + ->setModel(new AttributeFloat()) + ->setModel(new AttributeBoolean()) + ->setModel(new AttributeEmail()) + ->setModel(new AttributeEnum()) + ->setModel(new AttributeIP()) + ->setModel(new AttributeURL()) + ->setModel(new AttributeDatetime()) + ->setModel(new AttributeRelationship()) + // Table API Models ->setModel(new Table()) ->setModel(new Column()) ->setModel(new ColumnList()) @@ -443,6 +494,7 @@ class Response extends SwooleResponse ->setModel(new ColumnRelationship()) ->setModel(new Index()) ->setModel(new Row()) + ->setModel(new ModelDocument()) ->setModel(new Log()) ->setModel(new User()) ->setModel(new AlgoMd5()) @@ -509,6 +561,7 @@ class Response extends SwooleResponse ->setModel(new UsageDatabases()) ->setModel(new UsageDatabase()) ->setModel(new UsageTable()) + ->setModel(new UsageCollection()) ->setModel(new UsageUsers()) ->setModel(new UsageStorage()) ->setModel(new UsageBuckets()) diff --git a/src/Appwrite/Utopia/Response/Filters/V19.php b/src/Appwrite/Utopia/Response/Filters/V19.php index 24cb07889f..4505b2c8f2 100644 --- a/src/Appwrite/Utopia/Response/Filters/V19.php +++ b/src/Appwrite/Utopia/Response/Filters/V19.php @@ -7,44 +7,18 @@ use Appwrite\Utopia\Response\Filter; class V19 extends Filter { - private const DATABASE_MAPPINGS = [ - 'table' => 'collection', - 'tables' => 'collections', - '$tableId' => '$collectionId', - 'tablesTotal' => 'collectionsTotal', - 'relatedTable' => 'relatedCollection', - 'relatedTableId' => 'relatedCollectionId', - - 'column' => 'attribute', - 'columns' => 'attributes', - 'columnsTotal' => 'attributesTotal', - - 'row' => 'document', - 'rows' => 'documents', - 'rowsTotal' => 'documentsTotal' - ]; - // Convert 1.7 Data format to 1.6 format public function parse(array $content, string $model): array { $parsedResponse = $content; - return match ($model) { - Response::MODEL_ROW, - Response::MODEL_TABLE, - Response::MODEL_COLUMN, - Response::MODEL_ROW_LIST, - Response::MODEL_TABLE_LIST, - Response::MODEL_COLUMN_LIST, - Response::MODEL_USAGE_TABLE, - Response::MODEL_USAGE_DATABASE, - Response::MODEL_USAGE_DATABASES, - Response::MODEL_COLUMN_RELATIONSHIP => $this->handleDBTerminology($model, $content), - + $parsedResponse = match($model) { Response::MODEL_FUNCTION => $this->parseFunction($content), Response::MODEL_FUNCTION_LIST => $this->handleList($content, 'functions', fn ($item) => $this->parseFunction($item)), default => $parsedResponse, }; + + return $parsedResponse; } protected function parseFunction(array $content): array @@ -53,49 +27,4 @@ class V19 extends Filter unset($content['deploymentId']); return $content; } - - protected function handleDBTerminology(string $model, array $content): array - { - $isListModel = match ($model) { - Response::MODEL_ROW_LIST, - Response::MODEL_TABLE_LIST, - Response::MODEL_COLUMN_LIST => true, - - default => false - }; - - if ($isListModel) { - foreach (self::DATABASE_MAPPINGS as $oldKey => $newKey) { - if (isset($content[$oldKey])) { - $content[$newKey] = array_map(fn ($item) => $this->remapKeys($item), $content[$oldKey]); - unset($content[$oldKey]); - } - } - } else { - $content = $this->remapKeysRecursive($content); - } - - return $content; - } - - private function remapKeys(array $data): array - { - foreach (self::DATABASE_MAPPINGS as $old => $new) { - if (isset($data[$old])) { - $data[$new] = $data[$old]; - unset($data[$old]); - } - } - return $data; - } - - private function remapKeysRecursive(array $data): array - { - $result = []; - foreach ($data as $key => $value) { - $newKey = self::DATABASE_MAPPINGS[$key] ?? $key; - $result[$newKey] = \is_array($value) ? $this->remapKeysRecursive($value) : $value; - } - return $result; - } } diff --git a/src/Appwrite/Utopia/Response/Model/Attribute.php b/src/Appwrite/Utopia/Response/Model/Attribute.php new file mode 100644 index 0000000000..8c43f8d21c --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/Attribute.php @@ -0,0 +1,85 @@ +addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute Key.', + 'default' => '', + 'example' => 'fullName', + ]) + ->addRule('type', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute type.', + 'default' => '', + 'example' => 'string', + ]) + ->addRule('status', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`', + 'default' => '', + 'example' => 'available', + ]) + ->addRule('error', [ + 'type' => self::TYPE_STRING, + 'description' => 'Error message. Displays error generated on failure of creating or deleting an attribute.', + 'default' => '', + 'example' => 'string', + ]) + ->addRule('required', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Is attribute required?', + 'default' => false, + 'example' => true, + ]) + ->addRule('array', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Is attribute an array?', + 'default' => false, + 'required' => false, + 'example' => false, + ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Attribute creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Attribute update date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]); + } + + public array $conditions = []; + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'Attribute'; + } + + /** + * Get Collection + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_ATTRIBUTE; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php b/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php new file mode 100644 index 0000000000..05846817ca --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php @@ -0,0 +1,59 @@ +addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute Key.', + 'default' => '', + 'example' => 'isEnabled', + ]) + ->addRule('type', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute type.', + 'default' => '', + 'example' => 'boolean', + ]) + ->addRule('default', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.', + 'default' => null, + 'required' => false, + 'example' => false + ]) + ; + } + + public array $conditions = [ + 'type' => self::TYPE_BOOLEAN + ]; + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'AttributeBoolean'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_ATTRIBUTE_BOOLEAN; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeDatetime.php b/src/Appwrite/Utopia/Response/Model/AttributeDatetime.php new file mode 100644 index 0000000000..4651aebd06 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/AttributeDatetime.php @@ -0,0 +1,67 @@ +addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute Key.', + 'default' => '', + 'example' => 'birthDay', + ]) + ->addRule('type', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute type.', + 'default' => '', + 'example' => self::TYPE_DATETIME, + ]) + ->addRule('format', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'ISO 8601 format.', + 'default' => APP_DATABASE_ATTRIBUTE_DATETIME, + 'example' => APP_DATABASE_ATTRIBUTE_DATETIME, + 'array' => false, + ]) + ->addRule('default', [ + 'type' => self::TYPE_STRING, + 'description' => 'Default value for attribute when not provided. Only null is optional', + 'default' => null, + 'example' => self::TYPE_DATETIME_EXAMPLE, + 'array' => false, + 'required' => false, + ]) + ; + } + + public array $conditions = [ + 'type' => self::TYPE_DATETIME + ]; + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'AttributeDatetime'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_ATTRIBUTE_DATETIME; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeEmail.php b/src/Appwrite/Utopia/Response/Model/AttributeEmail.php new file mode 100644 index 0000000000..078087dd4b --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/AttributeEmail.php @@ -0,0 +1,66 @@ +addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute Key.', + 'default' => '', + 'example' => 'userEmail', + ]) + ->addRule('type', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute type.', + 'default' => '', + 'example' => 'string', + ]) + ->addRule('format', [ + 'type' => self::TYPE_STRING, + 'description' => 'String format.', + 'default' => APP_DATABASE_ATTRIBUTE_EMAIL, + 'example' => APP_DATABASE_ATTRIBUTE_EMAIL, + ]) + ->addRule('default', [ + 'type' => self::TYPE_STRING, + 'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.', + 'default' => null, + 'required' => false, + 'example' => 'default@example.com', + ]) + ; + } + + public array $conditions = [ + 'type' => self::TYPE_STRING, + 'format' => \APP_DATABASE_ATTRIBUTE_EMAIL + ]; + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'AttributeEmail'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_ATTRIBUTE_EMAIL; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeEnum.php b/src/Appwrite/Utopia/Response/Model/AttributeEnum.php new file mode 100644 index 0000000000..992b62ee3a --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/AttributeEnum.php @@ -0,0 +1,73 @@ +addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute Key.', + 'default' => '', + 'example' => 'status', + ]) + ->addRule('type', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute type.', + 'default' => '', + 'example' => 'string', + ]) + ->addRule('elements', [ + 'type' => self::TYPE_STRING, + 'description' => 'Array of elements in enumerated type.', + 'default' => null, + 'example' => 'element', + 'array' => true, + ]) + ->addRule('format', [ + 'type' => self::TYPE_STRING, + 'description' => 'String format.', + 'default' => APP_DATABASE_ATTRIBUTE_ENUM, + 'example' => APP_DATABASE_ATTRIBUTE_ENUM, + ]) + ->addRule('default', [ + 'type' => self::TYPE_STRING, + 'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.', + 'default' => null, + 'required' => false, + 'example' => 'element', + ]) + ; + } + + public array $conditions = [ + 'type' => self::TYPE_STRING, + 'format' => \APP_DATABASE_ATTRIBUTE_ENUM + ]; + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'AttributeEnum'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_ATTRIBUTE_ENUM; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeFloat.php b/src/Appwrite/Utopia/Response/Model/AttributeFloat.php new file mode 100644 index 0000000000..266b89c330 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/AttributeFloat.php @@ -0,0 +1,73 @@ +addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute Key.', + 'default' => '', + 'example' => 'percentageCompleted', + ]) + ->addRule('type', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute type.', + 'default' => '', + 'example' => 'double', + ]) + ->addRule('min', [ + 'type' => self::TYPE_FLOAT, + 'description' => 'Minimum value to enforce for new documents.', + 'default' => null, + 'required' => false, + 'example' => 1.5, + ]) + ->addRule('max', [ + 'type' => self::TYPE_FLOAT, + 'description' => 'Maximum value to enforce for new documents.', + 'default' => null, + 'required' => false, + 'example' => 10.5, + ]) + ->addRule('default', [ + 'type' => self::TYPE_FLOAT, + 'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.', + 'default' => null, + 'required' => false, + 'example' => 2.5, + ]) + ; + } + + public array $conditions = [ + 'type' => self::TYPE_FLOAT, + ]; + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'AttributeFloat'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_ATTRIBUTE_FLOAT; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeIP.php b/src/Appwrite/Utopia/Response/Model/AttributeIP.php new file mode 100644 index 0000000000..cfa309317a --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/AttributeIP.php @@ -0,0 +1,66 @@ +addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute Key.', + 'default' => '', + 'example' => 'ipAddress', + ]) + ->addRule('type', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute type.', + 'default' => '', + 'example' => 'string', + ]) + ->addRule('format', [ + 'type' => self::TYPE_STRING, + 'description' => 'String format.', + 'default' => APP_DATABASE_ATTRIBUTE_IP, + 'example' => APP_DATABASE_ATTRIBUTE_IP, + ]) + ->addRule('default', [ + 'type' => self::TYPE_STRING, + 'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.', + 'default' => null, + 'required' => false, + 'example' => '192.0.2.0', + ]) + ; + } + + public array $conditions = [ + 'type' => self::TYPE_STRING, + 'format' => \APP_DATABASE_ATTRIBUTE_IP + ]; + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'AttributeIP'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_ATTRIBUTE_IP; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeInteger.php b/src/Appwrite/Utopia/Response/Model/AttributeInteger.php new file mode 100644 index 0000000000..fddfe57445 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/AttributeInteger.php @@ -0,0 +1,72 @@ +addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute Key.', + 'default' => '', + 'example' => 'count', + ]) + ->addRule('type', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute type.', + 'default' => '', + 'example' => 'integer', + ]) + ->addRule('min', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Minimum value to enforce for new documents.', + 'default' => null, + 'required' => false, + 'example' => 1, + ]) + ->addRule('max', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Maximum value to enforce for new documents.', + 'default' => null, + 'required' => false, + 'example' => 10, + ]) + ->addRule('default', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.', + 'default' => null, + 'required' => false, + 'example' => 10, + ]) + ; + } + + public array $conditions = [ + 'type' => self::TYPE_INTEGER, + ]; + + /** + * Get Name * + * @return string + */ + public function getName(): string + { + return 'AttributeInteger'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_ATTRIBUTE_INTEGER; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeList.php b/src/Appwrite/Utopia/Response/Model/AttributeList.php new file mode 100644 index 0000000000..8b04475a14 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/AttributeList.php @@ -0,0 +1,58 @@ +addRule('total', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total number of attributes in the given collection.', + 'default' => 0, + 'example' => 5, + ]) + ->addRule('attributes', [ + 'type' => [ + Response::MODEL_ATTRIBUTE_BOOLEAN, + Response::MODEL_ATTRIBUTE_INTEGER, + Response::MODEL_ATTRIBUTE_FLOAT, + Response::MODEL_ATTRIBUTE_EMAIL, + Response::MODEL_ATTRIBUTE_ENUM, + Response::MODEL_ATTRIBUTE_URL, + Response::MODEL_ATTRIBUTE_IP, + Response::MODEL_ATTRIBUTE_DATETIME, + Response::MODEL_ATTRIBUTE_RELATIONSHIP, + Response::MODEL_ATTRIBUTE_STRING // needs to be last, since its condition would dominate any other string attribute + ], + 'description' => 'List of attributes.', + 'default' => [], + 'array' => true + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'Attributes List'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_ATTRIBUTE_LIST; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php b/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php new file mode 100644 index 0000000000..d88fbd1530 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php @@ -0,0 +1,96 @@ +addRule('relatedCollection', [ + 'type' => self::TYPE_STRING, + 'description' => 'The ID of the related collection.', + 'default' => null, + 'example' => 'collection', + ]) + ->addRule('relationType', [ + 'type' => self::TYPE_STRING, + 'description' => 'The type of the relationship.', + 'default' => '', + 'example' => 'oneToOne|oneToMany|manyToOne|manyToMany', + ]) + ->addRule('twoWay', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Is the relationship two-way?', + 'default' => false, + 'example' => false, + ]) + ->addRule('twoWayKey', [ + 'type' => self::TYPE_STRING, + 'description' => 'The key of the two-way relationship.', + 'default' => '', + 'example' => 'string', + ]) + ->addRule('onDelete', [ + 'type' => self::TYPE_STRING, + 'description' => 'How deleting the parent document will propagate to child documents.', + 'default' => 'restrict', + 'example' => 'restrict|cascade|setNull', + ]) + ->addRule('side', [ + 'type' => self::TYPE_STRING, + 'description' => 'Whether this is the parent or child side of the relationship', + 'default' => '', + 'example' => 'parent|child', + ]) + ; + } + + public array $conditions = [ + 'type' => self::TYPE_RELATIONSHIP, + ]; + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'AttributeRelationship'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_ATTRIBUTE_RELATIONSHIP; + } + + /** + * Process Document before returning it to the client + * + * @return Document + */ + public function filter(Document $document): Document + { + $options = $document->getAttribute('options'); + if (!\is_null($options)) { + $document->setAttribute('relatedCollection', $options['relatedCollection']); + $document->setAttribute('relationType', $options['relationType']); + $document->setAttribute('twoWay', $options['twoWay']); + $document->setAttribute('twoWayKey', $options['twoWayKey']); + $document->setAttribute('side', $options['side']); + $document->setAttribute('onDelete', $options['onDelete']); + } + return $document; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeString.php b/src/Appwrite/Utopia/Response/Model/AttributeString.php new file mode 100644 index 0000000000..12bb42009d --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/AttributeString.php @@ -0,0 +1,53 @@ +addRule('size', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Attribute size.', + 'default' => 0, + 'example' => 128, + ]) + ->addRule('default', [ + 'type' => self::TYPE_STRING, + 'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.', + 'default' => null, + 'required' => false, + 'example' => 'default', + ]) + ; + } + + public array $conditions = [ + 'type' => self::TYPE_STRING, + ]; + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'AttributeString'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_ATTRIBUTE_STRING; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeURL.php b/src/Appwrite/Utopia/Response/Model/AttributeURL.php new file mode 100644 index 0000000000..633d5b49d7 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/AttributeURL.php @@ -0,0 +1,66 @@ +addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute Key.', + 'default' => '', + 'example' => 'githubUrl', + ]) + ->addRule('type', [ + 'type' => self::TYPE_STRING, + 'description' => 'Attribute type.', + 'default' => '', + 'example' => 'string', + ]) + ->addRule('format', [ + 'type' => self::TYPE_STRING, + 'description' => 'String format.', + 'default' => APP_DATABASE_ATTRIBUTE_URL, + 'example' => APP_DATABASE_ATTRIBUTE_URL, + ]) + ->addRule('default', [ + 'type' => self::TYPE_STRING, + 'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.', + 'default' => null, + 'required' => false, + 'example' => 'http://example.com', + ]) + ; + } + + public array $conditions = [ + 'type' => self::TYPE_STRING, + 'format' => \APP_DATABASE_ATTRIBUTE_URL + ]; + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'AttributeURL'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_ATTRIBUTE_URL; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/BaseList.php b/src/Appwrite/Utopia/Response/Model/BaseList.php index 1fa3197ba7..dea5d476f2 100644 --- a/src/Appwrite/Utopia/Response/Model/BaseList.php +++ b/src/Appwrite/Utopia/Response/Model/BaseList.php @@ -32,9 +32,11 @@ class BaseList extends Model if ($paging) { $namesWithCap = [ - 'rows', 'tables', 'users', 'files', 'buckets', 'functions', - 'deployments', 'executions', 'projects', 'webhooks', 'keys', - 'platforms', 'rules', 'memberships', 'teams' + 'rows', 'tables', // new api + 'documents', 'collections', // legacy api + 'users', 'files', 'buckets', 'functions', + 'deployments', 'executions', 'projects', + 'webhooks', 'keys', 'platforms', 'rules', 'memberships', 'teams' ]; if (\in_array($name, $namesWithCap)) { diff --git a/src/Appwrite/Utopia/Response/Model/Collection.php b/src/Appwrite/Utopia/Response/Model/Collection.php new file mode 100644 index 0000000000..2c2bf0cca8 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/Collection.php @@ -0,0 +1,109 @@ +addRule('$id', [ + 'type' => self::TYPE_STRING, + 'description' => 'Collection ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Collection creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Collection update date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$permissions', [ + 'type' => self::TYPE_STRING, + 'description' => 'Collection permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', + 'default' => '', + 'example' => ['read("any")'], + 'array' => true + ]) + ->addRule('databaseId', [ + 'type' => self::TYPE_STRING, + 'description' => 'Database ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('name', [ + 'type' => self::TYPE_STRING, + 'description' => 'Collection name.', + 'default' => '', + 'example' => 'My Collection', + ]) + ->addRule('enabled', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Collection enabled. Can be \'enabled\' or \'disabled\'. When disabled, the collection is inaccessible to users, but remains accessible to Server SDKs using API keys.', + 'default' => true, + 'example' => false, + ]) + ->addRule('documentSecurity', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Whether document-level permissions are enabled. [Learn more about permissions](https://appwrite.io/docs/permissions).', + 'default' => '', + 'example' => true, + ]) + ->addRule('attributes', [ + 'type' => [ + Response::MODEL_ATTRIBUTE_BOOLEAN, + Response::MODEL_ATTRIBUTE_INTEGER, + Response::MODEL_ATTRIBUTE_FLOAT, + Response::MODEL_ATTRIBUTE_EMAIL, + Response::MODEL_ATTRIBUTE_ENUM, + Response::MODEL_ATTRIBUTE_URL, + Response::MODEL_ATTRIBUTE_IP, + Response::MODEL_ATTRIBUTE_DATETIME, + Response::MODEL_ATTRIBUTE_RELATIONSHIP, + Response::MODEL_ATTRIBUTE_STRING, // needs to be last, since its condition would dominate any other string attribute + ], + 'description' => 'Collection attributes.', + 'default' => [], + 'example' => new \stdClass(), + 'array' => true, + ]) + ->addRule('indexes', [ + 'type' => Response::MODEL_INDEX, + 'description' => 'Collection indexes.', + 'default' => [], + 'example' => new \stdClass(), + 'array' => true + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'Collection'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_COLLECTION; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/Document.php b/src/Appwrite/Utopia/Response/Model/Document.php new file mode 100644 index 0000000000..41a10cee89 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/Document.php @@ -0,0 +1,92 @@ +addRule('$id', [ + 'type' => self::TYPE_STRING, + 'description' => 'Document ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('$collectionId', [ + 'type' => self::TYPE_STRING, + 'description' => 'Collection ID.', + 'default' => '', + 'example' => '5e5ea5c15117e', + ]) + ->addRule('$databaseId', [ + 'type' => self::TYPE_STRING, + 'description' => 'Database ID.', + 'default' => '', + 'example' => '5e5ea5c15117e', + ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Document creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Document update date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$permissions', [ + 'type' => self::TYPE_STRING, + 'description' => 'Document permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', + 'default' => '', + 'example' => ['read("any")'], + 'array' => true, + ]); + } + + public function filter(DatabaseDocument $document): DatabaseDocument + { + $document->removeAttribute('$internalId'); + $document->removeAttribute('$collection'); + $document->removeAttribute('$tenant'); + + foreach ($document->getAttributes() as $attribute) { + if (\is_array($attribute)) { + foreach ($attribute as $subAttribute) { + if ($subAttribute instanceof DatabaseDocument) { + $this->filter($subAttribute); + } + } + } elseif ($attribute instanceof DatabaseDocument) { + $this->filter($attribute); + } + } + + return $document; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/UsageCollection.php b/src/Appwrite/Utopia/Response/Model/UsageCollection.php new file mode 100644 index 0000000000..b2336d65ba --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/UsageCollection.php @@ -0,0 +1,54 @@ +addRule('range', [ + 'type' => self::TYPE_STRING, + 'description' => 'Time range of the usage stats.', + 'default' => '', + 'example' => '30d', + ]) + ->addRule('documentsTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of of documents.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('documents', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of documents per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'UsageCollection'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_USAGE_COLLECTION; + } +} From 7f023f29c56ee7123026d22e060ce2f17d222dfa Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 7 May 2025 11:30:31 +0530 Subject: [PATCH 072/343] update: keep both tables and collections api errors. --- app/config/errors.php | 122 ++++++++++++++++++++++++++++-- app/controllers/general.php | 38 ++++++++-- src/Appwrite/Extend/Exception.php | 26 +++++++ 3 files changed, 174 insertions(+), 12 deletions(-) diff --git a/app/config/errors.php b/app/config/errors.php index 979bf43f7d..c1121cb98e 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -71,7 +71,7 @@ return [ ], Exception::GENERAL_QUERY_LIMIT_EXCEEDED => [ 'name' => Exception::GENERAL_QUERY_LIMIT_EXCEEDED, - 'description' => 'Query limit exceeded for the current column. Usage of more than 100 query values on a single column is prohibited.', + 'description' => 'Query limit exceeded for the current attribute/column. Usage of more than 100 query values on a single column is prohibited.', 'code' => 400, ], Exception::GENERAL_QUERY_INVALID => [ @@ -653,7 +653,24 @@ return [ ], Exception::DATABASE_QUERY_ORDER_NULL => [ 'name' => Exception::DATABASE_QUERY_ORDER_NULL, - 'description' => 'The order column had a null value. Cursor pagination requires all rows order column values are non-null.', + 'description' => 'The order attribute/column had a null value. Cursor pagination requires all documents/rows order attribute/column values are non-null.', + 'code' => 400, + ], + + /** Collections */ + Exception::COLLECTION_NOT_FOUND => [ + 'name' => Exception::COLLECTION_NOT_FOUND, + 'description' => 'Collection with the requested ID could not be found.', + 'code' => 404, + ], + Exception::COLLECTION_ALREADY_EXISTS => [ + 'name' => Exception::COLLECTION_ALREADY_EXISTS, + 'description' => 'A collection with the requested ID already exists. Try again with a different ID or use ID.unique() to generate a unique ID.', + 'code' => 409, + ], + Exception::COLLECTION_LIMIT_EXCEEDED => [ + 'name' => Exception::COLLECTION_LIMIT_EXCEEDED, + 'description' => 'The maximum number of collections has been reached.', 'code' => 400, ], @@ -674,6 +691,43 @@ return [ 'code' => 400, ], + /** Documents */ + Exception::DOCUMENT_NOT_FOUND => [ + 'name' => Exception::DOCUMENT_NOT_FOUND, + 'description' => 'Document with the requested ID could not be found.', + 'code' => 404, + ], + Exception::DOCUMENT_INVALID_STRUCTURE => [ + 'name' => Exception::DOCUMENT_INVALID_STRUCTURE, + 'description' => 'The document structure is invalid. Please ensure the attributes match the collection definition.', + 'code' => 400, + ], + Exception::DOCUMENT_MISSING_DATA => [ + 'name' => Exception::DOCUMENT_MISSING_DATA, + 'description' => 'The document data is missing. Try again with document data populated', + 'code' => 400, + ], + Exception::DOCUMENT_MISSING_PAYLOAD => [ + 'name' => Exception::DOCUMENT_MISSING_PAYLOAD, + 'description' => 'The document data and permissions are missing. You must provide either document data or permissions to be updated.', + 'code' => 400, + ], + Exception::DOCUMENT_ALREADY_EXISTS => [ + 'name' => Exception::DOCUMENT_ALREADY_EXISTS, + 'description' => 'Document with the requested ID already exists. Try again with a different ID or use ID.unique() to generate a unique ID.', + 'code' => 409, + ], + Exception::DOCUMENT_UPDATE_CONFLICT => [ + 'name' => Exception::DOCUMENT_UPDATE_CONFLICT, + 'description' => 'Remote document is newer than local.', + 'code' => 409, + ], + Exception::DOCUMENT_DELETE_RESTRICTED => [ + 'name' => Exception::DOCUMENT_DELETE_RESTRICTED, + 'description' => 'Document cannot be deleted because it is referenced by another document.', + 'code' => 403, + ], + /** Rows */ Exception::ROW_NOT_FOUND => [ 'name' => Exception::ROW_NOT_FOUND, @@ -711,6 +765,65 @@ return [ 'code' => 403, ], + /** Attributes */ + Exception::ATTRIBUTE_NOT_FOUND => [ + 'name' => Exception::ATTRIBUTE_NOT_FOUND, + 'description' => 'Attribute with the requested ID could not be found.', + 'code' => 404, + ], + Exception::ATTRIBUTE_UNKNOWN => [ + 'name' => Exception::ATTRIBUTE_UNKNOWN, + 'description' => 'The attribute required for the index could not be found. Please confirm all your attributes are in the available state.', + 'code' => 400, + ], + Exception::ATTRIBUTE_NOT_AVAILABLE => [ + 'name' => Exception::ATTRIBUTE_NOT_AVAILABLE, + 'description' => 'The requested attribute is not yet available. Please try again later.', + 'code' => 400, + ], + Exception::ATTRIBUTE_FORMAT_UNSUPPORTED => [ + 'name' => Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, + 'description' => 'The requested attribute format is not supported.', + 'code' => 400, + ], + Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED => [ + 'name' => Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, + 'description' => 'Default values cannot be set for array or required attributes.', + 'code' => 400, + ], + Exception::ATTRIBUTE_ALREADY_EXISTS => [ + 'name' => Exception::ATTRIBUTE_ALREADY_EXISTS, + 'description' => 'Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.', + 'code' => 409, + ], + Exception::ATTRIBUTE_LIMIT_EXCEEDED => [ + 'name' => Exception::ATTRIBUTE_LIMIT_EXCEEDED, + 'description' => 'The maximum number or size of attributes for this collection has been reached.', + 'code' => 400, + ], + Exception::ATTRIBUTE_VALUE_INVALID => [ + 'name' => Exception::ATTRIBUTE_VALUE_INVALID, + 'description' => 'The attribute value is invalid. Please check the type, range and value of the attribute.', + 'code' => 400, + ], + Exception::ATTRIBUTE_TYPE_INVALID => [ + 'name' => Exception::ATTRIBUTE_TYPE_INVALID, + 'description' => 'The attribute type is invalid.', + 'code' => 400, + ], + Exception::ATTRIBUTE_INVALID_RESIZE => [ + 'name' => Exception::ATTRIBUTE_INVALID_RESIZE, + 'description' => "Existing data is too large for new size, truncate your existing data then try again.", + 'code' => 400, + ], + + /** Exists for both Attributes & Columns */ + Exception::RELATIONSHIP_VALUE_INVALID => [ + 'name' => Exception::RELATIONSHIP_VALUE_INVALID, + 'description' => 'The relationship value is invalid.', + 'code' => 400, + ], + /** Columns */ Exception::COLUMN_NOT_FOUND => [ 'name' => Exception::COLUMN_NOT_FOUND, @@ -757,11 +870,6 @@ return [ 'description' => 'The column type is invalid.', 'code' => 400, ], - Exception::RELATIONSHIP_VALUE_INVALID => [ - 'name' => Exception::RELATIONSHIP_VALUE_INVALID, - 'description' => 'The relationship value is invalid.', - 'code' => 400, - ], Exception::COLUMN_INVALID_RESIZE => [ 'name' => Exception::COLUMN_INVALID_RESIZE, 'description' => "Existing data is too large for new size, truncate your existing data then try again.", diff --git a/app/controllers/general.php b/app/controllers/general.php index cc6739e790..da68d4758c 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1148,6 +1148,9 @@ App::error() Console::error('[Error] Line: ' . $line); } + // routes like /tables, /tables/:tableId, etc. + $isTablesAPI = str_contains($route->getPath(), '/databases/:databaseId/tables'); + switch ($class) { case 'Utopia\Exception': $error = new AppwriteException(AppwriteException::GENERAL_UNKNOWN, $message, $code, $error); @@ -1161,7 +1164,12 @@ App::error() } break; case 'Utopia\Database\Exception\Conflict': - $error = new AppwriteException(AppwriteException::ROW_UPDATE_CONFLICT, previous: $error); + $error = new AppwriteException( + $isTablesAPI + ? AppwriteException::ROW_UPDATE_CONFLICT + : AppwriteException::DOCUMENT_UPDATE_CONFLICT, + previous: $error + ); break; case 'Utopia\Database\Exception\Timeout': $error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error); @@ -1170,13 +1178,27 @@ App::error() $error = new AppwriteException(AppwriteException::GENERAL_QUERY_INVALID, $error->getMessage(), previous: $error); break; case 'Utopia\Database\Exception\Structure': - $error = new AppwriteException(AppwriteException::ROW_INVALID_STRUCTURE, $error->getMessage(), previous: $error); + $error = new AppwriteException( + $isTablesAPI + ? AppwriteException::ROW_INVALID_STRUCTURE + : AppwriteException::DOCUMENT_INVALID_STRUCTURE, + $error->getMessage(), + previous: $error + ); break; case 'Utopia\Database\Exception\Duplicate': - $error = new AppwriteException(AppwriteException::ROW_ALREADY_EXISTS); + $error = new AppwriteException( + $isTablesAPI + ? AppwriteException::ROW_ALREADY_EXISTS + : AppwriteException::DOCUMENT_ALREADY_EXISTS + ); break; case 'Utopia\Database\Exception\Restricted': - $error = new AppwriteException(AppwriteException::ROW_DELETE_RESTRICTED); + $error = new AppwriteException( + $isTablesAPI + ? AppwriteException::ROW_DELETE_RESTRICTED + : AppwriteException::DOCUMENT_DELETE_RESTRICTED + ); break; case 'Utopia\Database\Exception\Authorization': $error = new AppwriteException(AppwriteException::USER_UNAUTHORIZED); @@ -1185,7 +1207,13 @@ App::error() $error = new AppwriteException(AppwriteException::RELATIONSHIP_VALUE_INVALID, $error->getMessage(), previous: $error); break; case 'Utopia\Database\Exception\NotFound': - $error = new AppwriteException(AppwriteException::TABLE_NOT_FOUND, $error->getMessage(), previous: $error); + $error = new AppwriteException( + $isTablesAPI + ? AppwriteException::TABLE_NOT_FOUND + : AppwriteException::COLLECTION_NOT_FOUND, + $error->getMessage(), + previous: $error + ); break; case 'Utopia\Database\Exception\Dependency': $error = new AppwriteException(AppwriteException::INDEX_DEPENDENCY, null, previous: $error); diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 31a52a6a04..15b964577d 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -192,10 +192,24 @@ class Exception extends \Exception public const DATABASE_QUERY_ORDER_NULL = 'database_query_order_null'; /** Collections */ + public const COLLECTION_NOT_FOUND = 'collection_not_found'; + public const COLLECTION_ALREADY_EXISTS = 'collection_already_exists'; + public const COLLECTION_LIMIT_EXCEEDED = 'collection_limit_exceeded'; + + /** Tables */ public const TABLE_NOT_FOUND = 'table_not_found'; public const TABLE_ALREADY_EXISTS = 'table_already_exists'; public const TABLE_LIMIT_EXCEEDED = 'table_limit_exceeded'; + /** Documents */ + public const DOCUMENT_NOT_FOUND = 'document_not_found'; + public const DOCUMENT_INVALID_STRUCTURE = 'document_invalid_structure'; + public const DOCUMENT_MISSING_DATA = 'document_missing_data'; + public const DOCUMENT_MISSING_PAYLOAD = 'document_missing_payload'; + public const DOCUMENT_ALREADY_EXISTS = 'document_already_exists'; + public const DOCUMENT_UPDATE_CONFLICT = 'document_update_conflict'; + public const DOCUMENT_DELETE_RESTRICTED = 'document_delete_restricted'; + /** Rows */ public const ROW_NOT_FOUND = 'row_not_found'; public const ROW_INVALID_STRUCTURE = 'row_invalid_structure'; @@ -205,6 +219,18 @@ class Exception extends \Exception public const ROW_UPDATE_CONFLICT = 'row_update_conflict'; public const ROW_DELETE_RESTRICTED = 'row_delete_restricted'; + /** Attributes */ + public const ATTRIBUTE_NOT_FOUND = 'attribute_not_found'; + public const ATTRIBUTE_UNKNOWN = 'attribute_unknown'; + public const ATTRIBUTE_NOT_AVAILABLE = 'attribute_not_available'; + public const ATTRIBUTE_FORMAT_UNSUPPORTED = 'attribute_format_unsupported'; + public const ATTRIBUTE_DEFAULT_UNSUPPORTED = 'attribute_default_unsupported'; + public const ATTRIBUTE_ALREADY_EXISTS = 'attribute_already_exists'; + public const ATTRIBUTE_LIMIT_EXCEEDED = 'attribute_limit_exceeded'; + public const ATTRIBUTE_VALUE_INVALID = 'attribute_value_invalid'; + public const ATTRIBUTE_TYPE_INVALID = 'attribute_type_invalid'; + public const ATTRIBUTE_INVALID_RESIZE = 'attribute_invalid_resize'; + /** Columns */ public const COLUMN_NOT_FOUND = 'column_not_found'; public const COLUMN_UNKNOWN = 'column_unknown'; From 8610687b873df10bfb072b2f4e7f4d8674fabdf3 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 7 May 2025 13:23:27 +0530 Subject: [PATCH 073/343] update: events schema, response models for database usages. --- app/config/events.php | 2 +- .../Databases/Http/Databases/Usage/Get.php | 8 +- .../Databases/Http/Databases/Usage/XList.php | 8 +- src/Appwrite/Utopia/Response.php | 5 + .../Utopia/Response/Model/ColumnIndex.php | 94 +++++++++++++++++++ src/Appwrite/Utopia/Response/Model/Index.php | 15 +-- src/Appwrite/Utopia/Response/Model/Table.php | 2 +- .../Utopia/Response/Model/UsageDatabase.php | 17 ++-- .../Utopia/Response/Model/UsageDatabases.php | 17 ++-- .../Utopia/Response/Model/UsageProject.php | 5 +- 10 files changed, 131 insertions(+), 42 deletions(-) create mode 100644 src/Appwrite/Utopia/Response/Model/ColumnIndex.php diff --git a/app/config/events.php b/app/config/events.php index 182aa91363..e7b079050c 100644 --- a/app/config/events.php +++ b/app/config/events.php @@ -114,7 +114,7 @@ return [ ], ], 'indexes' => [ - '$model' => Response::MODEL_INDEX, + '$model' => Response::MODEL_COLUMN_INDEX, '$resource' => true, '$description' => 'This event triggers on any indexes event.', 'create' => [ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php index c7ae2e4d81..c4105effa0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -123,13 +123,13 @@ class Get extends Action $response->dynamic(new Document([ 'range' => $range, - 'tablesTotal' => $usage[$metrics[0]]['total'], - 'rowsTotal' => $usage[$metrics[1]]['total'], + 'collectionsTotal' => $usage[$metrics[0]]['total'], + 'documentsTotal' => $usage[$metrics[1]]['total'], 'storageTotal' => $usage[$metrics[2]]['total'], 'databaseReadsTotal' => $usage[$metrics[3]]['total'], 'databaseWritesTotal' => $usage[$metrics[4]]['total'], - 'tables' => $usage[$metrics[0]]['data'], - 'rows' => $usage[$metrics[1]]['data'], + 'collections' => $usage[$metrics[0]]['data'], + 'documents' => $usage[$metrics[1]]['data'], 'storage' => $usage[$metrics[2]]['data'], 'databaseReads' => $usage[$metrics[3]]['data'], 'databaseWrites' => $usage[$metrics[4]]['data'], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php index 8737585e8c..0078d54a4b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -116,14 +116,14 @@ class XList extends Action $response->dynamic(new Document([ 'range' => $range, 'databasesTotal' => $usage[$metrics[0]]['total'], - 'tablesTotal' => $usage[$metrics[1]]['total'], - 'rowsTotal' => $usage[$metrics[2]]['total'], + 'collectionsTotal' => $usage[$metrics[1]]['total'], + 'documentsTotal' => $usage[$metrics[2]]['total'], 'storageTotal' => $usage[$metrics[3]]['total'], 'databasesReadsTotal' => $usage[$metrics[4]]['total'], 'databasesWritesTotal' => $usage[$metrics[5]]['total'], 'databases' => $usage[$metrics[0]]['data'], - 'tables' => $usage[$metrics[1]]['data'], - 'rows' => $usage[$metrics[2]]['data'], + 'collections' => $usage[$metrics[1]]['data'], + 'documents' => $usage[$metrics[2]]['data'], 'storage' => $usage[$metrics[3]]['data'], 'databasesReads' => $usage[$metrics[4]]['data'], 'databasesWrites' => $usage[$metrics[5]]['data'], diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index c72a01c79a..cec275869a 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -38,6 +38,7 @@ use Appwrite\Utopia\Response\Model\ColumnDatetime; use Appwrite\Utopia\Response\Model\ColumnEmail; use Appwrite\Utopia\Response\Model\ColumnEnum; use Appwrite\Utopia\Response\Model\ColumnFloat; +use Appwrite\Utopia\Response\Model\ColumnIndex; use Appwrite\Utopia\Response\Model\ColumnInteger; use Appwrite\Utopia\Response\Model\ColumnIP; use Appwrite\Utopia\Response\Model\ColumnList; @@ -182,6 +183,8 @@ class Response extends SwooleResponse public const MODEL_TABLE_LIST = 'tableList'; public const MODEL_INDEX = 'index'; public const MODEL_INDEX_LIST = 'indexList'; + public const MODEL_COLUMN_INDEX = 'columnIndex'; + public const MODEL_COLUMN_INDEX_LIST = 'columnIndexList'; public const MODEL_DOCUMENT = 'document'; public const MODEL_DOCUMENT_LIST = 'documentList'; public const MODEL_ROW = 'row'; @@ -416,6 +419,7 @@ class Response extends SwooleResponse ->setModel(new BaseList('Collections List', self::MODEL_COLLECTION_LIST, 'collections', self::MODEL_COLLECTION)) ->setModel(new BaseList('Databases List', self::MODEL_DATABASE_LIST, 'databases', self::MODEL_DATABASE)) ->setModel(new BaseList('Indexes List', self::MODEL_INDEX_LIST, 'indexes', self::MODEL_INDEX)) + ->setModel(new BaseList('Column Indexes List', self::MODEL_COLUMN_INDEX_LIST, 'indexes', self::MODEL_COLUMN_INDEX)) ->setModel(new BaseList('Users List', self::MODEL_USER_LIST, 'users', self::MODEL_USER)) ->setModel(new BaseList('Sessions List', self::MODEL_SESSION_LIST, 'sessions', self::MODEL_SESSION)) ->setModel(new BaseList('Identities List', self::MODEL_IDENTITY_LIST, 'identities', self::MODEL_IDENTITY)) @@ -493,6 +497,7 @@ class Response extends SwooleResponse ->setModel(new ColumnDatetime()) ->setModel(new ColumnRelationship()) ->setModel(new Index()) + ->setModel(new ColumnIndex()) ->setModel(new Row()) ->setModel(new ModelDocument()) ->setModel(new Log()) diff --git a/src/Appwrite/Utopia/Response/Model/ColumnIndex.php b/src/Appwrite/Utopia/Response/Model/ColumnIndex.php new file mode 100644 index 0000000000..8c632266ef --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/ColumnIndex.php @@ -0,0 +1,94 @@ +addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Index Key.', + 'default' => '', + 'example' => 'index1', + ]) + ->addRule('type', [ + 'type' => self::TYPE_STRING, + 'description' => 'Index type.', + 'default' => '', + 'example' => 'primary', + ]) + ->addRule('status', [ + 'type' => self::TYPE_STRING, + 'description' => 'Index status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`', + 'default' => '', + 'example' => 'available', + ]) + ->addRule('error', [ + 'type' => self::TYPE_STRING, + 'description' => 'Error message. Displays error generated on failure of creating or deleting an index.', + 'default' => '', + 'example' => 'string', + ]) + ->addRule('columns', [ + 'type' => self::TYPE_STRING, + 'description' => 'Index columns.', + 'default' => [], + 'example' => [], + 'array' => true, + ]) + ->addRule('orders', [ + 'type' => self::TYPE_STRING, + 'description' => 'Index orders.', + 'default' => [], + 'example' => [], + 'array' => true, + 'required' => false, + ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Index creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Index update date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]); + } + + /** + * Get Name + */ + public function getName(): string + { + return 'Index'; + } + + /** + * Get Collection + */ + public function getType(): string + { + return Response::MODEL_COLUMN_INDEX; + } + + public function filter(Document $document): Document + { + + $columns = $document->getAttribute('attributes', []); + $document + ->removeAttribute('attributes') + ->setAttribute('columns', $columns); + + return $document; + + } +} diff --git a/src/Appwrite/Utopia/Response/Model/Index.php b/src/Appwrite/Utopia/Response/Model/Index.php index e18a9db334..2d795ad439 100644 --- a/src/Appwrite/Utopia/Response/Model/Index.php +++ b/src/Appwrite/Utopia/Response/Model/Index.php @@ -4,7 +4,6 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; -use Utopia\Database\Document; class Index extends Model { @@ -35,7 +34,7 @@ class Index extends Model 'default' => '', 'example' => 'string', ]) - ->addRule('columns', [ + ->addRule('attributes', [ 'type' => self::TYPE_STRING, 'description' => 'Index attributes.', 'default' => [], @@ -79,16 +78,4 @@ class Index extends Model { return Response::MODEL_INDEX; } - - public function filter(Document $document): Document - { - - $columns = $document->getAttribute('attributes', []); - $document - ->removeAttribute('attributes') - ->setAttribute('columns', $columns); - - return $document; - - } } diff --git a/src/Appwrite/Utopia/Response/Model/Table.php b/src/Appwrite/Utopia/Response/Model/Table.php index 1855f471b1..1b890d9e60 100644 --- a/src/Appwrite/Utopia/Response/Model/Table.php +++ b/src/Appwrite/Utopia/Response/Model/Table.php @@ -79,7 +79,7 @@ class Table extends Model 'array' => true, ]) ->addRule('indexes', [ - 'type' => Response::MODEL_INDEX, + 'type' => Response::MODEL_COLUMN_INDEX, 'description' => 'Table indexes.', 'default' => [], 'example' => new \stdClass(), diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php index a3212017a4..3adabae4c1 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php @@ -5,6 +5,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; +// TODO: check what do we use for - collectionsTotal, documentsTotal, collections, documents class UsageDatabase extends Model { public function __construct() @@ -16,15 +17,15 @@ class UsageDatabase extends Model 'default' => '', 'example' => '30d', ]) - ->addRule('tablesTotal', [ + ->addRule('collectionsTotal', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of tables.', + 'description' => 'Total aggregated number of collections.', 'default' => 0, 'example' => 0, ]) - ->addRule('rowsTotal', [ + ->addRule('collectionsTotal', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of rows.', + 'description' => 'Total aggregated number of documents.', 'default' => 0, 'example' => 0, ]) @@ -46,16 +47,16 @@ class UsageDatabase extends Model 'default' => 0, 'example' => 0, ]) - ->addRule('tables', [ + ->addRule('collections', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of tables per period.', + 'description' => 'Aggregated number of collections per period.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('rows', [ + ->addRule('documents', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of rows per period.', + 'description' => 'Aggregated number of documents per period.', 'default' => [], 'example' => [], 'array' => true diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php index 11392f6efb..ae93182c0f 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php @@ -5,6 +5,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; +// TODO: check what do we use for - collectionsTotal, documentsTotal, collections, documents class UsageDatabases extends Model { public function __construct() @@ -22,15 +23,15 @@ class UsageDatabases extends Model 'default' => 0, 'example' => 0, ]) - ->addRule('tablesTotal', [ + ->addRule('collectionsTotal', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of tables.', + 'description' => 'Total aggregated number of collections.', 'default' => 0, 'example' => 0, ]) - ->addRule('rowsTotal', [ + ->addRule('documentsTotal', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of rows.', + 'description' => 'Total aggregated number of documents.', 'default' => 0, 'example' => 0, ]) @@ -59,16 +60,16 @@ class UsageDatabases extends Model 'example' => [], 'array' => true ]) - ->addRule('tables', [ + ->addRule('collections', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of tables per period.', + 'description' => 'Aggregated number of collections per period.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('rows', [ + ->addRule('documents', [ 'type' => Response::MODEL_METRIC, - 'description' => 'Aggregated number of rows per period.', + 'description' => 'Aggregated number of documents per period.', 'default' => [], 'example' => [], 'array' => true diff --git a/src/Appwrite/Utopia/Response/Model/UsageProject.php b/src/Appwrite/Utopia/Response/Model/UsageProject.php index b79cd85bed..70f8003cfd 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageProject.php +++ b/src/Appwrite/Utopia/Response/Model/UsageProject.php @@ -5,6 +5,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; +// TODO: check what do we use for - documents. class UsageProject extends Model { public function __construct() @@ -16,9 +17,9 @@ class UsageProject extends Model 'default' => 0, 'example' => 0, ]) - ->addRule('rowsTotal', [ + ->addRule('documentsTotal', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Total aggregated number of rows.', + 'description' => 'Total aggregated number of documents.', 'default' => 0, 'example' => 0, ]) From f2f23be648f9c3c8c1e07ee073a4c35f3f1f7f5c Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 7 May 2025 14:11:28 +0530 Subject: [PATCH 074/343] update: events, errors, realtime. --- app/config/errors.php | 2 +- app/config/events.php | 2 +- app/config/templates/function.php | 5 +- src/Appwrite/Event/Database.php | 56 ++++++++++++- src/Appwrite/Messaging/Adapter/Realtime.php | 7 +- .../Modules/Databases/Workers/Databases.php | 78 ++++++++++++------- 6 files changed, 114 insertions(+), 36 deletions(-) diff --git a/app/config/errors.php b/app/config/errors.php index c1121cb98e..182b6286e8 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -71,7 +71,7 @@ return [ ], Exception::GENERAL_QUERY_LIMIT_EXCEEDED => [ 'name' => Exception::GENERAL_QUERY_LIMIT_EXCEEDED, - 'description' => 'Query limit exceeded for the current attribute/column. Usage of more than 100 query values on a single column is prohibited.', + 'description' => 'Query limit exceeded for the current attribute/column. Usage of more than 100 query values on a single attribute/column is prohibited.', 'code' => 400, ], Exception::GENERAL_QUERY_INVALID => [ diff --git a/app/config/events.php b/app/config/events.php index e7b079050c..b0e6b9f5fc 100644 --- a/app/config/events.php +++ b/app/config/events.php @@ -152,7 +152,7 @@ return [ 'documents' => [ '$model' => Response::MODEL_DOCUMENT, '$resource' => true, - '$description' => 'This event triggers on any document event.', + '$description' => 'This event triggers on any documents event.', 'create' => [ '$description' => 'This event triggers when a document is created.', ], diff --git a/app/config/templates/function.php b/app/config/templates/function.php index b017281dbe..960bc1d65e 100644 --- a/app/config/templates/function.php +++ b/app/config/templates/function.php @@ -1395,7 +1395,10 @@ return [ 'score' => 5, 'tagline' => 'Convert text to speech using the Hugging Face inference API.', 'permissions' => ['any'], - 'events' => ['databases.*.tables.*.rows.*.create'], + 'events' => [ + 'databases.*.tables.*.rows.*.create', + 'databases.*.collections.*.documents.*.create', + ], 'cron' => '', 'timeout' => 15, 'useCases' => ['ai'], diff --git a/src/Appwrite/Event/Database.php b/src/Appwrite/Event/Database.php index 797574d2fc..be73614dc1 100644 --- a/src/Appwrite/Event/Database.php +++ b/src/Appwrite/Event/Database.php @@ -10,8 +10,15 @@ class Database extends Event { protected string $type = ''; protected ?Document $database = null; - protected ?Document $table = null; + + // tables api protected ?Document $row = null; + protected ?Document $table = null; + + // collections api + protected ?Document $document = null; + protected ?Document $collection = null; + public function __construct(protected Publisher $publisher) { @@ -99,6 +106,51 @@ class Database extends Event return $this->row; } + /** + * Set the collection for this database event. + * + * @param Document $collection + * @return self + */ + public function setCollection(Document $collection): self + { + $this->collection = $collection; + + return $this; + } + + /** + * Returns set collection for this event. + * + * @return null|Document + */ + public function getCollection(): ?Document + { + return $this->collection; + } + + /** + * Set the document for this database event. + * + * @param Document $document + * @return self + */ + public function setDocument(Document $document): self + { + $this->document = $document; + + return $this; + } + + /** + * Returns set document for this database event. + * @return null|Document + */ + public function getDocument(): ?Document + { + return $this->document; + } + public function getQueue(): string { try { @@ -125,6 +177,8 @@ class Database extends Event 'type' => $this->type, 'table' => $this->table, 'row' => $this->row, + 'collection' => $this->collection, + 'document' => $this->document, 'database' => $this->database, 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) ]; diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index 5cb908464f..4980618ab1 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -230,7 +230,7 @@ class Realtime extends Adapter foreach ($channels as $key => $value) { switch (true) { - case strpos($key, 'account.') === 0: + case str_starts_with($key, 'account.'): unset($channels[$key]); break; @@ -298,12 +298,13 @@ class Realtime extends Adapter $roles = [Role::team(ID::custom($parts[1]))->toString()]; break; case 'databases': - if (in_array($parts[4] ?? [], ['columns', 'indexes'])) { + $resource = $parts[4] ?? ''; + if (in_array($resource, ['columns', 'attributes', 'indexes'])) { $channels[] = 'console'; $channels[] = 'projects.' . $project->getId(); $projectId = 'console'; $roles = [Role::team($project->getAttribute('teamId'))->toString()]; - } elseif (($parts[4] ?? '') === 'rows' || ($parts[4] ?? '') === 'documents') { + } elseif (in_array($resource, ['rows', 'documents'])) { if ($database->isEmpty()) { throw new \Exception('Database needs to be passed to Realtime for Document/Row events in the Database.'); } diff --git a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php index 37fa7cf0cc..2a6d1f1f28 100644 --- a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php +++ b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php @@ -60,8 +60,8 @@ class Databases extends Action } $type = $payload['type']; - $row = new Document($payload['row'] ?? []); - $table = new Document($payload['table'] ?? []); + $row = new Document($payload['row'] ?? $payload['document'] ?? []); + $table = new Document($payload['table'] ?? $payload['collection'] ?? []); $database = new Document($payload['database'] ?? []); $log->addTag('projectId', $project->getId()); @@ -115,10 +115,13 @@ class Databases extends Action } $projectId = $project->getId(); - $event = "databases.[databaseId].tables.[tableId].columns.[columnId].update"; + $events = [ + "databases.[databaseId].tables.[tableId].columns.[columnId].update", + "databases.[databaseId].collections.[collectionId].attributes.[attributeId].update", + ]; /** * TODO @christyjacob4 verify if this is still the case - * Fetch attribute from the database, since with Resque float values are loosing informations. + * Fetch attribute from the database, since with Resque float values are loosing information. */ $column = $dbForProject->getDocument('attributes', $column->getId()); @@ -204,7 +207,7 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $table, $project, $event, $queueForRealtime, $column); + $this->trigger($database, $table, $project, $events, $queueForRealtime, $column); if (! $relatedTable->isEmpty()) { $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedTable->getId()); @@ -238,7 +241,10 @@ class Databases extends Action } $projectId = $project->getId(); - $event = 'databases.[databaseId].tables.[tableId].columns.[columnId].delete'; + $events = [ + 'databases.[databaseId].tables.[tableId].columns.[columnId].delete', + 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].delete', + ]; $tableId = $table->getId(); $key = $column->getAttribute('key', ''); $type = $column->getAttribute('type', ''); @@ -311,7 +317,7 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $table, $project, $event, $queueForRealtime, $column); + $this->trigger($database, $table, $project, $events, $queueForRealtime, $column); } // The underlying database removes/rebuilds indexes when attribute is removed @@ -398,7 +404,10 @@ class Databases extends Action } $projectId = $project->getId(); - $event = 'databases.[databaseId].tables.[tableId].indexes.[indexId].update'; + $events = [ + 'databases.[databaseId].tables.[tableId].indexes.[indexId].update', + 'databases.[databaseId].collections.[collectionId].indexes.[indexId].update', + ]; $collectionId = $table->getId(); $key = $index->getAttribute('key', ''); $type = $index->getAttribute('type', ''); @@ -425,7 +434,7 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $table, $project, $event, $queueForRealtime, null, $index); + $this->trigger($database, $table, $project, $events, $queueForRealtime, null, $index); $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } } @@ -455,7 +464,10 @@ class Databases extends Action } $projectId = $project->getId(); - $event = 'databases.[databaseId].tables.[tableId].indexes.[indexId].delete'; + $events = [ + 'databases.[databaseId].tables.[tableId].indexes.[indexId].delete', + 'databases.[databaseId].collections.[collectionId].indexes.[indexId].delete', + ]; $key = $index->getAttribute('key'); $status = $index->getAttribute('status', ''); $project = $dbForPlatform->getDocument('projects', $projectId); @@ -481,7 +493,7 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $table, $project, $event, $queueForRealtime, null, $index); + $this->trigger($database, $table, $project, $events, $queueForRealtime, null, $index); $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $table->getId()); } } @@ -590,38 +602,46 @@ class Databases extends Action * @param Document $database * @param Document $table * @param Document $project + * @param string[] $events * @param Realtime $queueForRealtime * @param Document|null $column * @param Document|null $index * @return void + * @throws DatabaseException */ protected function trigger( Document $database, Document $table, Document $project, - string $event, + array $events, Realtime $queueForRealtime, Document|null $column = null, Document|null $index = null, ): void { - $queueForRealtime - ->setProject($project) - ->setSubscribers(['console']) - ->setEvent($event) - ->setParam('databaseId', $database->getId()) - ->setParam('tableId', $table->getId()); - - if (! empty($column)) { + // table and collection + foreach ($events as $event) { $queueForRealtime - ->setParam('columnId', $column->getId()) - ->setPayload($column->getArrayCopy()); - } - if (! empty($index)) { - $queueForRealtime - ->setParam('indexId', $index->getId()) - ->setPayload($index->getArrayCopy()); - } + ->setProject($project) + ->setSubscribers(['console']) + ->setEvent($event) + ->setParam('tableId', $table->getId()) + ->setParam('collectionId', $table->getId()) + ->setParam('databaseId', $database->getId()); - $queueForRealtime->trigger(); + if (! empty($column)) { + $queueForRealtime + ->setParam('columnId', $column->getId()) + ->setParam('attributeId', $column->getId()) + ->setPayload($column->getArrayCopy()); + } + + if (! empty($index)) { + $queueForRealtime + ->setParam('indexId', $index->getId()) + ->setPayload($index->getArrayCopy()); + } + + $queueForRealtime->trigger(); + } } } From 6d1afea436d9e2cecbee3aca27dd409615ce9889 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 7 May 2025 14:14:12 +0530 Subject: [PATCH 075/343] misc. --- src/Appwrite/Utopia/Response/Model/Webhook.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Utopia/Response/Model/Webhook.php b/src/Appwrite/Utopia/Response/Model/Webhook.php index 8e53b41e6e..af1e23447e 100644 --- a/src/Appwrite/Utopia/Response/Model/Webhook.php +++ b/src/Appwrite/Utopia/Response/Model/Webhook.php @@ -49,7 +49,10 @@ class Webhook extends Model 'type' => self::TYPE_STRING, 'description' => 'Webhook trigger events.', 'default' => [], - 'example' => 'database.tables.update', + 'example' => [ + 'databases.tables.update', + 'databases.collections.update' + ], 'array' => true, ]) ->addRule('security', [ From 0f94b800a52201e18426bc97f683db3a8259dd2b Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 7 May 2025 17:02:24 +0530 Subject: [PATCH 076/343] update: abstraction over table and collection apis. --- .../Databases/Http/Collections/Action.php | 124 ++++++++++++++ .../Databases/Http/Collections/Create.php | 123 +++++++++++++ .../Databases/Http/Collections/Delete.php | 109 ++++++++++++ .../Databases/Http/Collections/Get.php | 81 +++++++++ .../Databases/Http/Collections/Logs/XList.php | 161 ++++++++++++++++++ .../Databases/Http/Collections/Update.php | 117 +++++++++++++ .../Databases/Http/Collections/Usage/Get.php | 143 ++++++++++++++++ .../Databases/Http/Collections/XList.php | 128 ++++++++++++++ .../Modules/Databases/Http/Tables/Create.php | 75 ++------ .../Modules/Databases/Http/Tables/Delete.php | 55 ++---- .../Modules/Databases/Http/Tables/Get.php | 42 ++--- .../Databases/Http/Tables/Logs/XList.php | 113 ++---------- .../Modules/Databases/Http/Tables/Update.php | 64 ++----- .../Databases/Http/Tables/Usage/Get.php | 95 ++--------- .../Modules/Databases/Http/Tables/XList.php | 82 ++------- .../Modules/Databases/Services/Http.php | 21 ++- 16 files changed, 1116 insertions(+), 417 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Collections/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Collections/Delete.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Collections/Get.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Collections/Logs/XList.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Collections/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Collections/Usage/Get.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Collections/XList.php diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php new file mode 100644 index 0000000000..d2129f31ea --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php @@ -0,0 +1,124 @@ +context = $context; + } + + /** + * Get the current API context. + * + * @throws \Exception if context has not been set. + */ + final protected function getContext(): string + { + if ($this->context === null) { + throw new \Exception('Missing context: you must call setContext() with either `Action::TABLE` or `Action::COLLECTION` before using this method.'); + } + + return $this->context; + } + + /** + * Get the key used in event parameters (e.g., 'collectionId' or 'tableId'). + */ + final protected function getEventsParamKey(): string + { + return $this->getContext() . 'Id'; + } + + /** + * Get the response model used in the SDK and HTTP responses. + */ + abstract protected function getResponseModel(): string; + + /** + * Determine if the current action is for the Collections API. + */ + final protected function isCollectionsAPI(): bool + { + return $this->getContext() === self::COLLECTION; + } + + /** + * Get the SDK group name for the current action. + */ + final protected function getSdkGroup(): string + { + return $this->isCollectionsAPI() ? 'collections' : 'tables'; + } + + /** + * Get the exception to throw when the resource already exists. + */ + final protected function getDuplicateException(): string + { + return $this->isCollectionsAPI() + ? Exception::COLLECTION_ALREADY_EXISTS + : Exception::TABLE_ALREADY_EXISTS; + } + + /** + * Get the exception to throw when the resource is not found. + */ + final protected function getNotFoundException(): string + { + return $this->isCollectionsAPI() + ? Exception::COLLECTION_NOT_FOUND + : Exception::TABLE_NOT_FOUND; + } + + /** + * Get the exception to throw when the resource limit is exceeded. + */ + final protected function getLimitException(): string + { + return $this->isCollectionsAPI() + ? Exception::COLLECTION_LIMIT_EXCEEDED + : Exception::TABLE_LIMIT_EXCEEDED; + } + + /** + * Ensures that a valid context has been set. + * + * @throws \Exception if context is missing + */ + final protected function validateContext(): void + { + $this->getContext(); // Triggers exception if not set + } + +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Create.php new file mode 100644 index 0000000000..d0320c6dd0 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Create.php @@ -0,0 +1,123 @@ +setContext(Action::COLLECTION); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/collections') + ->desc('Create collections') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].collections.[collectionId].create') + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'collection.create') + ->label('audits.resource', 'database/{request.databaseId}/collection/{response.$id}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/create-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_CREATED, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.') + ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { + $this->validateContext(); + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collectionId = $collectionId === 'unique()' ? ID::unique() : $collectionId; + + $permissions = Permission::aggregate($permissions) ?? []; + + try { + $collection = $dbForProject->createDocument('database_' . $database->getInternalId(), new Document([ + '$id' => $collectionId, + 'databaseInternalId' => $database->getInternalId(), + 'databaseId' => $databaseId, + '$permissions' => $permissions, + 'documentSecurity' => $documentSecurity, + 'enabled' => $enabled, + 'name' => $name, + 'search' => \implode(' ', [$collectionId, $name]), + ])); + + $dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), permissions: $permissions, documentSecurity: $documentSecurity); + } catch (DuplicateException) { + throw new Exception($this->getDuplicateException()); + } catch (LimitException) { + throw new Exception($this->getLimitException()); + } + + $queueForEvents + ->setContext('database', $database) + ->setParam('databaseId', $databaseId) + ->setParam($this->getEventsParamKey(), $collection->getId()); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) + ->dynamic($collection, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Delete.php new file mode 100644 index 0000000000..d30c37efed --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Delete.php @@ -0,0 +1,109 @@ +setContext(Action::COLLECTION); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId') + ->desc('Delete collection') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].delete') + ->label('audits.event', 'collection.delete') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/delete-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_NOCONTENT, + model: UtopiaResponse::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { + $this->validateContext(); + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + if ($collection->isEmpty()) { + throw new Exception($this->getNotFoundException()); + } + + if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $collectionId)) { + $type = $this->getContext(); + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Failed to remove $type from DB"); + } + + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + + $queueForDatabase + ->setType(DATABASE_TYPE_DELETE_COLLECTION) + ->setDatabase($database); + + if ($this->isCollectionsAPI()) { + $queueForDatabase->setCollection($collection); + } else { + $queueForDatabase->setTable($collection); + } + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setContext('database', $database) + ->setParam($this->getEventsParamKey(), $collection->getId()) + ->setPayload($response->output($collection, $this->getResponseModel())); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Get.php new file mode 100644 index 0000000000..962ad3d21d --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Get.php @@ -0,0 +1,81 @@ +setContext(Action::COLLECTION); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId') + ->desc('Get collection') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/get-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject): void + { + $this->validateContext(); + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + + if ($collection->isEmpty()) { + throw new Exception($this->getNotFoundException()); + } + + $response->dynamic($collection, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Logs/XList.php new file mode 100644 index 0000000000..429c39dc44 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Logs/XList.php @@ -0,0 +1,161 @@ +setContext(Action::COLLECTION); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/logs') + ->desc('List collection logs') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/get-collection-logs.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) + ->inject('response') + ->inject('dbForProject') + ->inject('locale') + ->inject('geodb') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void + { + $this->validateContext(); + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + + if ($collection->isEmpty()) { + throw new Exception($this->getNotFoundException()); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); + + $audit = new Audit($dbForProject); + $resource = 'database/' . $databaseId . '/' . $this->getContext() . '/' . $collectionId; + $logs = $audit->getLogsByResource($resource, $queries); + + $output = []; + + foreach ($logs as $i => &$log) { + $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + + $detector = new Detector($log['userAgent']); + $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) + + $os = $detector->getOS(); + $client = $detector->getClient(); + $device = $detector->getDevice(); + + $output[$i] = new Document([ + 'event' => $log['event'], + 'userId' => $log['data']['userId'], + 'userEmail' => $log['data']['userEmail'] ?? null, + 'userName' => $log['data']['userName'] ?? null, + 'mode' => $log['data']['mode'] ?? null, + 'ip' => $log['ip'], + 'time' => $log['time'], + 'osCode' => $os['osCode'], + 'osName' => $os['osName'], + 'osVersion' => $os['osVersion'], + 'clientType' => $client['clientType'], + 'clientCode' => $client['clientCode'], + 'clientName' => $client['clientName'], + 'clientVersion' => $client['clientVersion'], + 'clientEngine' => $client['clientEngine'], + 'clientEngineVersion' => $client['clientEngineVersion'], + 'deviceName' => $device['deviceName'], + 'deviceBrand' => $device['deviceBrand'], + 'deviceModel' => $device['deviceModel'] + ]); + + $record = $geodb->get($log['ip']); + + if ($record) { + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + } else { + $output[$i]['countryCode'] = '--'; + $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); + } + } + + $response->dynamic(new Document([ + 'logs' => $output, + 'total' => $audit->countLogsByResource($resource, $queries), + ]), $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Update.php new file mode 100644 index 0000000000..582f0e84a3 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Update.php @@ -0,0 +1,117 @@ +setContext(Action::COLLECTION); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId') + ->desc('Update collection') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].update') + ->label('audits.event', 'collection.update') + ->label('audits.resource', 'database/{request.databaseId}/collections/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.') + ->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('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { + $this->validateContext(); + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + if ($collection->isEmpty()) { + throw new Exception($this->getNotFoundException()); + } + + $permissions ??= $collection->getPermissions() ?? []; + + // Map aggregate permissions into the multiple permissions they represent. + $permissions = Permission::aggregate($permissions); + + $enabled ??= $collection->getAttribute('enabled', true); + + $collection = $dbForProject->updateDocument( + 'database_' . $database->getInternalId(), + $collectionId, + $collection + ->setAttribute('name', $name) + ->setAttribute('$permissions', $permissions) + ->setAttribute('documentSecurity', $documentSecurity) + ->setAttribute('enabled', $enabled) + ->setAttribute('search', \implode(' ', [$collectionId, $name])) + ); + + $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity); + + $queueForEvents + ->setContext('database', $database) + ->setParam('databaseId', $databaseId) + ->setParam($this->getEventsParamKey(), $collection->getId()); + + $response->dynamic($collection, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Usage/Get.php new file mode 100644 index 0000000000..a9a924114f --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Usage/Get.php @@ -0,0 +1,143 @@ +setContext(Action::COLLECTION); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/usage') + ->desc('Get collection usage stats') + ->groups(['api', 'database', 'usage']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: null, + name: self::getName(), + description: '/docs/references/databases/get-collection-usage.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel() + ) + ], + contentType: ContentType::JSON, + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) + ->param('collectionId', '', new UID(), 'Collection ID.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject): void + { + $this->validateContext(); + + $database = $dbForProject->getDocument('databases', $databaseId); + $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + + if ($collection->isEmpty()) { + throw new Exception($this->getNotFoundException()); + } + + $periods = Config::getParam('usage', []); + $stats = $usage = []; + $days = $periods[$range]; + $metrics = [ + str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collectionDocument->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), + ]; + + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + foreach ($metrics as $metric) { + $result = $dbForProject->findOne('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', ['inf']) + ]); + + $stats[$metric]['total'] = $result['value'] ?? 0; + $limit = $days['limit']; + $period = $days['period']; + $results = $dbForProject->find('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', [$period]), + Query::limit($limit), + Query::orderDesc('time'), + ]); + $stats[$metric]['data'] = []; + foreach ($results as $result) { + $stats[$metric]['data'][$result->getAttribute('time')] = [ + 'value' => $result->getAttribute('value'), + ]; + } + } + }); + + $format = match ($days['period']) { + '1h' => 'Y-m-d\TH:00:00.000P', + '1d' => 'Y-m-d\T00:00:00.000P', + }; + + foreach ($metrics as $metric) { + $usage[$metric]['total'] = $stats[$metric]['total']; + $usage[$metric]['data'] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric]['data'][] = [ + 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } + } + + $prefix = $this->isCollectionsAPI() ? 'documents' : 'rows'; + + // prefix, prefixTotal + $usageDocument = new Document([ + 'range' => $range, + $prefix => $usage[$metrics[0]]['data'], + $prefix . 'Total' => $usage[$metrics[0]]['total'], + ]); + + $response->dynamic($usageDocument, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/XList.php new file mode 100644 index 0000000000..e540e86c06 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/XList.php @@ -0,0 +1,128 @@ +setContext(Action::COLLECTION); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/collections') + ->desc('List collections') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/list-collections.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('queries', [], new Collections(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Collections::ALLOWED_ATTRIBUTES), true) + ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject): void + { + $this->validateContext(); + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $queries = Query::parseQueries($queries); + + if (!empty($search)) { + $queries[] = Query::search('search', $search); + } + + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + $cursor = reset($cursor); + + if ($cursor) { + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $collectionIdId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionIdId); + + if ($cursorDocument->isEmpty()) { + $message = + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, ucfirst($this->getContext()) . " '$collectionIdId' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + + $filterQueries = Query::groupByType($queries)['filters']; + + try { + $collections = $dbForProject->find('database_' . $database->getInternalId(), $queries); + $total = $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT); + } catch (OrderException $e) { + $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; + $attribute = $this->isCollectionsAPI() ? 'attribute' : 'column'; + $message = "The order $attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all $documents order $attribute values are non-null."; + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, $message); + } + + $response->dynamic(new Document([ + 'total' => $total, + $this->getSdkGroup() => $collections, + ]), $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php index dc3f7b8574..6f30c897b4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php @@ -3,7 +3,8 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables; use Appwrite\Event\Event; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Collections\Action; +use Appwrite\Platform\Modules\Databases\Http\Collections\Create as CollectionCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -11,21 +12,14 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; -use Utopia\Database\Exception\Duplicate as DuplicateException; -use Utopia\Database\Exception\Limit as LimitException; -use Utopia\Database\Helpers\ID; -use Utopia\Database\Helpers\Permission; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Text; -class Create extends Action +class Create extends CollectionCreate { use HTTP; @@ -34,12 +28,18 @@ class Create extends Action return 'createTable'; } + protected function getResponseModel(): string + { + return UtopiaResponse::MODEL_TABLE; + } + public function __construct() { + $this->setContext(Action::TABLE); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables') - ->httpAlias('/v1/databases/:databaseId/collections') ->desc('Create table') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].tables.[tableId].create') @@ -49,14 +49,14 @@ class Create extends Action ->label('audits.resource', 'database/{request.databaseId}/table/{response.$id}') ->label('sdk', new Method( namespace: 'databases', - group: 'tables', - name: 'createTable', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/create-collection.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_CREATED, - model: UtopiaResponse::MODEL_TABLE, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -65,52 +65,13 @@ class Create extends Action ->param('tableId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Table name. Max length: 128 chars.') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) - ->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) - ->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true) + ->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or table level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->param('enabled', true, new Boolean(), 'Is table enabled? When set to \'disabled\', users cannot access the table but Server SDKs with and API key can still read and write to the table. No data is lost when this is toggled.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void - { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $tableId = $tableId === 'unique()' ? ID::unique() : $tableId; - - $permissions = Permission::aggregate($permissions) ?? []; - - try { - $table = $dbForProject->createDocument('database_' . $database->getInternalId(), new Document([ - '$id' => $tableId, - 'databaseInternalId' => $database->getInternalId(), - 'databaseId' => $databaseId, - '$permissions' => $permissions, - 'documentSecurity' => $documentSecurity, - 'enabled' => $enabled, - 'name' => $name, - 'search' => \implode(' ', [$tableId, $name]), - ])); - - $dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), permissions: $permissions, documentSecurity: $documentSecurity); - } catch (DuplicateException) { - throw new Exception(Exception::TABLE_ALREADY_EXISTS); - } catch (LimitException) { - throw new Exception(Exception::TABLE_LIMIT_EXCEEDED); - } - - $queueForEvents - ->setContext('database', $database) - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) - ->dynamic($table, UtopiaResponse::MODEL_TABLE); + ->callback(function (string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { + parent::action($databaseId, $tableId, $name, $permissions, $documentSecurity, $enabled, $response, $dbForProject, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php index b7e8f6ecf7..810edf7f21 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php @@ -4,20 +4,19 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Collections\Action; +use Appwrite\Platform\Modules\Databases\Http\Collections\Delete as CollectionDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; -class Delete extends Action +class Delete extends CollectionDelete { use HTTP; @@ -26,12 +25,18 @@ class Delete extends Action return 'deleteTable'; } + protected function getResponseModel(): string + { + return UtopiaResponse::MODEL_TABLE; + } + public function __construct() { + $this->setContext(Action::TABLE); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId') ->desc('Delete table') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -41,8 +46,8 @@ class Delete extends Action ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'tables', - name: 'deleteTable', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/delete-collection.md', auth: [AuthType::KEY], responses: [ @@ -59,38 +64,8 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void - { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $tableId)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); - } - - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId()); - - $queueForDatabase - ->setType(DATABASE_TYPE_DELETE_COLLECTION) - ->setDatabase($database) - ->setTable($table); - - $queueForEvents - ->setContext('database', $database) - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setPayload($response->output($table, UtopiaResponse::MODEL_TABLE)); - - $response->noContent(); + ->callback(function (string $databaseId, string $tableId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php index 4c76c1f89d..80798a4516 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php @@ -2,20 +2,19 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Collections\Action; +use Appwrite\Platform\Modules\Databases\Http\Collections\Get as CollectionGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; -class Get extends Action +class Get extends CollectionGet { use HTTP; @@ -24,26 +23,32 @@ class Get extends Action return 'getTable'; } + protected function getResponseModel(): string + { + return UtopiaResponse::MODEL_TABLE; + } + public function __construct() { + $this->setContext(Action::TABLE); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId') ->desc('Get table') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'tables', - name: 'getTable', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/get-collection.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_TABLE, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -52,23 +57,8 @@ class Get extends Action ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, UtopiaResponse $response, Database $dbForProject): void - { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - $response->dynamic($table, UtopiaResponse::MODEL_TABLE); + ->callback(function (string $databaseId, string $tableId, UtopiaResponse $response, Database $dbForProject) { + parent::action($databaseId, $tableId, $response, $dbForProject); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php index 1dba2493cf..b3ce8cd272 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php @@ -2,31 +2,24 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables\Logs; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Collections\Action; +use Appwrite\Platform\Modules\Databases\Http\Collections\Logs\XList as CollectionLogXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use DeviceDetector\DeviceDetector as Detector; use MaxMind\Db\Reader; -use Utopia\Audit\Audit; use Utopia\Database\Database; -use Utopia\Database\DateTime; -use Utopia\Database\Document; -use Utopia\Database\Exception\Query as QueryException; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; -class XList extends Action +class XList extends CollectionLogXList { use HTTP; @@ -35,26 +28,32 @@ class XList extends Action return 'listTableLogs'; } + protected function getResponseModel(): string + { + return UtopiaResponse::MODEL_LOG_LIST; + } + public function __construct() { + $this->setContext(Action::TABLE); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/logs') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/logs') ->desc('List table logs') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'tables', - name: 'listTableLogs', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/get-collection-logs.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_LOG_LIST, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -66,88 +65,8 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void - { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $tableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $tableDocument->getInternalId()); - - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } - - // Temp fix for logs - $queries[] = Query::or([ - Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), - Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), - ]); - - $audit = new Audit($dbForProject); - $resource = 'database/' . $databaseId . '/table/' . $tableId; - $logs = $audit->getLogsByResource($resource, $queries); - - $output = []; - - foreach ($logs as $i => &$log) { - $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; - - $detector = new Detector($log['userAgent']); - $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) - - $os = $detector->getOS(); - $client = $detector->getClient(); - $device = $detector->getDevice(); - - $output[$i] = new Document([ - 'event' => $log['event'], - 'userId' => $log['data']['userId'], - 'userEmail' => $log['data']['userEmail'] ?? null, - 'userName' => $log['data']['userName'] ?? null, - 'mode' => $log['data']['mode'] ?? null, - 'ip' => $log['ip'], - 'time' => $log['time'], - 'osCode' => $os['osCode'], - 'osName' => $os['osName'], - 'osVersion' => $os['osVersion'], - 'clientType' => $client['clientType'], - 'clientCode' => $client['clientCode'], - 'clientName' => $client['clientName'], - 'clientVersion' => $client['clientVersion'], - 'clientEngine' => $client['clientEngine'], - 'clientEngineVersion' => $client['clientEngineVersion'], - 'deviceName' => $device['deviceName'], - 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'] - ]); - - $record = $geodb->get($log['ip']); - - if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); - } else { - $output[$i]['countryCode'] = '--'; - $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); - } - } - - $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource, $queries), - 'logs' => $output, - ]), UtopiaResponse::MODEL_LOG_LIST); + ->callback(function (string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb) { + parent::action($databaseId, $tableId, $queries, $response, $dbForProject, $locale, $geodb); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php index f5621feab3..fde9114e59 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php @@ -3,24 +3,22 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables; use Appwrite\Event\Event; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Collections\Action; +use Appwrite\Platform\Modules\Databases\Http\Collections\Update as CollectionUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Helpers\Permission; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Text; -class Update extends Action +class Update extends CollectionUpdate { use HTTP; @@ -29,12 +27,18 @@ class Update extends Action return 'updateTable'; } + protected function getResponseModel(): string + { + return UtopiaResponse::MODEL_TABLE; + } + public function __construct() { + $this->setContext(Action::TABLE); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId') ->desc('Update table') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -44,8 +48,8 @@ class Update extends Action ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'tables', - name: 'updateTable', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/update-collection.md', auth: [AuthType::KEY], responses: [ @@ -65,46 +69,8 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void - { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - $permissions ??= $table->getPermissions() ?? []; - - // Map aggregate permissions into the multiple permissions they represent. - $permissions = Permission::aggregate($permissions); - - $enabled ??= $table->getAttribute('enabled', true); - - $table = $dbForProject->updateDocument( - 'database_' . $database->getInternalId(), - $tableId, - $table - ->setAttribute('name', $name) - ->setAttribute('$permissions', $permissions) - ->setAttribute('documentSecurity', $documentSecurity) - ->setAttribute('enabled', $enabled) - ->setAttribute('search', \implode(' ', [$tableId, $name])) - ); - - $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $permissions, $documentSecurity); - - $queueForEvents - ->setContext('database', $database) - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()); - - $response->dynamic($table, UtopiaResponse::MODEL_TABLE); + ->callback(function (string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { + parent::action($databaseId, $tableId, $name, $permissions, $documentSecurity, $enabled, $response, $dbForProject, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php index b528fee7cf..9ba99d32e1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php @@ -2,24 +2,20 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables\Usage; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Collections\Action; +use Appwrite\Platform\Modules\Databases\Http\Collections\Usage\Get as CollectionUsageGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Config\Config; use Utopia\Database\Database; -use Utopia\Database\Document; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\WhiteList; -class Get extends Action +class Get extends CollectionUsageGet { use HTTP; @@ -28,12 +24,18 @@ class Get extends Action return 'getTableUsage'; } + protected function getResponseModel(): string + { + return UtopiaResponse::MODEL_USAGE_TABLE; + } + public function __construct() { + $this->setContext(Action::TABLE); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/usage') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/usage') ->desc('Get table usage stats') ->groups(['api', 'database', 'usage']) ->label('scope', 'collections.read') @@ -41,13 +43,13 @@ class Get extends Action ->label('sdk', new Method( namespace: 'databases', group: null, - name: 'getTableUsage', + name: self::getName(), description: '/docs/references/databases/get-collection-usage.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_USAGE_TABLE, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON, @@ -57,75 +59,8 @@ class Get extends Action ->param('tableId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $range, string $tableId, UtopiaResponse $response, Database $dbForProject): void - { - - $database = $dbForProject->getDocument('databases', $databaseId); - $tableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $tableDocument->getInternalId()); - - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - $periods = Config::getParam('usage', []); - $stats = $usage = []; - $days = $periods[$range]; - $metrics = [ - str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $tableDocument->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), - ]; - - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { - foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ - Query::equal('metric', [$metric]), - Query::equal('period', ['inf']) - ]); - - $stats[$metric]['total'] = $result['value'] ?? 0; - $limit = $days['limit']; - $period = $days['period']; - $results = $dbForProject->find('stats', [ - Query::equal('metric', [$metric]), - Query::equal('period', [$period]), - Query::limit($limit), - Query::orderDesc('time'), - ]); - $stats[$metric]['data'] = []; - foreach ($results as $result) { - $stats[$metric]['data'][$result->getAttribute('time')] = [ - 'value' => $result->getAttribute('value'), - ]; - } - } - }); - - $format = match ($days['period']) { - '1h' => 'Y-m-d\TH:00:00.000P', - '1d' => 'Y-m-d\T00:00:00.000P', - }; - - foreach ($metrics as $metric) { - $usage[$metric]['total'] = $stats[$metric]['total']; - $usage[$metric]['data'] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric]['data'][] = [ - 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } - } - - $response->dynamic(new Document([ - 'range' => $range, - 'rows' => $usage[$metrics[0]]['data'], - 'rowsTotal' => $usage[$metrics[0]]['total'], - ]), UtopiaResponse::MODEL_USAGE_TABLE); + ->callback(function (string $databaseId, string $range, string $tableId, UtopiaResponse $response, Database $dbForProject) { + parent::action($databaseId, $range, $tableId, $response, $dbForProject); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php index e6d2a2d02a..f90a1f66f2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php @@ -2,7 +2,8 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Collections\Action; +use Appwrite\Platform\Modules\Databases\Http\Collections\XList as CollectionXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -10,18 +11,12 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Tables; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; -use Utopia\Database\Exception\Order as OrderException; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Text; -class XList extends Action +class XList extends CollectionXList { use HTTP; @@ -30,26 +25,32 @@ class XList extends Action return 'listTables'; } + protected function getResponseModel(): string + { + return UtopiaResponse::MODEL_TABLE_LIST; + } + public function __construct() { + $this->setContext(Action::TABLE); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables') - ->httpAlias('/v1/databases/:databaseId/collections') ->desc('List tables') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'tables', - name: 'listTables', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/list-collections.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_TABLE_LIST, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -59,59 +60,8 @@ class XList extends Action ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject): void - { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $queries = Query::parseQueries($queries); - - if (!empty($search)) { - $queries[] = Query::search('search', $search); - } - - /** - * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries - */ - $cursor = \array_filter($queries, function ($query) { - return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); - }); - $cursor = reset($cursor); - - if ($cursor) { - $validator = new Cursor(); - if (!$validator->isValid($cursor)) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); - } - - $tableId = $cursor->getValue(); - $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - - if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Table '{$tableId}' for the 'cursor' value not found."); - } - - $cursor->setValue($cursorDocument); - } - - $filterQueries = Query::groupByType($queries)['filters']; - - try { - $tables = $dbForProject->find('database_' . $database->getInternalId(), $queries); - $total = $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT); - } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); - } - - $response->dynamic(new Document([ - 'tables' => $tables, - 'total' => $total, - ]), UtopiaResponse::MODEL_TABLE_LIST); + ->callback(function (string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject) { + parent::action($databaseId, $queries, $search, $response, $dbForProject); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Http.php b/src/Appwrite/Platform/Modules/Databases/Services/Http.php index ffdd4f1903..26a4aa0942 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Http.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Http.php @@ -2,6 +2,13 @@ namespace Appwrite\Platform\Modules\Databases\Services; +use Appwrite\Platform\Modules\Databases\Http\Collections\Create as CreateCollection; +use Appwrite\Platform\Modules\Databases\Http\Collections\Delete as DeleteCollection; +use Appwrite\Platform\Modules\Databases\Http\Collections\Get as GetCollection; +use Appwrite\Platform\Modules\Databases\Http\Collections\Logs\XList as ListCollectionLogs; +use Appwrite\Platform\Modules\Databases\Http\Collections\Update as UpdateCollection; +use Appwrite\Platform\Modules\Databases\Http\Collections\Usage\Get as GetCollectionUsage; +use Appwrite\Platform\Modules\Databases\Http\Collections\XList as ListCollections; use Appwrite\Platform\Modules\Databases\Http\Columns\Boolean\Create as CreateBoolean; use Appwrite\Platform\Modules\Databases\Http\Columns\Boolean\Update as UpdateBoolean; use Appwrite\Platform\Modules\Databases\Http\Columns\Datetime\Create as CreateDatetime; @@ -59,7 +66,7 @@ class Http extends Service $this->type = Service::TYPE_HTTP; $this->registerDatabaseActions(); - $this->registerTableActions(); + $this->registerCollectionAndTableActions(); $this->registerColumnActions(); $this->registerIndexActions(); $this->registerRowActions(); @@ -77,8 +84,18 @@ class Http extends Service $this->addAction(ListDatabaseUsage::getName(), new ListDatabaseUsage()); } - private function registerTableActions(): void + private function registerCollectionAndTableActions(): void { + // Collections + $this->addAction(CreateCollection::getName(), new CreateCollection()); + $this->addAction(GetCollection::getName(), new GetCollection()); + $this->addAction(UpdateCollection::getName(), new UpdateCollection()); + $this->addAction(DeleteCollection::getName(), new DeleteCollection()); + $this->addAction(ListCollections::getName(), new ListCollections()); + $this->addAction(ListCollectionLogs::getName(), new ListCollectionLogs()); + $this->addAction(GetCollectionUsage::getName(), new GetCollectionUsage()); + + // Tables $this->addAction(CreateTable::getName(), new CreateTable()); $this->addAction(GetTable::getName(), new GetTable()); $this->addAction(UpdateTable::getName(), new UpdateTable()); From 69cc4f0bb6d6f5b6f6f99c559612e919fa23d514 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 7 May 2025 17:32:54 +0530 Subject: [PATCH 077/343] update: handle the context logic, use defaults. --- app/init/constants.php | 10 +++++++ .../Databases/Http/Collections/Action.php | 30 ++++--------------- .../Databases/Http/Collections/Create.php | 4 --- .../Databases/Http/Collections/Delete.php | 4 --- .../Databases/Http/Collections/Get.php | 4 --- .../Databases/Http/Collections/Logs/XList.php | 4 --- .../Databases/Http/Collections/Update.php | 4 --- .../Databases/Http/Collections/Usage/Get.php | 4 --- .../Databases/Http/Collections/XList.php | 4 --- .../Modules/Databases/Http/Tables/Create.php | 2 +- .../Modules/Databases/Http/Tables/Delete.php | 2 +- .../Modules/Databases/Http/Tables/Get.php | 2 +- .../Databases/Http/Tables/Logs/XList.php | 2 +- .../Modules/Databases/Http/Tables/Update.php | 2 +- .../Databases/Http/Tables/Usage/Get.php | 2 +- .../Modules/Databases/Http/Tables/XList.php | 2 +- 16 files changed, 22 insertions(+), 60 deletions(-) diff --git a/app/init/constants.php b/app/init/constants.php index 2b15f9fa0b..80d4796aad 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -257,3 +257,13 @@ const RESOURCE_TYPE_PROVIDERS = 'providers'; const RESOURCE_TYPE_TOPICS = 'topics'; const RESOURCE_TYPE_SUBSCRIBERS = 'subscribers'; const RESOURCE_TYPE_MESSAGES = 'messages'; + +// Context constants for database + +const DATABASE_ROWS_CONTEXT = 'row'; +const DATABASE_TABLES_CONTEXT = 'table'; +const DATABASE_COLUMNS_CONTEXT = 'column'; + +const DATABASE_DOCUMENTS_CONTEXT = 'document'; +const DATABASE_ATTRIBUTES_CONTEXT = 'attribute'; +const DATABASE_COLLECTIONS_CONTEXT = 'collection'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php index d2129f31ea..d00bc1f9f9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php @@ -13,26 +13,21 @@ use Utopia\Platform\Action as UtopiaAction; */ abstract class Action extends UtopiaAction { - /** - * Valid context identifiers. - */ - public const TABLE = 'table'; - public const COLLECTION = 'collection'; /** * The current API context (either 'table' or 'collection'). */ - private ?string $context = null; + private ?string $context = DATABASE_COLLECTIONS_CONTEXT; /** * Set the current API context. * - * @param string $context Must be either `self::TABLE` or `self::COLLECTION`. + * @param string $context Must be either `DATABASE_TABLES_CONTEXT` or `DATABASE_COLLECTIONS_CONTEXT`. */ final protected function setContext(string $context): void { - if (!\in_array($context, [self::TABLE, self::COLLECTION], true)) { - throw new \InvalidArgumentException("Invalid context '$context'. Must be either `Action::TABLE` or `Action::COLLECTION`."); + if (!\in_array($context, [DATABASE_TABLES_CONTEXT, DATABASE_COLLECTIONS_CONTEXT], true)) { + throw new \InvalidArgumentException("Invalid context '$context'. Must be either `DATABASE_TABLES_CONTEXT` or `DATABASE_COLLECTIONS_CONTEXT`."); } $this->context = $context; @@ -45,10 +40,6 @@ abstract class Action extends UtopiaAction */ final protected function getContext(): string { - if ($this->context === null) { - throw new \Exception('Missing context: you must call setContext() with either `Action::TABLE` or `Action::COLLECTION` before using this method.'); - } - return $this->context; } @@ -70,7 +61,7 @@ abstract class Action extends UtopiaAction */ final protected function isCollectionsAPI(): bool { - return $this->getContext() === self::COLLECTION; + return $this->getContext() === DATABASE_COLLECTIONS_CONTEXT; } /** @@ -110,15 +101,4 @@ abstract class Action extends UtopiaAction ? Exception::COLLECTION_LIMIT_EXCEEDED : Exception::TABLE_LIMIT_EXCEEDED; } - - /** - * Ensures that a valid context has been set. - * - * @throws \Exception if context is missing - */ - final protected function validateContext(): void - { - $this->getContext(); // Triggers exception if not set - } - } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Create.php index d0320c6dd0..063ce75720 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Create.php @@ -40,8 +40,6 @@ class Create extends Action public function __construct() { - $this->setContext(Action::COLLECTION); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/collections') @@ -80,8 +78,6 @@ class Create extends Action public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { - $this->validateContext(); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Delete.php index d30c37efed..7cec4addea 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Delete.php @@ -32,8 +32,6 @@ class Delete extends Action public function __construct() { - $this->setContext(Action::COLLECTION); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId') @@ -69,8 +67,6 @@ class Delete extends Action public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { - $this->validateContext(); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Get.php index 962ad3d21d..e7f02b8930 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Get.php @@ -30,8 +30,6 @@ class Get extends Action public function __construct() { - $this->setContext(Action::COLLECTION); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId') @@ -62,8 +60,6 @@ class Get extends Action public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject): void { - $this->validateContext(); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Logs/XList.php index 429c39dc44..bd31ad2fe1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Logs/XList.php @@ -42,8 +42,6 @@ class XList extends Action public function __construct() { - $this->setContext(Action::COLLECTION); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/logs') @@ -77,8 +75,6 @@ class XList extends Action public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void { - $this->validateContext(); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Update.php index 582f0e84a3..8c8dfb58b5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Update.php @@ -35,8 +35,6 @@ class Update extends Action public function __construct() { - $this->setContext(Action::COLLECTION); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId') @@ -75,8 +73,6 @@ class Update extends Action public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void { - $this->validateContext(); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Usage/Get.php index a9a924114f..60c7af4420 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Usage/Get.php @@ -35,8 +35,6 @@ class Get extends Action public function __construct() { - $this->setContext(Action::COLLECTION); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/usage') @@ -68,8 +66,6 @@ class Get extends Action public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject): void { - $this->validateContext(); - $database = $dbForProject->getDocument('databases', $databaseId); $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/XList.php index e540e86c06..98246defaa 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/XList.php @@ -36,8 +36,6 @@ class XList extends Action public function __construct() { - $this->setContext(Action::COLLECTION); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/collections') @@ -69,8 +67,6 @@ class XList extends Action public function action(string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject): void { - $this->validateContext(); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php index 6f30c897b4..8a6c009e87 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php @@ -35,7 +35,7 @@ class Create extends CollectionCreate public function __construct() { - $this->setContext(Action::TABLE); + $this->setContext(DATABASE_TABLES_CONTEXT); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php index 810edf7f21..e06c19b308 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php @@ -32,7 +32,7 @@ class Delete extends CollectionDelete public function __construct() { - $this->setContext(Action::TABLE); + $this->setContext(DATABASE_TABLES_CONTEXT); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php index 80798a4516..e5f2954de5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php @@ -30,7 +30,7 @@ class Get extends CollectionGet public function __construct() { - $this->setContext(Action::TABLE); + $this->setContext(DATABASE_TABLES_CONTEXT); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php index b3ce8cd272..67ff31efb7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php @@ -35,7 +35,7 @@ class XList extends CollectionLogXList public function __construct() { - $this->setContext(Action::TABLE); + $this->setContext(DATABASE_TABLES_CONTEXT); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php index fde9114e59..f27232353e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php @@ -34,7 +34,7 @@ class Update extends CollectionUpdate public function __construct() { - $this->setContext(Action::TABLE); + $this->setContext(DATABASE_TABLES_CONTEXT); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php index 9ba99d32e1..647a98d952 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php @@ -31,7 +31,7 @@ class Get extends CollectionUsageGet public function __construct() { - $this->setContext(Action::TABLE); + $this->setContext(DATABASE_TABLES_CONTEXT); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php index f90a1f66f2..77eb556301 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php @@ -32,7 +32,7 @@ class XList extends CollectionXList public function __construct() { - $this->setContext(Action::TABLE); + $this->setContext(DATABASE_TABLES_CONTEXT); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) From bc8a38ba55c05c17d4e308fa3ed8585d5fc4c19f Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 7 May 2025 20:01:46 +0530 Subject: [PATCH 078/343] update: abstraction over attribute and column apis [WIP]. --- .../Databases/Http/Attributes/Action.php | 627 ++++++++++++++++++ .../Http/Attributes/Boolean/Create.php | 94 +++ .../Http/Attributes/Boolean/Update.php | 95 +++ .../Http/Attributes/Datetime/Create.php | 104 +++ .../Http/Attributes/Datetime/Update.php | 97 +++ .../Databases/Http/Attributes/Delete.php | 161 +++++ .../Http/Attributes/Email/Create.php | 104 +++ .../Http/Attributes/Email/Update.php | 98 +++ .../Databases/Http/Attributes/Enum/Create.php | 113 ++++ .../Databases/Http/Attributes/Enum/Update.php | 102 +++ .../Http/Attributes/Float/Create.php | 121 ++++ .../Http/Attributes/Float/Update.php | 109 +++ .../Modules/Databases/Http/Attributes/Get.php | 101 +++ .../Databases/Http/Attributes/IP/Create.php | 104 +++ .../Databases/Http/Attributes/IP/Update.php | 98 +++ .../Http/Attributes/Integer/Create.php | 123 ++++ .../Http/Attributes/Integer/Update.php | 109 +++ .../Http/Attributes/Relationship/Create.php | 169 +++++ .../Http/Attributes/Relationship/Update.php | 103 +++ .../Http/Attributes/String/Create.php | 122 ++++ .../Http/Attributes/String/Update.php | 102 +++ .../Databases/Http/Attributes/URL/Create.php | 96 +++ .../Databases/Http/Attributes/URL/Update.php | 98 +++ .../Databases/Http/Attributes/XList.php | 130 ++++ .../Databases/Http/Collections/Action.php | 1 - .../Http/Columns/Datetime/Create.php | 2 +- .../Databases/Http/Columns/String/Update.php | 2 +- .../Modules/Databases/Http/Tables/Create.php | 1 - .../Modules/Databases/Http/Tables/Delete.php | 1 - .../Modules/Databases/Http/Tables/Get.php | 1 - .../Databases/Http/Tables/Logs/XList.php | 1 - .../Modules/Databases/Http/Tables/Update.php | 1 - .../Databases/Http/Tables/Usage/Get.php | 1 - .../Modules/Databases/Http/Tables/XList.php | 1 - 34 files changed, 3182 insertions(+), 10 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Delete.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Get.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Attributes/XList.php diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php new file mode 100644 index 0000000000..66e8313d33 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php @@ -0,0 +1,627 @@ +context = $context; + } + + /** + * Get the current context. + * + * @throws \LogicException If context has not been set. + */ + final protected function getContext(): string + { + return $this->context; + } + + /** + * Returns true if current context is Collections API. + */ + final protected function isCollectionsAPI(): bool + { + // columns in tables context + // attributes in collections context + return $this->getContext() === DATABASE_ATTRIBUTES_CONTEXT; + } + + /** + * Get the SDK group name for the current action. + * + * Can be used for XList operations as well! + */ + final protected function getSdkGroup(): string + { + return $this->isCollectionsAPI() ? 'attributes' : 'columns'; + } + + /** + * Get the correct parent param key (e.g. `tableId` or `collectionId`) + */ + final protected function getParentEventsParamKey(): string + { + return $this->isCollectionsAPI() ? 'collectionId' : 'tableId'; + } + + /** + * Get the correct param key (e.g. `attributeId` or `columnId`) + */ + final protected function getEventsParamKey(): string + { + return $this->getContext() . 'Id'; + } + + /** + * Set the correct response model. + */ + final protected function setResponseModel(string|array $model): void + { + $this->responseModel = $model; + } + + /** + * Get the correct response model. + */ + final protected function getResponseModel(): string|array + { + if ($this->responseModel === null) { + throw new \LogicException("Missing response model: you must call setResponseModel() before using it."); + } + + return $this->responseModel; + } + + /** + * Get the appropriate parent level not found exception. + */ + final protected function getParentNotFoundException(): string + { + return $this->isCollectionsAPI() + ? Exception::COLLECTION_NOT_FOUND + : Exception::TABLE_NOT_FOUND; + } + + /** + * Get the appropriate not found exception. + */ + final protected function getNotFoundException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_NOT_FOUND + : Exception::COLUMN_NOT_FOUND; + } + + /** + * Get the appropriate already exists exception. + */ + final protected function getDuplicateException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_ALREADY_EXISTS + : Exception::COLUMN_ALREADY_EXISTS; + } + + /** + * Get the appropriate limit exceeded exception. + */ + final protected function getLimitException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_LIMIT_EXCEEDED + : Exception::COLUMN_LIMIT_EXCEEDED; + } + + /** + * Get the correct default unsupported message. + */ + final protected function getDefaultUnsupportedException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED + : Exception::COLUMN_DEFAULT_UNSUPPORTED; + } + + /** + * Get the correct format unsupported message. + */ + final protected function getFormatUnsupportedException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_FORMAT_UNSUPPORTED + : Exception::COLUMN_FORMAT_UNSUPPORTED; + } + + /** + * Get the exception for invalid type or format mismatch. + */ + final protected function getTypeInvalidException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_TYPE_INVALID + : Exception::COLUMN_TYPE_INVALID; + } + + /** + * Get the exception for resizing invalid attributes/columns. + */ + final protected function getInvalidResizeException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_INVALID_RESIZE + : Exception::COLUMN_INVALID_RESIZE; + } + + /** + * Get the exception for invalid attributes/columns value. + */ + final protected function getInvalidValueException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_VALUE_INVALID + : Exception::COLUMN_VALUE_INVALID; + } + + /** + * Get the exception for non-available column/attribute. + */ + final protected function getNotAvailableException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_NOT_AVAILABLE + : Exception::COLUMN_NOT_AVAILABLE; + } + + /** + * Get the proper column/attribute type based on set context. + */ + final protected function getCorrectModel(string $type, string $format): string + { + $isCollections = $this->isCollectionsAPI(); + + return match ($type) { + Database::VAR_BOOLEAN => $isCollections + ? UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN + : UtopiaResponse::MODEL_COLUMN_BOOLEAN, + + Database::VAR_INTEGER => $isCollections + ? UtopiaResponse::MODEL_ATTRIBUTE_INTEGER + : UtopiaResponse::MODEL_COLUMN_INTEGER, + + Database::VAR_FLOAT => $isCollections + ? UtopiaResponse::MODEL_ATTRIBUTE_FLOAT + : UtopiaResponse::MODEL_COLUMN_FLOAT, + + Database::VAR_DATETIME => $isCollections + ? UtopiaResponse::MODEL_ATTRIBUTE_DATETIME + : UtopiaResponse::MODEL_COLUMN_DATETIME, + + Database::VAR_RELATIONSHIP => $isCollections + ? UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP + : UtopiaResponse::MODEL_COLUMN_RELATIONSHIP, + + Database::VAR_STRING => match ($format) { + APP_DATABASE_ATTRIBUTE_EMAIL => $isCollections + ? UtopiaResponse::MODEL_ATTRIBUTE_EMAIL + : UtopiaResponse::MODEL_COLUMN_EMAIL, + + APP_DATABASE_ATTRIBUTE_ENUM => $isCollections + ? UtopiaResponse::MODEL_ATTRIBUTE_ENUM + : UtopiaResponse::MODEL_COLUMN_ENUM, + + APP_DATABASE_ATTRIBUTE_IP => $isCollections + ? UtopiaResponse::MODEL_ATTRIBUTE_IP + : UtopiaResponse::MODEL_COLUMN_IP, + + APP_DATABASE_ATTRIBUTE_URL => $isCollections + ? UtopiaResponse::MODEL_ATTRIBUTE_URL + : UtopiaResponse::MODEL_COLUMN_URL, + + default => $isCollections + ? UtopiaResponse::MODEL_ATTRIBUTE_STRING + : UtopiaResponse::MODEL_COLUMN_STRING, + }, + default => $isCollections + ? UtopiaResponse::MODEL_ATTRIBUTE + : UtopiaResponse::MODEL_COLUMN, + }; + } + + final protected function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): Document + { + $key = $attribute->getAttribute('key'); + $type = $attribute->getAttribute('type', ''); + $size = $attribute->getAttribute('size', 0); + $required = $attribute->getAttribute('required', true); + $signed = $attribute->getAttribute('signed', true); // integers are signed by default + $array = $attribute->getAttribute('array', false); + $format = $attribute->getAttribute('format', ''); + $formatOptions = $attribute->getAttribute('formatOptions', []); + $filters = $attribute->getAttribute('filters', []); // filters are hidden from the endpoint + $default = $attribute->getAttribute('default'); + $options = $attribute->getAttribute('options', []); + + $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($db->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + + if ($collection->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + if (!empty($format)) { + if (!Structure::hasFormat($format, $type)) { + throw new Exception($this->getFormatUnsupportedException(), "Format {$format} not available for {$type} columns."); + } + } + + // Must throw here since dbForProject->createAttribute is performed by db worker + if ($required && isset($default)) { + throw new Exception($this->getDefaultUnsupportedException(), 'Cannot set default value for required ' . $this->getContext()); + } + + if ($array && isset($default)) { + throw new Exception($this->getDefaultUnsupportedException(), 'Cannot set default value for array ' . $this->getContext() . 's'); + } + + if ($type === Database::VAR_RELATIONSHIP) { + $options['side'] = Database::RELATION_SIDE_PARENT; + $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection'] ?? ''); + if ($relatedTable->isEmpty()) { + $parent = $this->isCollectionsAPI() ? 'collection' : 'table'; + throw new Exception($this->getParentNotFoundException(), "The related $parent was not found."); + } + } + + try { + $attribute = new Document([ + '$id' => ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), + 'key' => $key, + 'databaseInternalId' => $db->getInternalId(), + 'databaseId' => $db->getId(), + 'collectionInternalId' => $collection->getInternalId(), + 'collectionId' => $collectionId, + 'type' => $type, + 'status' => 'processing', // processing, available, failed, deleting, stuck + 'size' => $size, + 'required' => $required, + 'signed' => $signed, + 'default' => $default, + 'array' => $array, + 'format' => $format, + 'formatOptions' => $formatOptions, + 'filters' => $filters, + 'options' => $options, + ]); + + $dbForProject->checkAttribute($collection, $attribute); + $attribute = $dbForProject->createDocument('attributes', $attribute); + } catch (DuplicateException) { + throw new Exception($this->getDuplicateException()); + } catch (LimitException) { + throw new Exception($this->getLimitException()); + } catch (Throwable $e) { + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + throw $e; + } + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + + if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { + $twoWayKey = $options['twoWayKey']; + $options['relatedCollection'] = $collection->getId(); + $options['twoWayKey'] = $key; + $options['side'] = Database::RELATION_SIDE_CHILD; + + try { + $twoWayAttribute = new Document([ + '$id' => ID::custom($db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $twoWayKey), + 'key' => $twoWayKey, + 'databaseInternalId' => $db->getInternalId(), + 'databaseId' => $db->getId(), + 'collectionInternalId' => $relatedTable->getInternalId(), + 'collectionId' => $relatedTable->getId(), + 'type' => $type, + 'status' => 'processing', // processing, available, failed, deleting, stuck + 'size' => $size, + 'required' => $required, + 'signed' => $signed, + 'default' => $default, + 'array' => $array, + 'format' => $format, + 'formatOptions' => $formatOptions, + 'filters' => $filters, + 'options' => $options, + ]); + + $dbForProject->checkAttribute($relatedTable, $twoWayAttribute); + $dbForProject->createDocument('attributes', $twoWayAttribute); + } catch (DuplicateException) { + $dbForProject->deleteDocument('attributes', $attribute->getId()); + throw new Exception($this->getDuplicateException()); + } catch (LimitException) { + $dbForProject->deleteDocument('attributes', $attribute->getId()); + throw new Exception($this->getLimitException()); + } catch (Throwable $e) { + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); + throw $e; + } + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); + } + + $queueForDatabase + ->setType(DATABASE_TYPE_CREATE_ATTRIBUTE) + ->setDatabase($db); + + if ($this->isCollectionsAPI()) { + $queueForDatabase + ->setDocument($attribute) + ->setCollection($collection); + } else { + $queueForDatabase + ->setRow($attribute) + ->setTable($collection); + } + + $queueForEvents + ->setContext('database', $db) + ->setParam('databaseId', $databaseId) + ->setParam($this->getEventsParamKey(), $attribute->getId()) + // tableId or columnId + ->setParam($this->getParentEventsParamKey(), $collection->getId()) + ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); + + $response->setStatusCode(SwooleResponse::STATUS_CODE_CREATED); + + return $attribute; + } + + final protected function updateAttribute(string $databaseId, string $collectionId, string $key, Database $dbForProject, Event $queueForEvents, string $type, int $size = null, string $filter = null, string|bool|int|float $default = null, bool $required = null, int|float|null $min = null, int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null): Document + { + $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($db->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + + if ($collection->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + $attribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + + if ($attribute->isEmpty()) { + throw new Exception($this->getNotFoundException()); + } + + if ($attribute->getAttribute('status') !== 'available') { + throw new Exception($this->getNotAvailableException()); + } + + if ($attribute->getAttribute(('type') !== $type)) { + throw new Exception($this->getTypeInvalidException()); + } + + if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute(('filter') !== $filter)) { + throw new Exception($this->getTypeInvalidException()); + } + + if ($required && isset($default)) { + throw new Exception($this->getDefaultUnsupportedException(), 'Cannot set default value for required ' . $this->getContext()); + } + + if ($attribute->getAttribute('array', false) && isset($default)) { + throw new Exception($this->getDefaultUnsupportedException(), 'Cannot set default value for array ' . $this->getContext() . 's'); + } + + $collectionId = 'database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId(); + + $attribute + ->setAttribute('default', $default) + ->setAttribute('required', $required); + + if (!empty($size)) { + $attribute->setAttribute('size', $size); + } + + switch ($attribute->getAttribute('format')) { + case APP_DATABASE_ATTRIBUTE_INT_RANGE: + case APP_DATABASE_ATTRIBUTE_FLOAT_RANGE: + $min ??= $attribute->getAttribute('formatOptions')['min']; + $max ??= $attribute->getAttribute('formatOptions')['max']; + + if ($min > $max) { + throw new Exception($this->getTypeInvalidException(), 'Minimum value must be lesser than maximum value'); + } + + if ($attribute->getAttribute('format') === APP_DATABASE_ATTRIBUTE_INT_RANGE) { + $validator = new Range($min, $max, Database::VAR_INTEGER); + } else { + $validator = new Range($min, $max, Database::VAR_FLOAT); + + if (!is_null($default)) { + $default = \floatval($default); + } + } + + if (!is_null($default) && !$validator->isValid($default)) { + throw new Exception($this->getTypeInvalidException(), $validator->getDescription()); + } + + $options = [ + 'min' => $min, + 'max' => $max + ]; + $attribute->setAttribute('formatOptions', $options); + + break; + case APP_DATABASE_ATTRIBUTE_ENUM: + if (empty($elements)) { + throw new Exception($this->getTypeInvalidException(), 'Enum elements must not be empty'); + } + + foreach ($elements as $element) { + if (\strlen($element) === 0) { + throw new Exception($this->getTypeInvalidException(), 'Each enum element must not be empty'); + } + } + + if (!is_null($default) && !in_array($default, $elements)) { + throw new Exception($this->getTypeInvalidException(), 'Default value not found in elements'); + } + + $options = [ + 'elements' => $elements + ]; + + $attribute->setAttribute('formatOptions', $options); + + break; + } + + if ($type === Database::VAR_RELATIONSHIP) { + $primaryDocumentOptions = \array_merge($attribute->getAttribute('options', []), $options); + $attribute->setAttribute('options', $primaryDocumentOptions); + try { + $dbForProject->updateRelationship( + collection: $collectionId, + id: $key, + newKey: $newKey, + onDelete: $primaryDocumentOptions['onDelete'], + ); + } catch (NotFoundException) { + throw new Exception($this->getNotFoundException()); + } + + if ($primaryDocumentOptions['twoWay']) { + $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $primaryDocumentOptions['relatedCollection']); + + $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey']); + + if (!empty($newKey) && $newKey !== $key) { + $options['twoWayKey'] = $newKey; + } + + $relatedOptions = \array_merge($relatedAttribute->getAttribute('options'), $options); + $relatedAttribute->setAttribute('options', $relatedOptions); + $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); + } + } else { + try { + $dbForProject->updateAttribute( + collection: $collectionId, + id: $key, + size: $size, + required: $required, + default: $default, + formatOptions: $options, + newKey: $newKey ?? null + ); + } catch (TruncateException) { + throw new Exception($this->getInvalidResizeException()); + } catch (NotFoundException) { + throw new Exception($this->getNotFoundException()); + } catch (LimitException) { + throw new Exception($this->getLimitException()); + } catch (IndexException $e) { + throw new Exception(Exception::INDEX_INVALID, $e->getMessage()); + } + } + + if (!empty($newKey) && $key !== $newKey) { + $originalUid = $attribute->getId(); + + $attribute + ->setAttribute('$id', ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $newKey)) + ->setAttribute('key', $newKey); + + $dbForProject->updateDocument('attributes', $originalUid, $attribute); + + /** + * @var Document $index + */ + foreach ($collection->getAttribute('indexes') as $index) { + /** + * @var string[] $attribute + */ + $attribute = $index->getAttribute('attributes', []); + $found = \array_search($key, $attribute); + + if ($found !== false) { + $attribute[$found] = $newKey; + $index->setAttribute('attributes', $attribute); + $dbForProject->updateDocument('indexes', $index->getId(), $index); + } + } + } else { + $attribute = $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute); + } + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collection->getId()); + + $queueForEvents + ->setContext('database', $db) + ->setParam('databaseId', $databaseId) + ->setParam($this->getEventsParamKey(), $attribute->getId()) + // tableId or columnId + ->setParam($this->getParentEventsParamKey(), $collection->getId()) + ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); + + return $attribute; + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php new file mode 100644 index 0000000000..583e42b4ed --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php @@ -0,0 +1,94 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN); + + $this->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/boolean') + ->desc('Create boolean attribute') + ->groups(['api', 'database', 'schema']) + ->label('event', 'databases.[databaseId].collections.[collectionId].collections.[attributeId].create') + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'attribute.create') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/create-boolean-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: $this->getResponseModel(), + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, new Boolean(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) + ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?bool $default, + bool $array, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + + $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ + 'key' => $key, + 'type' => Database::VAR_BOOLEAN, + 'size' => 0, + 'required' => $required, + 'default' => $default, + 'array' => $array, + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Update.php new file mode 100644 index 0000000000..41a0c5a621 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Update.php @@ -0,0 +1,95 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN); + + $this->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/boolean/:key') + ->desc('Update boolean attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') + ->label('audits.event', 'attribute.update') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-boolean-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#createCollection).') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, new Nullable(new Boolean()), 'Default value for attribute when not provided. Cannot be set when attribute is required.') + ->param('newKey', null, new Key(), 'New attribute key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?bool $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $attribute = $this->updateAttribute( + databaseId: $databaseId, + collectionId: $collectionId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_BOOLEAN, + default: $default, + required: $required, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Create.php new file mode 100644 index 0000000000..40d7aed1e9 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Create.php @@ -0,0 +1,104 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_DATETIME); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/datetime') + ->desc('Create datetime attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('audits.event', 'attribute.create') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/create-datetime-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: $this->getResponseModel() + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#createCollection).') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, fn (Database $dbForProject) => new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime()), 'Default value for the attribute in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.', true, ['dbForProject']) + ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?string $default, + bool $array, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $attribute = $this->createAttribute( + $databaseId, + $collectionId, + new Document([ + 'key' => $key, + 'type' => Database::VAR_DATETIME, + 'size' => 0, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'filters' => ['datetime'], + ]), + $response, + $dbForProject, + $queueForDatabase, + $queueForEvents + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Update.php new file mode 100644 index 0000000000..386d6682ad --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Update.php @@ -0,0 +1,97 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_DATETIME); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/datetime/:key') + ->desc('Update datetime attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') + ->label('audits.event', 'attribute.update') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-datetime-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel() + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, fn (Database $dbForProject) => new Nullable(new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime())), 'Default value for attribute when not provided. Cannot be set when attribute is required.', injections: ['dbForProject']) + ->param('newKey', null, new Key(), 'New attribute key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?string $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $attribute = $this->updateAttribute( + databaseId: $databaseId, + collectionId: $collectionId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_DATETIME, + default: $default, + required: $required, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Delete.php new file mode 100644 index 0000000000..da29fd09ee --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Delete.php @@ -0,0 +1,161 @@ +setResponseModel(UtopiaResponse::MODEL_NONE); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') + ->desc('Delete attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') + ->label('audits.event', 'attribute.delete') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: 'attributes', + name: 'deleteAttribute', + description: '/docs/references/databases/delete-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_NOCONTENT, + model: UtopiaResponse::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($db->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + if ($collection->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + $attribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + if ($attribute->isEmpty()) { + throw new Exception($this->getNotFoundException()); + } + + $validator = new IndexDependencyValidator( + $collection->getAttribute('indexes'), + $dbForProject->getAdapter()->getSupportForCastIndexArray(), + ); + if (!$validator->isValid($attribute)) { + throw new Exception(Exception::INDEX_DEPENDENCY); + } + + if ($attribute->getAttribute('status') === 'available') { + $attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting')); + } + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + + if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { + $options = $attribute->getAttribute('options'); + if ($options['twoWay']) { + $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection']); + if ($relatedCollection->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + if ($relatedAttribute->isEmpty()) { + throw new Exception($this->getNotFoundException()); + } + + if ($relatedAttribute->getAttribute('status') === 'available') { + $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'deleting')); + } + + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + } + } + + $queueForDatabase + ->setDatabase($db) + ->setType(DATABASE_TYPE_DELETE_ATTRIBUTE); + + if ($this->isCollectionsAPI()) { + $queueForDatabase + ->setRow($attribute) + ->setTable($collection); + } else { + $queueForDatabase + ->setDocument($attribute) + ->setCollection($collection); + } + + $type = $attribute->getAttribute('type'); + $format = $attribute->getAttribute('format'); + + $model = $this->getCorrectModel($type, $format); + + $queueForEvents + ->setContext('database', $db) + ->setParam('databaseId', $databaseId) + ->setPayload($response->output($attribute, $model)) + ->setParam($this->getEventsParamKey(), $attribute->getId()) + // tableId or columnId + ->setParam($this->getParentEventsParamKey(), $collection->getId()) + // set proper context + ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Create.php new file mode 100644 index 0000000000..9b63f2198a --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Create.php @@ -0,0 +1,104 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_EMAIL); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/email') + ->desc('Create email attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('audits.event', 'attribute.create') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/create-email-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: $this->getResponseModel(), + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, new Email(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) + ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + ?bool $required, + ?string $default, + bool $array, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $attribute = $this->createAttribute( + $databaseId, + $tableId, + new Document([ + 'key' => $key, + 'type' => Database::VAR_STRING, + 'size' => 254, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'format' => APP_DATABASE_ATTRIBUTE_EMAIL, + ]), + $response, + $dbForProject, + $queueForDatabase, + $queueForEvents + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Update.php new file mode 100644 index 0000000000..0c41961099 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Update.php @@ -0,0 +1,98 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_EMAIL); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/email/:key') + ->desc('Update email attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') + ->label('audits.event', 'attribute.update') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-email-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, new Nullable(new Email()), 'Default value for attribute when not provided. Cannot be set when attribute is required.') + ->param('newKey', null, new Key(), 'New Attribute Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?string $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $attribute = $this->updateAttribute( + databaseId: $databaseId, + collectionId: $collectionId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_STRING, + filter: APP_DATABASE_ATTRIBUTE_EMAIL, + default: $default, + required: $required, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Create.php new file mode 100644 index 0000000000..61298cbe94 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Create.php @@ -0,0 +1,113 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_ENUM); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') + ->desc('Create enum attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('audits.event', 'attribute.create') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/create-attribute-enum.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: $this->getResponseModel(), + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('elements', [], new ArrayList(new Text(Database::LENGTH_KEY), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of enum values.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, new Text(0), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) + ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + array $elements, + ?bool $required, + ?string $default, + bool $array, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + if (!is_null($default) && !\in_array($default, $elements, true)) { + throw new Exception($this->getInvalidValueException(), 'Default value not found in elements'); + } + + $attribute = $this->createAttribute( + $databaseId, + $collectionId, + new Document([ + 'key' => $key, + 'type' => Database::VAR_STRING, + 'size' => Database::LENGTH_KEY, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'format' => APP_DATABASE_ATTRIBUTE_ENUM, + 'formatOptions' => ['elements' => $elements], + ]), + $response, + $dbForProject, + $queueForDatabase, + $queueForEvents + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Update.php new file mode 100644 index 0000000000..37d8065608 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Update.php @@ -0,0 +1,102 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_ENUM); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/enum/:key') + ->desc('Update enum attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') + ->label('audits.event', 'attribute.update') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-enum-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('elements', null, new ArrayList(new Text(Database::LENGTH_KEY), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Updated list of enum values.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, new Nullable(new Text(0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.') + ->param('newKey', null, new Key(), 'New Attribute Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?array $elements, + ?bool $required, + ?string $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $attribute = $this->updateAttribute( + databaseId: $databaseId, + collectionId: $collectionId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_STRING, + filter: APP_DATABASE_ATTRIBUTE_ENUM, + default: $default, + required: $required, + elements: $elements, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Create.php new file mode 100644 index 0000000000..9603cf4c9a --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Create.php @@ -0,0 +1,121 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_FLOAT); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/float') + ->desc('Create float attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('audits.event', 'attribute.create') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/create-float-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: $this->getResponseModel(), + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('min', null, new FloatValidator(), 'Minimum value.', true) + ->param('max', null, new FloatValidator(), 'Maximum value.', true) + ->param('default', null, new FloatValidator(), 'Default value. Cannot be set when required.', true) + ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?float $min, + ?float $max, + ?float $default, + bool $array, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $min ??= -PHP_FLOAT_MAX; + $max ??= PHP_FLOAT_MAX; + + if ($min > $max) { + throw new Exception($this->getInvalidValueException(), 'Minimum value must be lesser than maximum value'); + } + + $validator = new Range($min, $max, Database::VAR_FLOAT); + if (!\is_null($default) && !$validator->isValid($default)) { + throw new Exception($this->getInvalidValueException(), $validator->getDescription()); + } + + $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ + 'key' => $key, + 'type' => Database::VAR_FLOAT, + 'size' => 0, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'format' => APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, + 'formatOptions' => ['min' => $min, 'max' => $max], + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + + $formatOptions = $attribute->getAttribute('formatOptions', []); + if (!empty($formatOptions)) { + $attribute->setAttribute('min', \floatval($formatOptions['min'])); + $attribute->setAttribute('max', \floatval($formatOptions['max'])); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Update.php new file mode 100644 index 0000000000..012e8239c9 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Update.php @@ -0,0 +1,109 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_FLOAT); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/float/:key') + ->desc('Update float attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') + ->label('audits.event', 'attribute.update') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-float-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('min', null, new FloatValidator(), 'Minimum value.', true) + ->param('max', null, new FloatValidator(), 'Maximum value.', true) + ->param('default', null, new Nullable(new FloatValidator()), 'Default value. Cannot be set when required.') + ->param('newKey', null, new Key(), 'New Attribute Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?float $min, + ?float $max, + ?float $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $attribute = $this->updateAttribute( + databaseId: $databaseId, + collectionId: $collectionId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_FLOAT, + default: $default, + required: $required, + min: $min, + max: $max, + newKey: $newKey + ); + + $formatOptions = $attribute->getAttribute('formatOptions', []); + if (!empty($formatOptions)) { + $attribute->setAttribute('min', \floatval($formatOptions['min'])); + $attribute->setAttribute('max', \floatval($formatOptions['max'])); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Get.php new file mode 100644 index 0000000000..e782897be2 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Get.php @@ -0,0 +1,101 @@ +setResponseModel([ + UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN, + UtopiaResponse::MODEL_ATTRIBUTE_INTEGER, + UtopiaResponse::MODEL_ATTRIBUTE_FLOAT, + UtopiaResponse::MODEL_ATTRIBUTE_EMAIL, + UtopiaResponse::MODEL_ATTRIBUTE_ENUM, + UtopiaResponse::MODEL_ATTRIBUTE_URL, + UtopiaResponse::MODEL_ATTRIBUTE_IP, + UtopiaResponse::MODEL_ATTRIBUTE_DATETIME, + UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP, + UtopiaResponse::MODEL_ATTRIBUTE_STRING, + ]); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') + ->desc('Get column') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'columns', + name: 'getColumn', + description: '/docs/references/databases/get-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel() + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('key', '', new Key(), 'Column Key.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $tableId, + string $key, + UtopiaResponse $response, + Database $dbForProject + ): void { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + if ($collection->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + if ($attribute->isEmpty()) { + throw new Exception($this->getNotFoundException()); + } + + foreach ($attribute->getAttribute('options', []) as $optKey => $optVal) { + $attribute->setAttribute($optKey, $optVal); + } + + $type = $attribute->getAttribute('type'); + $format = $attribute->getAttribute('format'); + $model = $this->getCorrectModel($type, $format); + + $response->dynamic($attribute, $model); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Create.php new file mode 100644 index 0000000000..8176b03bba --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Create.php @@ -0,0 +1,104 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_IP); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') + ->desc('Create IP address attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('audits.event', 'attribute.create') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/create-ip-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: $this->getResponseModel(), + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, new IP(), 'Default value. Cannot be set when attribute is required.', true) + ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?string $default, + bool $array, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $attribute = $this->createAttribute( + $databaseId, + $collectionId, + new Document([ + 'key' => $key, + 'type' => Database::VAR_STRING, + 'size' => 39, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'format' => APP_DATABASE_ATTRIBUTE_IP, + ]), + $response, + $dbForProject, + $queueForDatabase, + $queueForEvents + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Update.php new file mode 100644 index 0000000000..868b735bbb --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Update.php @@ -0,0 +1,98 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_IP); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/ip/:key') + ->desc('Update IP address attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') + ->label('audits.event', 'attribute.update') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-ip-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, new Nullable(new IP()), 'Default value. Cannot be set when attribute is required.') + ->param('newKey', null, new Key(), 'New Attribute Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?string $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $attribute = $this->updateAttribute( + databaseId: $databaseId, + collectionId: $collectionId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_STRING, + filter: APP_DATABASE_ATTRIBUTE_IP, + default: $default, + required: $required, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Create.php new file mode 100644 index 0000000000..99371b26d9 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Create.php @@ -0,0 +1,123 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_INTEGER); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/integer') + ->desc('Create integer attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('audits.event', 'attribute.create') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/create-integer-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: $this->getResponseModel(), + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('min', null, new Integer(), 'Minimum value', true) + ->param('max', null, new Integer(), 'Maximum value', true) + ->param('default', null, new Integer(), 'Default value. Cannot be set when attribute is required.', true) + ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?int $min, + ?int $max, + ?int $default, + bool $array, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $min ??= \PHP_INT_MIN; + $max ??= \PHP_INT_MAX; + + if ($min > $max) { + throw new Exception($this->getInvalidValueException(), 'Minimum value must be lesser than maximum value'); + } + + $validator = new Range($min, $max, Database::VAR_INTEGER); + if (!\is_null($default) && !$validator->isValid($default)) { + throw new Exception($this->getInvalidValueException(), $validator->getDescription()); + } + + $size = $max > 2147483647 ? 8 : 4; + + $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ + 'key' => $key, + 'type' => Database::VAR_INTEGER, + 'size' => $size, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'format' => APP_DATABASE_ATTRIBUTE_INT_RANGE, + 'formatOptions' => ['min' => $min, 'max' => $max], + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + + $formatOptions = $attribute->getAttribute('formatOptions', []); + if (!empty($formatOptions)) { + $attribute->setAttribute('min', \intval($formatOptions['min'])); + $attribute->setAttribute('max', \intval($formatOptions['max'])); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Update.php new file mode 100644 index 0000000000..51c72af363 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Update.php @@ -0,0 +1,109 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_INTEGER); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/integer/:key') + ->desc('Update integer attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') + ->label('audits.event', 'attribute.update') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-integer-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('min', null, new Integer(), 'Minimum value', true) + ->param('max', null, new Integer(), 'Maximum value', true) + ->param('default', null, new Nullable(new Integer()), 'Default value. Cannot be set when attribute is required.') + ->param('newKey', null, new Key(), 'New Attribute Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?int $min, + ?int $max, + ?int $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $attribute = $this->updateAttribute( + databaseId: $databaseId, + collectionId: $collectionId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_INTEGER, + default: $default, + required: $required, + min: $min, + max: $max, + newKey: $newKey + ); + + $formatOptions = $attribute->getAttribute('formatOptions', []); + if (!empty($formatOptions)) { + $attribute->setAttribute('min', \intval($formatOptions['min'])); + $attribute->setAttribute('max', \intval($formatOptions['max'])); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Create.php new file mode 100644 index 0000000000..cdc1861c26 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Create.php @@ -0,0 +1,169 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/relationship') + ->desc('Create relationship attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('audits.event', 'attribute.create') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/create-relationship-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: $this->getResponseModel() + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('relatedCollectionId', '', new UID(), 'Related Collection ID.') + ->param('type', '', new WhiteList([ + Database::RELATION_ONE_TO_ONE, + Database::RELATION_MANY_TO_ONE, + Database::RELATION_MANY_TO_MANY, + Database::RELATION_ONE_TO_MANY + ], true), 'Relation type') + ->param('twoWay', false, new Boolean(), 'Is Two Way?', true) + ->param('key', null, new Key(), 'Attribute Key.', true) + ->param('twoWayKey', null, new Key(), 'Two Way Attribute Key.', true) + ->param('onDelete', Database::RELATION_MUTATE_RESTRICT, new WhiteList([ + Database::RELATION_MUTATE_CASCADE, + Database::RELATION_MUTATE_RESTRICT, + Database::RELATION_MUTATE_SET_NULL + ], true), 'Constraints option', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $relatedCollectionId, + string $type, + bool $twoWay, + ?string $key, + ?string $twoWayKey, + string $onDelete, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $key ??= $relatedCollectionId; + $twoWayKey ??= $collectionId; + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + if ($collection->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + $relatedCollectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); + $relatedCollection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollectionDocument->getInternalId()); + if ($relatedCollection->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + $attributes = $collection->getAttribute('attributes', []); + foreach ($attributes as $attribute) { + if ($attribute->getAttribute('type') !== Database::VAR_RELATIONSHIP) { + continue; + } + + if (\strtolower($attribute->getId()) === \strtolower($key)) { + throw new Exception($this->getDuplicateException()); + } + + if ( + \strtolower($attribute->getAttribute('options')['twoWayKey']) === \strtolower($twoWayKey) && + $attribute->getAttribute('options')['relatedCollection'] === $relatedCollection->getId() + ) { + throw new Exception($this->getDuplicateException(), 'Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.'); + } + + if ( + $type === Database::RELATION_MANY_TO_MANY && + $attribute->getAttribute('options')['relationType'] === Database::RELATION_MANY_TO_MANY && + $attribute->getAttribute('options')['relatedCollection'] === $relatedCollection->getId() + ) { + $parentType = $this->isCollectionsAPI() ? 'collection' : 'table'; + throw new Exception($this->getDuplicateException(), "Creating more than one \"manyToMany\" relationship on the same $parentType is currently not permitted."); + } + } + + $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ + 'key' => $key, + 'type' => Database::VAR_RELATIONSHIP, + 'size' => 0, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + 'options' => [ + 'relatedCollection' => $relatedCollectionId, + 'relationType' => $type, + 'twoWay' => $twoWay, + 'twoWayKey' => $twoWayKey, + 'onDelete' => $onDelete, + ] + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + + foreach ($attribute->getAttribute('options', []) as $k => $option) { + $attribute->setAttribute($k, $option); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Update.php new file mode 100644 index 0000000000..6416e7793e --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Update.php @@ -0,0 +1,103 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/relationship') + ->desc('Update relationship attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') + ->label('audits.event', 'attribute.update') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-relationship-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel() + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('onDelete', null, new WhiteList([ + Database::RELATION_MUTATE_CASCADE, + Database::RELATION_MUTATE_RESTRICT, + Database::RELATION_MUTATE_SET_NULL + ], true), 'Constraints option', true) + ->param('newKey', null, new Key(), 'New Attribute Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?string $onDelete, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $attribute = $this->updateAttribute( + databaseId: $databaseId, + collectionId: $collectionId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_RELATIONSHIP, + required: false, + options: [ + 'onDelete' => $onDelete + ], + newKey: $newKey + ); + + foreach ($attribute->getAttribute('options', []) as $k => $option) { + $attribute->setAttribute($k, $option); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Create.php new file mode 100644 index 0000000000..29e3ce757d --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Create.php @@ -0,0 +1,122 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_STRING); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/string') + ->desc('Create string attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('audits.event', 'attribute.create') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/create-string-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: $this->getResponseModel() + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('size', null, new Range(1, APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH, Validator::TYPE_INTEGER), 'Attribute size for text attributes, in number of characters.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, new Text(0, 0), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) + ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->param('encrypt', false, new Boolean(), 'Toggle encryption for the attribute. Encryption enhances security by not storing any plain text values in the database. However, encrypted attributes cannot be queried.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?int $size, + ?bool $required, + ?string $default, + bool $array, + bool $encrypt, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + // Ensure default fits in the given size + $validator = new Text($size, 0); + if (!is_null($default) && !$validator->isValid($default)) { + throw new Exception($this->getInvalidValueException(), $validator->getDescription()); + } + + $filters = []; + if ($encrypt) { + $filters[] = 'encrypt'; + } + + $attribute = $this->createAttribute( + $databaseId, + $collectionId, + new Document([ + 'key' => $key, + 'type' => Database::VAR_STRING, + 'size' => $size, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'filters' => $filters, + ]), + $response, + $dbForProject, + $queueForDatabase, + $queueForEvents + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Update.php new file mode 100644 index 0000000000..b76a34951e --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Update.php @@ -0,0 +1,102 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_STRING); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/string/:key') + ->desc('Update string attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') + ->label('audits.event', 'attribute.update') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-string-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, new Nullable(new Text(0, 0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.') + ->param('size', null, new Range(1, APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH, Validator::TYPE_INTEGER), 'Maximum size of the string attribute.', true) + ->param('newKey', null, new Key(), 'New Attribute Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?string $default, + ?int $size, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $attribute = $this->updateAttribute( + databaseId: $databaseId, + collectionId: $collectionId, + key: $key, + dbForProject: $dbForProject, + queueForEvents: $queueForEvents, + type: Database::VAR_STRING, + size: $size, + default: $default, + required: $required, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Create.php new file mode 100644 index 0000000000..5b1906ac2b --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Create.php @@ -0,0 +1,96 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_URL); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/url') + ->desc('Create URL attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') + ->label('audits.event', 'attribute.create') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/create-url-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: $this->getResponseModel(), + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, new URL(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) + ->param('array', false, new Boolean(), 'Is attribute an array?', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?string $default, + bool $array, + UtopiaResponse $response, + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents + ): void { + $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ + 'key' => $key, + 'type' => Database::VAR_STRING, + 'size' => 2000, + 'required' => $required, + 'default' => $default, + 'array' => $array, + 'format' => APP_DATABASE_ATTRIBUTE_URL, + ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Update.php new file mode 100644 index 0000000000..253649f15a --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Update.php @@ -0,0 +1,98 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_URL); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/url/:key') + ->desc('Update URL attribute') + ->groups(['api', 'database', 'schema']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') + ->label('audits.event', 'attribute.update') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-url-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('key', '', new Key(), 'Attribute Key.') + ->param('required', null, new Boolean(), 'Is attribute required?') + ->param('default', null, new Nullable(new URL()), 'Default value for attribute when not provided. Cannot be set when attribute is required.') + ->param('newKey', null, new Key(), 'New Attribute Key.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?string $default, + ?string $newKey, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents + ): void { + $attribute = $this->updateAttribute( + $databaseId, + $collectionId, + $key, + $dbForProject, + $queueForEvents, + type: Database::VAR_STRING, + filter: APP_DATABASE_ATTRIBUTE_URL, + default: $default, + required: $required, + newKey: $newKey + ); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($attribute, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/XList.php new file mode 100644 index 0000000000..072f6987d2 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/XList.php @@ -0,0 +1,130 @@ +setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_LIST); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes') + ->desc('List attributes') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/list-attributes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel() + ) + ] + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('queries', [], new Columns(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + if ($table->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + $queries = Query::parseQueries($queries); + + \array_push( + $queries, + Query::equal('databaseInternalId', [$database->getInternalId()]), + Query::equal('collectionInternalId', [$table->getInternalId()]) + ); + + $cursor = \array_filter( + $queries, + fn ($query) => \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]) + ); + $cursor = \reset($cursor); + + if ($cursor) { + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $attributeId = $cursor->getValue(); + $cursorDocument = Authorization::skip( + fn () => $dbForProject->find('attributes', [ + Query::equal('databaseInternalId', [$database->getInternalId()]), + Query::equal('collectionInternalId', [$table->getInternalId()]), + Query::equal('key', [$attributeId]), + Query::limit(1), + ]) + ); + + if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { + $type = ucfirst($this->getContext()); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "$type '{$attributeId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument[0]); + } + + $filters = Query::groupByType($queries)['filters']; + + try { + $attributes = $dbForProject->find('attributes', $queries); + $total = $dbForProject->count('attributes', $filters, APP_LIMIT_COUNT); + } catch (OrderException $e) { + $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; + $attribute = $this->isCollectionsAPI() ? 'attribute' : 'column'; + $message = "The order $attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all $documents order $attribute values are non-null."; + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, $message); + } + + $response->dynamic(new Document([ + 'total' => $total, + $this->getSdkGroup() => $attributes, + ]), $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php index d00bc1f9f9..2ebcdb4c3f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php @@ -13,7 +13,6 @@ use Utopia\Platform\Action as UtopiaAction; */ abstract class Action extends UtopiaAction { - /** * The current API context (either 'table' or 'collection'). */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php index 775d33ab19..29ce39789e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php @@ -58,7 +58,7 @@ class Create extends ColumnAction ->param('tableId', '', new UID(), 'Table ID.') ->param('key', '', new Key(), 'Column Key.') ->param('required', null, new Boolean(), 'Is column required?') - ->param('default', null, fn (Database $dbForProject) => new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime()), 'Default value for the attribute in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Cannot be set when column is required.', true, ['dbForProject']) + ->param('default', null, fn (Database $dbForProject) => new DatetimeValidator($dbForProject->getAdapter()->getMinDateTime(), $dbForProject->getAdapter()->getMaxDateTime()), 'Default value for the column in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Cannot be set when column is required.', true, ['dbForProject']) ->param('array', false, new Boolean(), 'Is column an array?', true) ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php index 35fe6bc86d..ca692d9269 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php @@ -61,7 +61,7 @@ class Update extends ColumnAction ->param('key', '', new Key(), 'Column Key.') ->param('required', null, new Boolean(), 'Is column required?') ->param('default', null, new Nullable(new Text(0, 0)), 'Default value for column when not provided. Cannot be set when column is required.') - ->param('size', null, new Range(1, APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH, Validator::TYPE_INTEGER), 'Maximum size of the string attribute.', true) + ->param('size', null, new Range(1, APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH, Validator::TYPE_INTEGER), 'Maximum size of the string column.', true) ->param('newKey', null, new Key(), 'New Column Key.', true) ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php index 8a6c009e87..860c32ee4b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Create.php @@ -3,7 +3,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Collections\Action; use Appwrite\Platform\Modules\Databases\Http\Collections\Create as CollectionCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php index e06c19b308..1c70401a40 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Delete.php @@ -4,7 +4,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Collections\Action; use Appwrite\Platform\Modules\Databases\Http\Collections\Delete as CollectionDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php index e5f2954de5..f7f850a0fe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Get.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables; -use Appwrite\Platform\Modules\Databases\Http\Collections\Action; use Appwrite\Platform\Modules\Databases\Http\Collections\Get as CollectionGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php index 67ff31efb7..9b86dcff8f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables\Logs; -use Appwrite\Platform\Modules\Databases\Http\Collections\Action; use Appwrite\Platform\Modules\Databases\Http\Collections\Logs\XList as CollectionLogXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php index f27232353e..4a20770cbd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Update.php @@ -3,7 +3,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Collections\Action; use Appwrite\Platform\Modules\Databases\Http\Collections\Update as CollectionUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php index 647a98d952..0371eaa3f9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Usage/Get.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables\Usage; -use Appwrite\Platform\Modules\Databases\Http\Collections\Action; use Appwrite\Platform\Modules\Databases\Http\Collections\Usage\Get as CollectionUsageGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php index 77eb556301..4381597ec6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/XList.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Tables; -use Appwrite\Platform\Modules\Databases\Http\Collections\Action; use Appwrite\Platform\Modules\Databases\Http\Collections\XList as CollectionXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; From b55521e3de5c7470cb3793d2b603110a2655ce2a Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 09:36:13 +0530 Subject: [PATCH 079/343] update: address minor comments by `coderabbitai`. --- .../Databases/Http/Attributes/Action.php | 4 ++-- .../Http/Attributes/Boolean/Create.php | 2 +- .../Http/Attributes/Email/Create.php | 22 +++++++++---------- .../Databases/Http/Collections/XList.php | 3 +-- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php index 66e8313d33..6d729b8cf3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php @@ -451,11 +451,11 @@ abstract class Action extends UtopiaAction throw new Exception($this->getNotAvailableException()); } - if ($attribute->getAttribute(('type') !== $type)) { + if ($attribute->getAttribute('type') !== $type) { throw new Exception($this->getTypeInvalidException()); } - if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute(('filter') !== $filter)) { + if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute('filter') !== $filter) { throw new Exception($this->getTypeInvalidException()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php index 583e42b4ed..1db55ba33d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php @@ -34,7 +34,7 @@ class Create extends Action ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/boolean') ->desc('Create boolean attribute') ->groups(['api', 'database', 'schema']) - ->label('event', 'databases.[databaseId].collections.[collectionId].collections.[attributeId].create') + ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Create.php index 9b63f2198a..c33ce9daeb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Create.php @@ -55,7 +55,7 @@ class Create extends Action ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Collection ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') ->param('key', '', new Key(), 'Attribute Key.') ->param('required', null, new Boolean(), 'Is attribute required?') ->param('default', null, new Email(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) @@ -68,20 +68,20 @@ class Create extends Action } public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?string $default, - bool $array, + string $databaseId, + string $collectionId, + string $key, + ?bool $required, + ?string $default, + bool $array, UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents + Database $dbForProject, + EventDatabase $queueForDatabase, + Event $queueForEvents ): void { $attribute = $this->createAttribute( $databaseId, - $tableId, + $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_STRING, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/XList.php index 98246defaa..b6d002a59b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/XList.php @@ -97,8 +97,7 @@ class XList extends Action $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionIdId); if ($cursorDocument->isEmpty()) { - $message = - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, ucfirst($this->getContext()) . " '$collectionIdId' for the 'cursor' value not found."); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, ucfirst($this->getContext()) . " '$collectionIdId' for the 'cursor' value not found."); } $cursor->setValue($cursorDocument); From fc456b4cca28da0d5b67a8c1f6439d9edef997e0 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 10:40:35 +0530 Subject: [PATCH 080/343] update: abstraction over attribute and column apis. --- .../Http/Attributes/Boolean/Create.php | 3 +- .../Http/Attributes/Boolean/Update.php | 3 +- .../Modules/Databases/Http/Columns/Action.php | 417 ------------------ .../Databases/Http/Columns/Boolean/Create.php | 40 +- .../Databases/Http/Columns/Boolean/Update.php | 41 +- .../Http/Columns/Datetime/Create.php | 59 +-- .../Http/Columns/Datetime/Update.php | 49 +- .../Modules/Databases/Http/Columns/Delete.php | 120 +---- .../Databases/Http/Columns/Email/Create.php | 57 +-- .../Databases/Http/Columns/Email/Update.php | 50 +-- .../Databases/Http/Columns/Enum/Create.php | 64 +-- .../Databases/Http/Columns/Enum/Update.php | 52 +-- .../Databases/Http/Columns/Float/Create.php | 72 +-- .../Databases/Http/Columns/Float/Update.php | 59 +-- .../Modules/Databases/Http/Columns/Get.php | 87 +--- .../Databases/Http/Columns/IP/Create.php | 49 +- .../Databases/Http/Columns/IP/Update.php | 50 +-- .../Databases/Http/Columns/Integer/Create.php | 74 +--- .../Databases/Http/Columns/Integer/Update.php | 59 +-- .../Http/Columns/Relationship/Create.php | 110 +---- .../Http/Columns/Relationship/Update.php | 53 +-- .../Databases/Http/Columns/String/Create.php | 71 +-- .../Databases/Http/Columns/String/Update.php | 52 +-- .../Databases/Http/Columns/URL/Create.php | 49 +- .../Databases/Http/Columns/URL/Update.php | 49 +- .../Modules/Databases/Http/Columns/XList.php | 88 +--- 26 files changed, 294 insertions(+), 1583 deletions(-) delete mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php index 1db55ba33d..57cff8a75f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php @@ -30,7 +30,8 @@ class Create extends Action { $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN); - $this->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/boolean') ->desc('Create boolean attribute') ->groups(['api', 'database', 'schema']) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Update.php index 41a0c5a621..7a2db8e74f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Update.php @@ -30,7 +30,8 @@ class Update extends Action { $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN); - $this->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/boolean/:key') ->desc('Update boolean attribute') ->groups(['api', 'database', 'schema']) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php deleted file mode 100644 index a9415fded3..0000000000 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Action.php +++ /dev/null @@ -1,417 +0,0 @@ -getAttribute('key'); - $type = $column->getAttribute('type', ''); - $size = $column->getAttribute('size', 0); - $required = $column->getAttribute('required', true); - $signed = $column->getAttribute('signed', true); // integers are signed by default - $array = $column->getAttribute('array', false); - $format = $column->getAttribute('format', ''); - $formatOptions = $column->getAttribute('formatOptions', []); - $filters = $column->getAttribute('filters', []); // filters are hidden from the endpoint - $default = $column->getAttribute('default'); - $options = $column->getAttribute('options', []); - - $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($db->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - if (!empty($format)) { - if (!Structure::hasFormat($format, $type)) { - throw new Exception(Exception::COLUMN_FORMAT_UNSUPPORTED, "Format {$format} not available for {$type} columns."); - } - } - - // Must throw here since dbForProject->createAttribute is performed by db worker - if ($required && isset($default)) { - throw new Exception(Exception::COLUMN_DEFAULT_UNSUPPORTED, 'Cannot set default value for required column'); - } - - if ($array && isset($default)) { - throw new Exception(Exception::COLUMN_DEFAULT_UNSUPPORTED, 'Cannot set default value for array columns'); - } - - if ($type === Database::VAR_RELATIONSHIP) { - $options['side'] = Database::RELATION_SIDE_PARENT; - $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection'] ?? ''); - if ($relatedTable->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND, 'The related table was not found.'); - } - } - - try { - $column = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $table->getInternalId() . '_' . $key), - 'key' => $key, - 'databaseInternalId' => $db->getInternalId(), - 'databaseId' => $db->getId(), - 'collectionInternalId' => $table->getInternalId(), - 'collectionId' => $tableId, - 'type' => $type, - 'status' => 'processing', // processing, available, failed, deleting, stuck - 'size' => $size, - 'required' => $required, - 'signed' => $signed, - 'default' => $default, - 'array' => $array, - 'format' => $format, - 'formatOptions' => $formatOptions, - 'filters' => $filters, - 'options' => $options, - ]); - - $dbForProject->checkAttribute($table, $column); - $column = $dbForProject->createDocument('attributes', $column); - } catch (DuplicateException) { - throw new Exception(Exception::COLUMN_ALREADY_EXISTS); - } catch (LimitException) { - throw new Exception(Exception::COLUMN_LIMIT_EXCEEDED); - } catch (Throwable $e) { - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $table->getInternalId()); - throw $e; - } - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $table->getInternalId()); - - if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { - $twoWayKey = $options['twoWayKey']; - $options['relatedCollection'] = $table->getId(); - $options['twoWayKey'] = $key; - $options['side'] = Database::RELATION_SIDE_CHILD; - - try { - $twoWayAttribute = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $twoWayKey), - 'key' => $twoWayKey, - 'databaseInternalId' => $db->getInternalId(), - 'databaseId' => $db->getId(), - 'collectionInternalId' => $relatedTable->getInternalId(), - 'collectionId' => $relatedTable->getId(), - 'type' => $type, - 'status' => 'processing', // processing, available, failed, deleting, stuck - 'size' => $size, - 'required' => $required, - 'signed' => $signed, - 'default' => $default, - 'array' => $array, - 'format' => $format, - 'formatOptions' => $formatOptions, - 'filters' => $filters, - 'options' => $options, - ]); - - $dbForProject->checkAttribute($relatedTable, $twoWayAttribute); - $dbForProject->createDocument('attributes', $twoWayAttribute); - } catch (DuplicateException) { - $dbForProject->deleteDocument('attributes', $column->getId()); - throw new Exception(Exception::COLUMN_ALREADY_EXISTS); - } catch (LimitException) { - $dbForProject->deleteDocument('attributes', $column->getId()); - throw new Exception(Exception::COLUMN_LIMIT_EXCEEDED); - } catch (Throwable $e) { - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); - throw $e; - } - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); - } - - $queueForDatabase - ->setType(DATABASE_TYPE_CREATE_ATTRIBUTE) - ->setDatabase($db) - ->setTable($table) - ->setRow($column); - - $queueForEvents - ->setContext('table', $table) - ->setContext('database', $db) - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('columnId', $column->getId()); - - $response->setStatusCode(SwooleResponse::STATUS_CODE_CREATED); - - return $column; - } - - protected function updateColumn( - string $databaseId, - string $tableId, - string $key, - Database $dbForProject, - Event $queueForEvents, - string $type, - int $size = null, - string $filter = null, - string|bool|int|float $default = null, - bool $required = null, - int|float|null $min = null, - int|float|null $max = null, - array $elements = null, - array $options = [], - string $newKey = null, - ): Document { - $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($db->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - $column = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); - - if ($column->isEmpty()) { - throw new Exception(Exception::COLUMN_NOT_FOUND); - } - - if ($column->getAttribute('status') !== 'available') { - throw new Exception(Exception::COLUMN_NOT_AVAILABLE); - } - - if ($column->getAttribute(('type') !== $type)) { - throw new Exception(Exception::COLUMN_TYPE_INVALID); - } - - if ($column->getAttribute('type') === Database::VAR_STRING && $column->getAttribute(('filter') !== $filter)) { - throw new Exception(Exception::COLUMN_TYPE_INVALID); - } - - if ($required && isset($default)) { - throw new Exception(Exception::COLUMN_DEFAULT_UNSUPPORTED, 'Cannot set default value for required column'); - } - - if ($column->getAttribute('array', false) && isset($default)) { - throw new Exception(Exception::COLUMN_DEFAULT_UNSUPPORTED, 'Cannot set default value for array columns'); - } - - $tableId = 'database_' . $db->getInternalId() . '_collection_' . $table->getInternalId(); - - $column - ->setAttribute('default', $default) - ->setAttribute('required', $required); - - if (!empty($size)) { - $column->setAttribute('size', $size); - } - - switch ($column->getAttribute('format')) { - case APP_DATABASE_ATTRIBUTE_INT_RANGE: - case APP_DATABASE_ATTRIBUTE_FLOAT_RANGE: - $min ??= $column->getAttribute('formatOptions')['min']; - $max ??= $column->getAttribute('formatOptions')['max']; - - if ($min > $max) { - throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); - } - - if ($column->getAttribute('format') === APP_DATABASE_ATTRIBUTE_INT_RANGE) { - $validator = new Range($min, $max, Database::VAR_INTEGER); - } else { - $validator = new Range($min, $max, Database::VAR_FLOAT); - - if (!is_null($default)) { - $default = \floatval($default); - } - } - - if (!is_null($default) && !$validator->isValid($default)) { - throw new Exception(Exception::COLUMN_VALUE_INVALID, $validator->getDescription()); - } - - $options = [ - 'min' => $min, - 'max' => $max - ]; - $column->setAttribute('formatOptions', $options); - - break; - case APP_DATABASE_ATTRIBUTE_ENUM: - if (empty($elements)) { - throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Enum elements must not be empty'); - } - - foreach ($elements as $element) { - if (\strlen($element) === 0) { - throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Each enum element must not be empty'); - } - } - - if (!is_null($default) && !in_array($default, $elements)) { - throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Default value not found in elements'); - } - - $options = [ - 'elements' => $elements - ]; - - $column->setAttribute('formatOptions', $options); - - break; - } - - if ($type === Database::VAR_RELATIONSHIP) { - $primaryRowOptions = \array_merge($column->getAttribute('options', []), $options); - $column->setAttribute('options', $primaryRowOptions); - try { - $dbForProject->updateRelationship( - collection: $tableId, - id: $key, - newKey: $newKey, - onDelete: $primaryRowOptions['onDelete'], - ); - } catch (NotFoundException) { - throw new Exception(Exception::COLUMN_NOT_FOUND); - } - - if ($primaryRowOptions['twoWay']) { - $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $primaryRowOptions['relatedCollection']); - - $relatedColumn = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $primaryRowOptions['twoWayKey']); - - if (!empty($newKey) && $newKey !== $key) { - $options['twoWayKey'] = $newKey; - } - - $relatedOptions = \array_merge($relatedColumn->getAttribute('options'), $options); - $relatedColumn->setAttribute('options', $relatedOptions); - $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $primaryRowOptions['twoWayKey'], $relatedColumn); - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); - } - } else { - try { - $dbForProject->updateAttribute( - collection: $tableId, - id: $key, - size: $size, - required: $required, - default: $default, - formatOptions: $options, - newKey: $newKey ?? null - ); - } catch (TruncateException) { - throw new Exception(Exception::COLUMN_INVALID_RESIZE); - } catch (NotFoundException) { - throw new Exception(Exception::COLUMN_NOT_FOUND); - } catch (LimitException) { - throw new Exception(Exception::COLUMN_LIMIT_EXCEEDED); - } catch (IndexException $e) { - throw new Exception(Exception::INDEX_INVALID, $e->getMessage()); - } - } - - if (!empty($newKey) && $key !== $newKey) { - $originalUid = $column->getId(); - - $column - ->setAttribute('$id', ID::custom($db->getInternalId() . '_' . $table->getInternalId() . '_' . $newKey)) - ->setAttribute('key', $newKey); - - $dbForProject->updateDocument('attributes', $originalUid, $column); - - /** - * @var Document $index - */ - foreach ($table->getAttribute('indexes') as $index) { - /** - * @var string[] $columns - */ - $columns = $index->getAttribute('attributes', []); - $found = \array_search($key, $columns); - - if ($found !== false) { - $columns[$found] = $newKey; - $index->setAttribute('attributes', $columns); - $dbForProject->updateDocument('indexes', $index->getId(), $index); - } - } - } else { - $column = $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key, $column); - } - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $table->getId()); - - $queueForEvents - ->setContext('table', $table) - ->setContext('database', $db) - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('columnId', $column->getId()); - - return $column; - } -} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php index 7e1331a637..385c631493 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php @@ -4,21 +4,19 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Boolean; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Boolean\Create as BooleanCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; -class Create extends ColumnAction +class Create extends BooleanCreate { use HTTP; @@ -29,9 +27,12 @@ class Create extends ColumnAction public function __construct() { - $this->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_BOOLEAN); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/boolean') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/boolean') ->desc('Create boolean column') ->groups(['api', 'database', 'schema']) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') @@ -41,14 +42,14 @@ class Create extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'createBooleanColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/create-boolean-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_COLUMN_BOOLEAN, + model: $this->getResponseModel(), ) ] )) @@ -62,23 +63,8 @@ class Create extends ColumnAction ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void - { - - $column = $this->createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_BOOLEAN, - 'size' => 0, - 'required' => $required, - 'default' => $default, - 'array' => $array, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_BOOLEAN); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php index 6725e0c817..7b0754ccc7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php @@ -3,7 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Boolean; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Boolean\Update as BooleanUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -12,13 +12,12 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Nullable; -class Update extends ColumnAction +class Update extends BooleanUpdate { use HTTP; @@ -29,9 +28,12 @@ class Update extends ColumnAction public function __construct() { - $this->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_BOOLEAN); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/boolean/:key') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/boolean/:key') ->desc('Update boolean column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -41,14 +43,14 @@ class Update extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'updateBooleanColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/update-boolean-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLUMN_BOOLEAN, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -62,25 +64,8 @@ class Update extends ColumnAction ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void - { - $column = $this->updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_BOOLEAN, - default: $default, - required: $required, - newKey: $newKey - ); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_BOOLEAN); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $default, $newKey, $response, $dbForProject, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php index 29ce39789e..80031d61ab 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php @@ -4,22 +4,20 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Datetime; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Datetime\Create as DatetimeCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; -class Create extends ColumnAction +class Create extends DatetimeCreate { use HTTP; @@ -30,10 +28,12 @@ class Create extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_DATETIME); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/datetime') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/datetime') ->desc('Create datetime column') ->groups(['api', 'database']) ->label('scope', 'collections.write') @@ -43,14 +43,14 @@ class Create extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'createDatetimeColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/create-datetime-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_COLUMN_DATETIME, + model: $this->getResponseModel(), ) ] )) @@ -64,43 +64,8 @@ class Create extends ColumnAction ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?string $default, - bool $array, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { - $filters = ['datetime']; - - $column = $this->createColumn( - $databaseId, - $tableId, - new Document([ - 'key' => $key, - 'type' => Database::VAR_DATETIME, - 'size' => 0, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'filters' => $filters, - ]), - $response, - $dbForProject, - $queueForDatabase, - $queueForEvents - ); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_DATETIME); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php index 6ff0744859..d7124981d1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php @@ -3,7 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Datetime; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Datetime\Update as DatetimeUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -13,13 +13,12 @@ use Utopia\Database\Database; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Nullable; -class Update extends ColumnAction +class Update extends DatetimeUpdate { use HTTP; @@ -30,10 +29,12 @@ class Update extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_DATETIME); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/datetime/:key') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/datetime/:key') ->desc('Update dateTime column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -43,14 +44,14 @@ class Update extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'updateDatetimeColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/update-datetime-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLUMN_DATETIME, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -64,34 +65,8 @@ class Update extends ColumnAction ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?string $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { - $column = $this->updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_DATETIME, - default: $default, - required: $required, - newKey: $newKey - ); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_DATETIME); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $default, $newKey, $response, $dbForProject, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php index 717e8f958c..eb2c6a9ccf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php @@ -4,22 +4,19 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Delete as AttributesDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\IndexDependency as IndexDependencyValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; -class Delete extends Action +class Delete extends AttributesDelete { use HTTP; @@ -30,10 +27,14 @@ class Delete extends Action public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + + // parent action handles multiple model types internally + $this->setResponseModel(UtopiaResponse::MODEL_NONE); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/:key') ->desc('Delete column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -43,14 +44,14 @@ class Delete extends Action ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'deleteColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/delete-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_NOCONTENT, - model: UtopiaResponse::MODEL_NONE, + model: $this->getResponseModel(), ) ], contentType: ContentType::NONE @@ -62,103 +63,8 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents, - ): void { - $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($db->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - $column = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); - if ($column->isEmpty()) { - throw new Exception(Exception::COLUMN_NOT_FOUND); - } - - $validator = new IndexDependencyValidator( - $table->getAttribute('indexes'), - $dbForProject->getAdapter()->getSupportForCastIndexArray(), - ); - if (!$validator->isValid($column)) { - throw new Exception(Exception::INDEX_DEPENDENCY); - } - - if ($column->getAttribute('status') === 'available') { - $column = $dbForProject->updateDocument('attributes', $column->getId(), $column->setAttribute('status', 'deleting')); - } - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $table->getInternalId()); - - if ($column->getAttribute('type') === Database::VAR_RELATIONSHIP) { - $options = $column->getAttribute('options'); - if ($options['twoWay']) { - $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection']); - if ($relatedTable->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - $relatedColumn = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $options['twoWayKey']); - if ($relatedColumn->isEmpty()) { - throw new Exception(Exception::COLUMN_NOT_FOUND); - } - - if ($relatedColumn->getAttribute('status') === 'available') { - $dbForProject->updateDocument('attributes', $relatedColumn->getId(), $relatedColumn->setAttribute('status', 'deleting')); - } - - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); - } - } - - $queueForDatabase - ->setType(DATABASE_TYPE_DELETE_ATTRIBUTE) - ->setTable($table) - ->setDatabase($db) - ->setRow($column); - - $type = $column->getAttribute('type'); - $format = $column->getAttribute('format'); - - $model = match ($type) { - Database::VAR_BOOLEAN => UtopiaResponse::MODEL_COLUMN_BOOLEAN, - Database::VAR_INTEGER => UtopiaResponse::MODEL_COLUMN_INTEGER, - Database::VAR_FLOAT => UtopiaResponse::MODEL_COLUMN_FLOAT, - Database::VAR_DATETIME => UtopiaResponse::MODEL_COLUMN_DATETIME, - Database::VAR_RELATIONSHIP => UtopiaResponse::MODEL_COLUMN_RELATIONSHIP, - Database::VAR_STRING => match ($format) { - APP_DATABASE_ATTRIBUTE_EMAIL => UtopiaResponse::MODEL_COLUMN_EMAIL, - APP_DATABASE_ATTRIBUTE_ENUM => UtopiaResponse::MODEL_COLUMN_ENUM, - APP_DATABASE_ATTRIBUTE_IP => UtopiaResponse::MODEL_COLUMN_IP, - APP_DATABASE_ATTRIBUTE_URL => UtopiaResponse::MODEL_COLUMN_URL, - default => UtopiaResponse::MODEL_COLUMN_STRING, - }, - default => UtopiaResponse::MODEL_COLUMN, - }; - - $queueForEvents - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('columnId', $column->getId()) - ->setContext('table', $table) - ->setContext('database', $db) - ->setPayload($response->output($column, $model)); - - $response->noContent(); + ->callback(function (string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php index 2372d8b032..2fdb994251 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php @@ -5,21 +5,19 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Email; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; use Appwrite\Network\Validator\Email; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Email\Create as EmailCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; -class Create extends ColumnAction +class Create extends EmailCreate { use HTTP; @@ -30,10 +28,12 @@ class Create extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_EMAIL); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/email') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/email') ->desc('Create email column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -43,14 +43,14 @@ class Create extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'createEmailColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/create-email-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_COLUMN_EMAIL, + model: $this->getResponseModel(), ) ] )) @@ -64,41 +64,8 @@ class Create extends ColumnAction ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?string $default, - bool $array, - \Appwrite\Utopia\Response $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { - $column = $this->createColumn( - $databaseId, - $tableId, - new Document([ - 'key' => $key, - 'type' => Database::VAR_STRING, - 'size' => 254, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'format' => APP_DATABASE_ATTRIBUTE_EMAIL, - ]), - $response, - $dbForProject, - $queueForDatabase, - $queueForEvents - ); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_EMAIL); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php index 74124eba37..255e636a39 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php @@ -4,7 +4,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Email; use Appwrite\Event\Event; use Appwrite\Network\Validator\Email; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Email\Update as EmailUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -13,13 +13,12 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Nullable; -class Update extends ColumnAction +class Update extends EmailUpdate { use HTTP; @@ -30,10 +29,12 @@ class Update extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_EMAIL); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/email/:key') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/email/:key') ->desc('Update email column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -43,14 +44,14 @@ class Update extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'updateEmailColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/update-email-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLUMN_EMAIL, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -64,35 +65,8 @@ class Update extends ColumnAction ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?string $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { - $column = $this->updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_STRING, - filter: APP_DATABASE_ATTRIBUTE_EMAIL, - default: $default, - required: $required, - newKey: $newKey - ); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_EMAIL); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $default, $newKey, $response, $dbForProject, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php index c57d451743..2408aeeae4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php @@ -4,24 +4,21 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Enum; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Extend\Exception; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Enum\Create as EnumCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; use Utopia\Validator\Text; -class Create extends ColumnAction +class Create extends EnumCreate { use HTTP; @@ -32,10 +29,12 @@ class Create extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_ENUM); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/enum') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/enum') ->desc('Create enum column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -45,14 +44,14 @@ class Create extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'createEnumColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/create-attribute-enum.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_COLUMN_ENUM, + model: $this->getResponseModel(), ) ] )) @@ -67,47 +66,8 @@ class Create extends ColumnAction ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - array $elements, - ?bool $required, - ?string $default, - bool $array, - \Appwrite\Utopia\Response $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { - if (!is_null($default) && !in_array($default, $elements, true)) { - throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Default value not found in elements'); - } - - $column = $this->createColumn( - $databaseId, - $tableId, - new Document([ - 'key' => $key, - 'type' => Database::VAR_STRING, - 'size' => Database::LENGTH_KEY, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'format' => APP_DATABASE_ATTRIBUTE_ENUM, - 'formatOptions' => ['elements' => $elements], - ]), - $response, - $dbForProject, - $queueForDatabase, - $queueForEvents - ); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_ENUM); + ->callback(function (string $databaseId, string $tableId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $elements, $required, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php index aa588a9f1b..c47766b4dd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php @@ -3,7 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Enum; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Enum\Update as EnumUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -12,7 +12,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; @@ -20,7 +19,7 @@ use Utopia\Validator\Boolean; use Utopia\Validator\Nullable; use Utopia\Validator\Text; -class Update extends ColumnAction +class Update extends EnumUpdate { use HTTP; @@ -31,10 +30,12 @@ class Update extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_ENUM); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/enum/:key') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/enum/:key') ->desc('Update enum column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -44,14 +45,14 @@ class Update extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'updateEnumColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/update-enum-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLUMN_ENUM, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -66,37 +67,8 @@ class Update extends ColumnAction ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?array $elements, - ?bool $required, - ?string $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { - $column = $this->updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_STRING, - filter: APP_DATABASE_ATTRIBUTE_ENUM, - default: $default, - required: $required, - elements: $elements, - newKey: $newKey - ); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_ENUM); + ->callback(function (string $databaseId, string $tableId, string $key, array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $elements, $required, $default, $newKey, $response, $dbForProject, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php index a0a16fafec..c8b9a7ec7b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php @@ -4,24 +4,20 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Float; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Extend\Exception; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Float\Create as FloatCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\FloatValidator; -use Utopia\Validator\Range; -class Create extends ColumnAction +class Create extends FloatCreate { use HTTP; @@ -32,10 +28,12 @@ class Create extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_FLOAT); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/float') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/float') ->desc('Create float column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -45,14 +43,14 @@ class Create extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'createFloatColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/create-float-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_COLUMN_FLOAT, + model: $this->getResponseModel(), ) ] )) @@ -68,54 +66,8 @@ class Create extends ColumnAction ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?float $min, - ?float $max, - ?float $default, - bool $array, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { - $min ??= -PHP_FLOAT_MAX; - $max ??= PHP_FLOAT_MAX; - - if ($min > $max) { - throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); - } - - $validator = new Range($min, $max, Database::VAR_FLOAT); - if (!\is_null($default) && !$validator->isValid($default)) { - throw new Exception(Exception::COLUMN_VALUE_INVALID, $validator->getDescription()); - } - - $column = $this->createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_FLOAT, - 'size' => 0, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'format' => APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, - 'formatOptions' => ['min' => $min, 'max' => $max], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $formatOptions = $column->getAttribute('formatOptions', []); - if (!empty($formatOptions)) { - $column->setAttribute('min', \floatval($formatOptions['min'])); - $column->setAttribute('max', \floatval($formatOptions['max'])); - } - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_FLOAT); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $min, $max, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php index 8ea7ab474a..1e008de2c0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php @@ -3,7 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Float; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Float\Update as FloatUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -12,14 +12,13 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\FloatValidator; use Utopia\Validator\Nullable; -class Update extends ColumnAction +class Update extends FloatUpdate { use HTTP; @@ -30,10 +29,12 @@ class Update extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_FLOAT); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/float/:key') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/float/:key') ->desc('Update float column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -43,14 +44,14 @@ class Update extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'updateFloatColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/update-float-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLUMN_FLOAT, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -66,44 +67,8 @@ class Update extends ColumnAction ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?float $min, - ?float $max, - ?float $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { - $column = $this->updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_FLOAT, - default: $default, - required: $required, - min: $min, - max: $max, - newKey: $newKey - ); - - $formatOptions = $column->getAttribute('formatOptions', []); - if (!empty($formatOptions)) { - $column->setAttribute('min', \floatval($formatOptions['min'])); - $column->setAttribute('max', \floatval($formatOptions['max'])); - } - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_FLOAT); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $min, $max, $default, $newKey, $response, $dbForProject, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php index 4390f0841c..d8847f0122 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php @@ -2,20 +2,18 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Get as AttributesGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; -class Get extends Action +class Get extends AttributesGet { use HTTP; @@ -26,35 +24,38 @@ class Get extends Action public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + + $this->setResponseModel([ + UtopiaResponse::MODEL_COLUMN_BOOLEAN, + UtopiaResponse::MODEL_COLUMN_INTEGER, + UtopiaResponse::MODEL_COLUMN_FLOAT, + UtopiaResponse::MODEL_COLUMN_EMAIL, + UtopiaResponse::MODEL_COLUMN_ENUM, + UtopiaResponse::MODEL_COLUMN_URL, + UtopiaResponse::MODEL_COLUMN_IP, + UtopiaResponse::MODEL_COLUMN_DATETIME, + UtopiaResponse::MODEL_COLUMN_RELATIONSHIP, + UtopiaResponse::MODEL_COLUMN_STRING, + ]); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/:key') ->desc('Get column') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'getColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/get-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: [ - UtopiaResponse::MODEL_COLUMN_BOOLEAN, - UtopiaResponse::MODEL_COLUMN_INTEGER, - UtopiaResponse::MODEL_COLUMN_FLOAT, - UtopiaResponse::MODEL_COLUMN_EMAIL, - UtopiaResponse::MODEL_COLUMN_ENUM, - UtopiaResponse::MODEL_COLUMN_URL, - UtopiaResponse::MODEL_COLUMN_IP, - UtopiaResponse::MODEL_COLUMN_DATETIME, - UtopiaResponse::MODEL_COLUMN_RELATIONSHIP, - UtopiaResponse::MODEL_COLUMN_STRING, - ] + model: $this->getResponseModel() ) ] )) @@ -63,50 +64,8 @@ class Get extends Action ->param('key', '', new Key(), 'Column Key.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject): void - { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - $column = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $table->getInternalId() . '_' . $key); - if ($column->isEmpty()) { - throw new Exception(Exception::COLUMN_NOT_FOUND); - } - - $type = $column->getAttribute('type'); - $format = $column->getAttribute('format'); - $options = $column->getAttribute('options', []); - - foreach ($options as $optKey => $optValue) { - $column->setAttribute($optKey, $optValue); - } - - $model = match ($type) { - Database::VAR_BOOLEAN => UtopiaResponse::MODEL_COLUMN_BOOLEAN, - Database::VAR_INTEGER => UtopiaResponse::MODEL_COLUMN_INTEGER, - Database::VAR_FLOAT => UtopiaResponse::MODEL_COLUMN_FLOAT, - Database::VAR_DATETIME => UtopiaResponse::MODEL_COLUMN_DATETIME, - Database::VAR_RELATIONSHIP => UtopiaResponse::MODEL_COLUMN_RELATIONSHIP, - Database::VAR_STRING => match ($format) { - APP_DATABASE_ATTRIBUTE_EMAIL => UtopiaResponse::MODEL_COLUMN_EMAIL, - APP_DATABASE_ATTRIBUTE_ENUM => UtopiaResponse::MODEL_COLUMN_ENUM, - APP_DATABASE_ATTRIBUTE_IP => UtopiaResponse::MODEL_COLUMN_IP, - APP_DATABASE_ATTRIBUTE_URL => UtopiaResponse::MODEL_COLUMN_URL, - default => UtopiaResponse::MODEL_COLUMN_STRING, - }, - default => UtopiaResponse::MODEL_COLUMN, - }; - - $response->dynamic($column, $model); + ->callback(function (string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject) { + parent::action($databaseId, $tableId, $key, $response, $dbForProject); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php index 73d8c93031..a69cc6ccfe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php @@ -4,22 +4,20 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\IP; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\IP\Create as IPCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\IP; -class Create extends ColumnAction +class Create extends IPCreate { use HTTP; @@ -30,10 +28,12 @@ class Create extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_IP); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/ip') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/ip') ->desc('Create IP address column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -43,14 +43,14 @@ class Create extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'createIpColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/create-ip-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_COLUMN_IP, + model: $this->getResponseModel(), ) ] )) @@ -64,33 +64,8 @@ class Create extends ColumnAction ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?string $default, - bool $array, - \Appwrite\Utopia\Response $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { - $column = $this->createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_STRING, - 'size' => 39, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'format' => APP_DATABASE_ATTRIBUTE_IP, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_IP); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php index 4b9fa8bca8..d4c6db12fe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php @@ -3,7 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\IP; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\IP\Update as IPUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -12,14 +12,13 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\IP; use Utopia\Validator\Nullable; -class Update extends ColumnAction +class Update extends IPUpdate { use HTTP; @@ -30,10 +29,12 @@ class Update extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_IP); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/ip/:key') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/ip/:key') ->desc('Update IP address column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -43,14 +44,14 @@ class Update extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'updateIpColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/update-ip-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLUMN_IP, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -64,35 +65,8 @@ class Update extends ColumnAction ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?string $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { - $column = $this->updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_STRING, - filter: APP_DATABASE_ATTRIBUTE_IP, - default: $default, - required: $required, - newKey: $newKey - ); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_IP); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $default, $newKey, $response, $dbForProject, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php index cf2244bf1f..2c394dd042 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php @@ -4,24 +4,20 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Integer; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Extend\Exception; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Integer\Create as IntegerCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Integer; -use Utopia\Validator\Range; -class Create extends ColumnAction +class Create extends IntegerCreate { use HTTP; @@ -32,10 +28,12 @@ class Create extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_INTEGER); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/integer') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/integer') ->desc('Create integer column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -45,14 +43,14 @@ class Create extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'createIntegerColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/create-integer-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_COLUMN_INTEGER, + model: $this->getResponseModel(), ) ] )) @@ -68,56 +66,8 @@ class Create extends ColumnAction ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?int $min, - ?int $max, - ?int $default, - bool $array, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { - $min ??= \PHP_INT_MIN; - $max ??= \PHP_INT_MAX; - - if ($min > $max) { - throw new Exception(Exception::COLUMN_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); - } - - $validator = new Range($min, $max, Database::VAR_INTEGER); - if (!\is_null($default) && !$validator->isValid($default)) { - throw new Exception(Exception::COLUMN_VALUE_INVALID, $validator->getDescription()); - } - - $size = $max > 2147483647 ? 8 : 4; - - $column = $this->createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_INTEGER, - 'size' => $size, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'format' => APP_DATABASE_ATTRIBUTE_INT_RANGE, - 'formatOptions' => ['min' => $min, 'max' => $max], - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $formatOptions = $column->getAttribute('formatOptions', []); - if (!empty($formatOptions)) { - $column->setAttribute('min', \intval($formatOptions['min'])); - $column->setAttribute('max', \intval($formatOptions['max'])); - } - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_INTEGER); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $min, $max, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php index 1806cc91c3..4eacb2b0df 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php @@ -3,7 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Integer; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Integer\Update as IntegerUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -12,14 +12,13 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Integer; use Utopia\Validator\Nullable; -class Update extends ColumnAction +class Update extends IntegerUpdate { use HTTP; @@ -30,10 +29,12 @@ class Update extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_INTEGER); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/integer/:key') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/integer/:key') ->desc('Update integer column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -43,14 +44,14 @@ class Update extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'updateIntegerColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/update-integer-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLUMN_INTEGER, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -66,44 +67,8 @@ class Update extends ColumnAction ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?int $min, - ?int $max, - ?int $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { - $column = $this->updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_INTEGER, - default: $default, - required: $required, - min: $min, - max: $max, - newKey: $newKey - ); - - $formatOptions = $column->getAttribute('formatOptions', []); - if (!empty($formatOptions)) { - $column->setAttribute('min', \intval($formatOptions['min'])); - $column->setAttribute('max', \intval($formatOptions['max'])); - } - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_INTEGER); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $min, $max, $default, $newKey, $response, $dbForProject, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php index 8b3ec616a3..d0b080b237 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php @@ -4,24 +4,20 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Relationship; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Extend\Exception; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Relationship\Create as RelationshipCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\WhiteList; -class Create extends ColumnAction +class Create extends RelationshipCreate { use HTTP; @@ -32,10 +28,12 @@ class Create extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_RELATIONSHIP); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/relationship') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/relationship') ->desc('Create relationship column') ->groups(['api', 'database']) ->label('scope', 'collections.write') @@ -45,14 +43,14 @@ class Create extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'createRelationshipColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/create-relationship-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_COLUMN_RELATIONSHIP + model: $this->getResponseModel() ) ] )) @@ -77,92 +75,8 @@ class Create extends ColumnAction ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $relatedTableId, - string $type, - bool $twoWay, - ?string $key, - ?string $twoWayKey, - string $onDelete, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { - $key ??= $relatedTableId; - $twoWayKey ??= $tableId; - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - $table = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId()); - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - $relatedTableDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId); - $relatedTable = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $relatedTableDocument->getInternalId()); - if ($relatedTable->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - $columns = $table->getAttribute('attributes', []); - foreach ($columns as $column) { - if ($column->getAttribute('type') !== Database::VAR_RELATIONSHIP) { - continue; - } - - if (\strtolower($column->getId()) === \strtolower($key)) { - throw new Exception(Exception::COLUMN_ALREADY_EXISTS); - } - - if ( - \strtolower($column->getAttribute('options')['twoWayKey']) === \strtolower($twoWayKey) && - $column->getAttribute('options')['relatedCollection'] === $relatedTable->getId() - ) { - throw new Exception(Exception::COLUMN_ALREADY_EXISTS, 'Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.'); - } - - if ( - $type === Database::RELATION_MANY_TO_MANY && - $column->getAttribute('options')['relationType'] === Database::RELATION_MANY_TO_MANY && - $column->getAttribute('options')['relatedCollection'] === $relatedTable->getId() - ) { - throw new Exception(Exception::COLUMN_ALREADY_EXISTS, 'Creating more than one "manyToMany" relationship on the same table is currently not permitted.'); - } - } - - $column = $this->createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_RELATIONSHIP, - 'size' => 0, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - 'options' => [ - 'relatedCollection' => $relatedTableId, - 'relationType' => $type, - 'twoWay' => $twoWay, - 'twoWayKey' => $twoWayKey, - 'onDelete' => $onDelete, - ] - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - foreach ($column->getAttribute('options', []) as $k => $option) { - $column->setAttribute($k, $option); - } - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_RELATIONSHIP); + ->callback(function (string $databaseId, string $tableId, string $relatedTableId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $relatedTableId, $type, $twoWayKey, $key, $twoWayKey, $onDelete, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php index 80ca25e9cf..85e4e207a5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php @@ -3,7 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\Relationship; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\Relationship\Update as RelationshipUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -12,12 +12,11 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\WhiteList; -class Update extends ColumnAction +class Update extends RelationshipUpdate { use HTTP; @@ -28,8 +27,11 @@ class Update extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_RELATIONSHIP); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key/relationship') ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/:key/relationship') ->desc('Update relationship column') @@ -41,14 +43,14 @@ class Update extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'updateRelationshipColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/update-relationship-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLUMN_RELATIONSHIP + model: $this->getResponseModel() ) ], contentType: ContentType::JSON @@ -65,39 +67,8 @@ class Update extends ColumnAction ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?string $onDelete, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { - $column = $this->updateColumn( - $databaseId, - $tableId, - $key, - $dbForProject, - $queueForEvents, - type: Database::VAR_RELATIONSHIP, - required: false, - options: [ - 'onDelete' => $onDelete - ], - newKey: $newKey - ); - - foreach ($column->getAttribute('options', []) as $k => $option) { - $column->setAttribute($k, $option); - } - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_RELATIONSHIP); + ->callback(function (string $databaseId, string $tableId, string $key, ?string $onDelete, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $onDelete, $newKey, $response, $dbForProject, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php index e768fda1d6..e00bdf679e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php @@ -4,17 +4,14 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\String; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Extend\Exception; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\String\Create as StringCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator; @@ -22,7 +19,7 @@ use Utopia\Validator\Boolean; use Utopia\Validator\Range; use Utopia\Validator\Text; -class Create extends ColumnAction +class Create extends StringCreate { use HTTP; @@ -33,10 +30,12 @@ class Create extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_STRING); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/string') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/string') ->desc('Create string column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -46,14 +45,14 @@ class Create extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'createStringColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/create-string-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_COLUMN_STRING + model: $this->getResponseModel() ) ] )) @@ -69,54 +68,8 @@ class Create extends ColumnAction ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?int $size, - ?bool $required, - ?string $default, - bool $array, - bool $encrypt, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { - // Ensure default fits in the given size - $validator = new Text($size, 0); - if (!is_null($default) && !$validator->isValid($default)) { - throw new Exception(Exception::COLUMN_VALUE_INVALID, $validator->getDescription()); - } - - $filters = []; - if ($encrypt) { - $filters[] = 'encrypt'; - } - - $column = $this->createColumn( - $databaseId, - $tableId, - new Document([ - 'key' => $key, - 'type' => Database::VAR_STRING, - 'size' => $size, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'filters' => $filters, - ]), - $response, - $dbForProject, - $queueForDatabase, - $queueForEvents - ); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_STRING); + ->callback(function (string $databaseId, string $tableId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $size, $required, $default, $array, $encrypt, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php index ca692d9269..9db47fba69 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php @@ -3,7 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\String; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\String\Update as StringUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -12,7 +12,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator; @@ -21,7 +20,7 @@ use Utopia\Validator\Nullable; use Utopia\Validator\Range; use Utopia\Validator\Text; -class Update extends ColumnAction +class Update extends StringUpdate { use HTTP; @@ -32,9 +31,12 @@ class Update extends ColumnAction public function __construct() { - $this->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_STRING); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/string/:key') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/string/:key') ->desc('Update string column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -44,14 +46,14 @@ class Update extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'updateStringColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/update-string-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLUMN_STRING, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -66,36 +68,8 @@ class Update extends ColumnAction ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?string $default, - ?int $size, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { - $column = $this->updateColumn( - databaseId: $databaseId, - tableId: $tableId, - key: $key, - dbForProject: $dbForProject, - queueForEvents: $queueForEvents, - type: Database::VAR_STRING, - size: $size, - default: $default, - required: $required, - newKey: $newKey - ); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_STRING); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?int $size, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $default, $size, $newKey, $response, $dbForProject, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php index c1483c373a..ee770e9e4d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php @@ -4,22 +4,20 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\URL; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\URL\Create as URLCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\URL; -class Create extends ColumnAction +class Create extends URLCreate { use HTTP; @@ -30,10 +28,12 @@ class Create extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_URL); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/url') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/url') ->desc('Create URL column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -43,14 +43,14 @@ class Create extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'createUrlColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/create-url-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_COLUMN_URL, + model: $this->getResponseModel(), ) ] )) @@ -64,33 +64,8 @@ class Create extends ColumnAction ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?string $default, - bool $array, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { - $column = $this->createColumn($databaseId, $tableId, new Document([ - 'key' => $key, - 'type' => Database::VAR_STRING, - 'size' => 2000, - 'required' => $required, - 'default' => $default, - 'array' => $array, - 'format' => APP_DATABASE_ATTRIBUTE_URL, - ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_URL); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php index db35cf56c4..360445750b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php @@ -3,7 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns\URL; use Appwrite\Event\Event; -use Appwrite\Platform\Modules\Databases\Http\Columns\Action as ColumnAction; +use Appwrite\Platform\Modules\Databases\Http\Attributes\URL\Update as URLUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -12,14 +12,13 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Nullable; use Utopia\Validator\URL; -class Update extends ColumnAction +class Update extends URLUpdate { use HTTP; @@ -30,8 +29,11 @@ class Update extends ColumnAction public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_URL); + $this - ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/url/:key') ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/url/:key') ->desc('Update URL column') @@ -43,14 +45,14 @@ class Update extends ColumnAction ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'updateUrlColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/update-url-attribute.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLUMN_URL, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -64,35 +66,8 @@ class Update extends ColumnAction ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); - } - - public function action( - string $databaseId, - string $tableId, - string $key, - ?bool $required, - ?string $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { - $column = $this->updateColumn( - $databaseId, - $tableId, - $key, - $dbForProject, - $queueForEvents, - type: Database::VAR_STRING, - filter: APP_DATABASE_ATTRIBUTE_URL, - default: $default, - required: $required, - newKey: $newKey - ); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_OK) - ->dynamic($column, UtopiaResponse::MODEL_COLUMN_URL); + ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $required, $default, $newKey, $response, $dbForProject, $queueForEvents); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php index c480536e6c..06d7a57dcf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php @@ -2,24 +2,18 @@ namespace Appwrite\Platform\Modules\Databases\Http\Columns; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Attributes\XList as AttributesXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Columns; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; -use Utopia\Database\Exception\Order as OrderException; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; -class XList extends Action +class XList extends AttributesXList { use HTTP; @@ -30,24 +24,26 @@ class XList extends Action public function __construct() { + $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_LIST); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes') ->desc('List columns') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'listColumns', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/list-attributes.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_COLUMN_LIST + model: $this->getResponseModel() ) ] )) @@ -56,70 +52,8 @@ class XList extends Action ->param('queries', [], new Columns(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Columns::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject): void - { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - $queries = Query::parseQueries($queries); - - \array_push( - $queries, - Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$table->getInternalId()]) - ); - - $cursor = \array_filter( - $queries, - fn ($query) => \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]) - ); - $cursor = \reset($cursor); - - if ($cursor) { - $validator = new Cursor(); - if (!$validator->isValid($cursor)) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); - } - - $columnId = $cursor->getValue(); - $cursorDocument = Authorization::skip( - fn () => $dbForProject->find('attributes', [ - Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$table->getInternalId()]), - Query::equal('key', [$columnId]), - Query::limit(1), - ]) - ); - - if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Column '{$columnId}' for the 'cursor' value not found."); - } - - $cursor->setValue($cursorDocument[0]); - } - - $filters = Query::groupByType($queries)['filters']; - - try { - $columns = $dbForProject->find('attributes', $queries); - $total = $dbForProject->count('attributes', $filters, APP_LIMIT_COUNT); - } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); - } - - $response->dynamic(new Document([ - 'columns' => $columns, - 'total' => $total, - ]), UtopiaResponse::MODEL_COLUMN_LIST); + ->callback(function (string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject) { + parent::action($databaseId, $tableId, $queries, $response, $dbForProject); + }); } } From cb64484c440a91ad6f8b50c3d96eeb568c5ba9c4 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 11:59:55 +0530 Subject: [PATCH 081/343] update: abstraction over document and row apis. --- .../Databases/Http/Attributes/Action.php | 2 - .../Databases/Http/Documents/Action.php | 138 ++++++++ .../Databases/Http/Documents/Create.php | 318 ++++++++++++++++++ .../Databases/Http/Documents/Delete.php | 174 ++++++++++ .../Modules/Databases/Http/Documents/Get.php | 157 +++++++++ .../Databases/Http/Documents/Logs/XList.php | 164 +++++++++ .../Databases/Http/Documents/Update.php | 305 +++++++++++++++++ .../Databases/Http/Documents/XList.php | 231 +++++++++++++ .../Modules/Databases/Http/Rows/Create.php | 261 +------------- .../Modules/Databases/Http/Rows/Delete.php | 124 ++----- .../Modules/Databases/Http/Rows/Get.php | 114 +------ .../Databases/Http/Rows/Logs/XList.php | 110 +----- .../Modules/Databases/Http/Rows/Update.php | 252 +------------- .../Modules/Databases/Http/Rows/XList.php | 184 +--------- .../Databases/Http/Tables/Logs/XList.php | 5 - 15 files changed, 1575 insertions(+), 964 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Documents/Action.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Documents/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Documents/Delete.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Documents/Get.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Documents/Logs/XList.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Documents/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Documents/XList.php diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php index 6d729b8cf3..3cad730b6d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php @@ -50,8 +50,6 @@ abstract class Action extends UtopiaAction /** * Get the current context. - * - * @throws \LogicException If context has not been set. */ final protected function getContext(): string { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Documents/Action.php new file mode 100644 index 0000000000..d12a9bb8a7 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Documents/Action.php @@ -0,0 +1,138 @@ +context = $context; + } + + /** + * Get the current context. + */ + final protected function getContext(): string + { + return $this->context; + } + + /** + * Returns true if current context is Collections API. + */ + final protected function isCollectionsAPI(): bool + { + // rows in tables api context + // documents in collections api context + return $this->getContext() === DATABASE_DOCUMENTS_CONTEXT; + } + + /** + * Get the SDK group name for the current action. + * + * Can be used for XList operations as well! + */ + final protected function getSdkGroup(): string + { + return $this->isCollectionsAPI() ? 'documents' : 'rows'; + } + + /** + * Get the correct parent param key (e.g. `tableId` or `collectionId`) + */ + final protected function getParentEventsParamKey(): string + { + return $this->isCollectionsAPI() ? 'collectionId' : 'tableId'; + } + + /** + * Get the correct param key (e.g. `documentId` or `rowId`) + */ + final protected function getEventsParamKey(): string + { + return $this->getContext() . 'Id'; + } + + /** + * Get the appropriate parent level not found exception. + */ + final protected function getParentNotFoundException(): string + { + return $this->isCollectionsAPI() + ? Exception::COLLECTION_NOT_FOUND + : Exception::TABLE_NOT_FOUND; + } + + /** + * Get the appropriate not found exception. + */ + final protected function getNotFoundException(): string + { + return $this->isCollectionsAPI() + ? Exception::DOCUMENT_NOT_FOUND + : Exception::ROW_NOT_FOUND; + } + + /** + * Get the appropriate already exists exception. + */ + final protected function getDuplicateException(): string + { + return $this->isCollectionsAPI() + ? Exception::DOCUMENT_ALREADY_EXISTS + : Exception::ROW_ALREADY_EXISTS; + } + + + /** + * Get the correct invalid structure message. + */ + final protected function getInvalidStructureException(): string + { + return $this->isCollectionsAPI() + ? Exception::DOCUMENT_INVALID_STRUCTURE + : Exception::ROW_INVALID_STRUCTURE; + } + + /** + * Get the appropriate missing data exception. + */ + final protected function getMissingDataException(): string + { + return $this->isCollectionsAPI() + ? Exception::DOCUMENT_MISSING_DATA + : Exception::ROW_MISSING_DATA; + } + + /** + * Get the appropriate missing payload exception. + */ + final protected function getMissingPayloadException(): string + { + return $this->isCollectionsAPI() + ? Exception::DOCUMENT_MISSING_PAYLOAD + : Exception::ROW_MISSING_PAYLOAD; + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Documents/Create.php new file mode 100644 index 0000000000..a6e938bc18 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Documents/Create.php @@ -0,0 +1,318 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents') + ->desc('Create document') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].create') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'row.create') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', [ + new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/create-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_CREATED, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + ) + ]) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('documentId', '', new CustomId(), 'Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define attributes before creating documents.') + ->param('data', [], new JSON(), 'Document data as JSON object.') + ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->inject('response') + ->inject('dbForProject') + ->inject('user') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage): void + { + $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array + + if (empty($data)) { + throw new Exception($this->getMissingDataException()); + } + + if (isset($data['$id'])) { + // `rows` or `documents` in message. + throw new Exception($this->getInvalidStructureException(), '$id is not allowed for creating new ' . $this->getContext() . 's, try update instead'); + } + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + + if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception($this->getParentNotFoundException()); + } + + $allowedPermissions = [ + Database::PERMISSION_READ, + Database::PERMISSION_UPDATE, + Database::PERMISSION_DELETE, + ]; + + // Map aggregate permissions to into the set of individual permissions they represent. + $permissions = Permission::aggregate($permissions, $allowedPermissions); + + // Add permissions for current the user if none were provided. + if (\is_null($permissions)) { + $permissions = []; + if (!empty($user->getId())) { + foreach ($allowedPermissions as $permission) { + $permissions[] = (new Permission($permission, 'user', $user->getId()))->toString(); + } + } + } + + // Users can only manage their own roles, API keys and Admin users can manage any + if (!$isAPIKey && !$isPrivilegedUser) { + foreach (Database::PERMISSIONS as $type) { + foreach ($permissions as $permission) { + $permission = Permission::parse($permission); + if ($permission->getPermission() != $type) { + continue; + } + $role = (new Role( + $permission->getRole(), + $permission->getIdentifier(), + $permission->getDimension() + ))->toString(); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')'); + } + } + } + } + + $data['$collection'] = $collection->getId(); // Adding this param to make API easier for developers + $data['$id'] = $documentId == 'unique()' ? ID::unique() : $documentId; + $data['$permissions'] = $permissions; + $document = new Document($data); + + $operations = 0; + + $checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database, &$operations) { + $operations++; + + $documentSecurity = $collection->getAttribute('documentSecurity', false); + $validator = new Authorization($permission); + + $valid = $validator->isValid($collection->getPermissionsByType($permission)); + if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } + + if ($permission === Database::PERMISSION_UPDATE) { + $valid = $valid || $validator->isValid($document->getUpdate()); + if ($documentSecurity && !$valid) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } + } + + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + + $isList = \is_array($related) && \array_values($related) === $related; + + if ($isList) { + $relations = $related; + } else { + $relations = [$related]; + } + + $relatedTableId = $relationship->getAttribute('relatedCollection'); + $relatedTable = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) + ); + + foreach ($relations as &$relation) { + if ( + \is_array($relation) + && \array_values($relation) !== $relation + && !isset($relation['$id']) + ) { + $relation['$id'] = ID::unique(); + $relation = new Document($relation); + } + if ($relation instanceof Document) { + $current = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(), $relation->getId()) + ); + + if ($current->isEmpty()) { + $type = Database::PERMISSION_CREATE; + + if (isset($relation['$id']) && $relation['$id'] === 'unique()') { + $relation['$id'] = ID::unique(); + } + } else { + $relation->removeAttribute('$collectionId'); + $relation->removeAttribute('$databaseId'); + $relation->setAttribute('$collection', $relatedTable->getId()); + $type = Database::PERMISSION_UPDATE; + } + + $checkPermissions($relatedTable, $relation, $type); + } + } + + if ($isList) { + $document->setAttribute($relationship->getAttribute('key'), \array_values($relations)); + } else { + $document->setAttribute($relationship->getAttribute('key'), \reset($relations)); + } + } + }; + + $checkPermissions($collection, $document, Database::PERMISSION_CREATE); + + try { + $document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document); + } catch (StructureException $e) { + throw new Exception($this->getInvalidStructureException(), $e->getMessage()); + } catch (DuplicateException) { + throw new Exception($this->getDuplicateException()); + } catch (NotFoundException) { + throw new Exception($this->getParentNotFoundException()); + } + + + // Add $collectionId and $databaseId for all documents + $processDocument = function (Document $table, Document $document) use (&$processDocument, $dbForProject, $database) { + $document->setAttribute('$databaseId', $database->getId()); + $document->setAttribute('$collectionId', $table->getId()); + + $relationships = \array_filter( + $table->getAttribute('attributes', []), + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + if (!\is_array($related)) { + $related = [$related]; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + ); + + foreach ($related as $relation) { + if ($relation instanceof Document) { + $processDocument($relatedCollection, $relation); + } + } + } + }; + + $processDocument($collection, $document); + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); // per collection + + $response->addHeader('X-Debug-Operations', $operations); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) + ->dynamic($document, $this->getResponseModel()); + + $relationships = \array_map( + fn ($row) => $document->getAttribute('key'), + \array_filter( + $collection->getAttribute('attributes', []), + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + ) + ); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setContext('database', $database) + ->setParam($this->getEventsParamKey(), $document->getId()) + ->setPayload($response->getPayload(), sensitive: $relationships) + ->setParam($this->getParentEventsParamKey(), $collection->getId()) + ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Documents/Delete.php new file mode 100644 index 0000000000..93a4fdb57e --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Documents/Delete.php @@ -0,0 +1,174 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') + ->desc('Delete document') + ->groups(['api', 'database']) + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].delete') + ->label('audits.event', 'document.delete') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{request.documentId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/delete-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_NOCONTENT, + model: UtopiaResponse::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('documentId', '', new UID(), 'Document ID.') + ->inject('requestTimestamp') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $collectionId, string $documentId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + + if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception($this->getParentNotFoundException()); + } + + // Read permission should not be required for delete + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + + if ($document->isEmpty()) { + throw new Exception($this->getNotFoundException()); + } + + try { + $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) { + $dbForProject->deleteDocument( + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + $documentId + ); + }); + } catch (NotFoundException) { + throw new Exception($this->getParentNotFoundException()); + } + + // Add $collection and $databaseId for all documents + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $document->setAttribute('$databaseId', $database->getId()); + $document->setAttribute('$collectionId', $collection->getId()); + + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + if (!\is_array($related)) { + $related = [$related]; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + ); + + foreach ($related as $relation) { + if ($relation instanceof Document) { + $processDocument($relatedCollection, $relation); + } + } + } + }; + + $processDocument($collection, $document); + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1); // per collection + + $response->addHeader('X-Debug-Operations', 1); + + $relationships = \array_map( + fn ($document) => $document->getAttribute('key'), + \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ) + ); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setContext('database', $database) + ->setParam($this->getParentEventsParamKey(), $collection->getId()) + ->setParam($this->getEventsParamKey(), $document->getId()) + ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection) + ->setPayload($response->output($document, $this->getResponseModel()), sensitive: $relationships); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Documents/Get.php new file mode 100644 index 0000000000..ddc08f4783 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Documents/Get.php @@ -0,0 +1,157 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') + ->desc('Get document') + ->groups(['api', 'database']) + ->label('scope', 'documents.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/get-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('documentId', '', new UID(), 'Document ID.') + ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForStatsUsage') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + + if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception($this->getParentNotFoundException()); + } + + try { + $queries = Query::parseQueries($queries); + $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries); + } catch (AuthorizationException) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + if ($document->isEmpty()) { + throw new Exception($this->getNotFoundException()); + } + + $operations = 0; + + // Add $collectionId and $databaseId for all rows + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { + if ($document->isEmpty()) { + return; + } + + $operations++; + + $document->setAttribute('$databaseId', $database->getId()); + $document->setAttribute('$collectionId', $collection->getId()); + + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + + continue; + } + + if (!\is_array($related)) { + $related = [$related]; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + ); + + foreach ($related as $relation) { + if ($relation instanceof Document) { + $processDocument($relatedCollection, $relation); + } + } + } + }; + + $processDocument($collection, $document); + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); + + $response->addHeader('X-Debug-Operations', $operations); + + $response->dynamic($document, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Documents/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Documents/Logs/XList.php new file mode 100644 index 0000000000..991c43ca1c --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Documents/Logs/XList.php @@ -0,0 +1,164 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId/logs') + ->desc('List document logs') + ->groups(['api', 'database']) + ->label('scope', 'documents.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'logs', + name: self::getName(), + description: '/docs/references/databases/get-document-logs.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON, + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('documentId', '', new UID(), 'Document ID.') + ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) + ->inject('response') + ->inject('dbForProject') + ->inject('locale') + ->inject('geodb') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + + if ($collection->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); + + if ($document->isEmpty()) { + throw new Exception($this->getNotFoundException()); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); + + $audit = new Audit($dbForProject); + // getContext() => `document` or `row`. + $resource = 'database/' . $databaseId . '/collection/' . $collectionId . '/' .$this->getContext(). '/' . $document->getId(); + $logs = $audit->getLogsByResource($resource, $queries); + + $output = []; + + foreach ($logs as $i => &$log) { + $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; + + $detector = new Detector($log['userAgent']); + $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) + + $os = $detector->getOS(); + $client = $detector->getClient(); + $device = $detector->getDevice(); + + $output[$i] = new Document([ + 'event' => $log['event'], + 'userId' => $log['data']['userId'], + 'userEmail' => $log['data']['userEmail'] ?? null, + 'userName' => $log['data']['userName'] ?? null, + 'mode' => $log['data']['mode'] ?? null, + 'ip' => $log['ip'], + 'time' => $log['time'], + 'osCode' => $os['osCode'], + 'osName' => $os['osName'], + 'osVersion' => $os['osVersion'], + 'clientType' => $client['clientType'], + 'clientCode' => $client['clientCode'], + 'clientName' => $client['clientName'], + 'clientVersion' => $client['clientVersion'], + 'clientEngine' => $client['clientEngine'], + 'clientEngineVersion' => $client['clientEngineVersion'], + 'deviceName' => $device['deviceName'], + 'deviceBrand' => $device['deviceBrand'], + 'deviceModel' => $device['deviceModel'] + ]); + + $record = $geodb->get($log['ip']); + + if ($record) { + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + } else { + $output[$i]['countryCode'] = '--'; + $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); + } + } + + $response->dynamic(new Document([ + 'logs' => $output, + 'total' => $audit->countLogsByResource($resource, $queries), + ]), $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Documents/Update.php new file mode 100644 index 0000000000..e55b9bda39 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Documents/Update.php @@ -0,0 +1,305 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->desc('Update document') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].update') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'document.update') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{response.$id}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('documentId', '', new UID(), 'Document ID.') + ->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.', true) + ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->inject('requestTimestamp') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): void + { + + $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array + + if (empty($data) && \is_null($permissions)) { + throw new Exception($this->getMissingPayloadException()); + } + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + + if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception($this->getParentNotFoundException()); + } + + // Read permission should not be required for update + /** @var Document $document */ + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + + if ($document->isEmpty()) { + throw new Exception($this->getNotFoundException()); + } + + // Map aggregate permissions into the multiple permissions they represent. + $permissions = Permission::aggregate($permissions, [ + Database::PERMISSION_READ, + Database::PERMISSION_UPDATE, + Database::PERMISSION_DELETE, + ]); + + // Users can only manage their own roles, API keys and Admin users can manage any + $roles = Authorization::getRoles(); + if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { + foreach (Database::PERMISSIONS as $type) { + foreach ($permissions as $permission) { + $permission = Permission::parse($permission); + if ($permission->getPermission() != $type) { + continue; + } + $role = (new Role( + $permission->getRole(), + $permission->getIdentifier(), + $permission->getDimension() + ))->toString(); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); + } + } + } + } + + if (\is_null($permissions)) { + $permissions = $document->getPermissions() ?? []; + } + + $data['$id'] = $documentId; + $data['$permissions'] = $permissions; + $newDocument = new Document($data); + + $operations = 0; + + $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, &$operations) { + + $operations++; + + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + + $isList = \is_array($related) && \array_values($related) === $related; + + if ($isList) { + $relations = $related; + } else { + $relations = [$related]; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + ); + + foreach ($relations as &$relation) { + // If the relation is an array it can be either update or create a child document. + if ( + \is_array($relation) + && \array_values($relation) !== $relation + && !isset($relation['$id']) + ) { + $relation['$id'] = ID::unique(); + $relation = new Document($relation); + } + if ($relation instanceof Document) { + $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + $relation->getId() + )); + $relation->removeAttribute('$collectionId'); + $relation->removeAttribute('$databaseId'); + // Attribute $collection is required for Utopia. + $relation->setAttribute( + '$collection', + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() + ); + + if ($oldDocument->isEmpty()) { + if (isset($relation['$id']) && $relation['$id'] === 'unique()') { + $relation['$id'] = ID::unique(); + } + } + $setCollection($relatedCollection, $relation); + } + } + + if ($isList) { + $document->setAttribute($relationship->getAttribute('key'), \array_values($relations)); + } else { + $document->setAttribute($relationship->getAttribute('key'), \reset($relations)); + } + } + }); + + $setCollection($collection, $newDocument); + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); + + $response->addHeader('X-Debug-Operations', $operations); + + try { + $document = $dbForProject->withRequestTimestamp( + $requestTimestamp, + fn () => $dbForProject->updateDocument( + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + $document->getId(), + $newDocument + ) + ); + } catch (AuthorizationException) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } catch (DuplicateException) { + throw new Exception($this->getDuplicateException()); + } catch (StructureException $e) { + throw new Exception($this->getInvalidStructureException(), $e->getMessage()); + } catch (NotFoundException) { + throw new Exception($this->getParentNotFoundException()); + } + + // Add $collectionId and $databaseId for all documents + $processDocument = function (Document $table, Document $row) use (&$processDocument, $dbForProject, $database) { + $row->setAttribute('$databaseId', $database->getId()); + $row->setAttribute('$collectionId', $table->getId()); + + $relationships = \array_filter( + $table->getAttribute('attributes', []), + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $row->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + if (!\is_array($related)) { + $related = [$related]; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + ); + + foreach ($related as $relation) { + if ($relation instanceof Document) { + $processDocument($relatedCollection, $relation); + } + } + } + }; + + $processDocument($collection, $document); + + $response->dynamic($document, $this->getResponseModel()); + + $relationships = \array_map( + fn ($row) => $document->getAttribute('key'), + \array_filter( + $collection->getAttribute('attributes', []), + fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + ) + ); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setContext('database', $database) + ->setParam($this->getEventsParamKey(), $document->getId()) + ->setParam($this->getParentEventsParamKey(), $collection->getId()) + ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection) + ->setPayload($response->getPayload(), sensitive: $relationships); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Documents/XList.php new file mode 100644 index 0000000000..48779ae71d --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Documents/XList.php @@ -0,0 +1,231 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents') + ->desc('List documents') + ->groups(['api', 'database']) + ->label('scope', 'documents.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/list-documents.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForStatsUsage') + ->callback([$this, 'action']); + } + + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + + if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception($this->getParentNotFoundException()); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + + $cursor = \reset($cursor); + + if ($cursor) { + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $documentId = $cursor->getValue(); + + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + + if ($cursorDocument->isEmpty()) { + $type = ucfirst($this->getContext()); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "$type '{$documentId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + try { + $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); + $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); + } catch (OrderException $e) { + $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; + $attribute = $this->isCollectionsAPI() ? 'attribute' : 'column'; + $message = "The order $attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all $documents order $attribute values are non-null."; + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, $message); + } + + $operations = 0; + + // Add $collectionId and $databaseId for all documents + $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations): bool { + if ($document->isEmpty()) { + return false; + } + + $operations++; + + $document->removeAttribute('$collection'); + $document->setAttribute('$databaseId', $database->getId()); + $document->setAttribute('$collectionId', $collection->getId()); + + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + + continue; + } + + if (!\is_array($related)) { + $relations = [$related]; + } else { + $relations = $related; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + // todo: Use local cache for this getDocument + $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)); + + foreach ($relations as $index => $doc) { + if ($doc instanceof Document) { + if (!$processDocument($relatedCollection, $doc)) { + unset($relations[$index]); + } + } + } + + if (\is_array($related)) { + $document->setAttribute($relationship->getAttribute('key'), \array_values($relations)); + } elseif (empty($relations)) { + $document->setAttribute($relationship->getAttribute('key'), null); + } + } + + return true; + }); + + foreach ($documents as $row) { + $processDocument($collection, $row); + } + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); + + $response->addHeader('X-Debug-Operations', $operations); + + $select = \array_reduce($queries, function ($result, $query) { + return $result || ($query->getMethod() === Query::TYPE_SELECT); + }, false); + + // Check if the SELECT query includes $databaseId and $collectionId + $hasDatabaseId = false; + $hasCollectionId = false; + if ($select) { + $hasDatabaseId = \array_reduce($queries, function ($result, $query) { + return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$databaseId', $query->getValues())); + }, false); + $hasCollectionId = \array_reduce($queries, function ($result, $query) { + return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$collectionId', $query->getValues())); + }, false); + } + + if ($select) { + foreach ($documents as $row) { + if (!$hasDatabaseId) { + $row->removeAttribute('$databaseId'); + } + if (!$hasCollectionId) { + $row->removeAttribute('$collectionId'); + } + } + } + + $response->dynamic(new Document([ + 'total' => $total, + // rows or documents + $this->getSdkGroup() => $documents, + ]), $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php index 87078a5d3d..fa0fca4101 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Create.php @@ -2,10 +2,9 @@ namespace Appwrite\Platform\Modules\Databases\Http\Rows; -use Appwrite\Auth\Auth; use Appwrite\Event\Event; use Appwrite\Event\StatsUsage; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Documents\Create as DocumentCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; @@ -14,21 +13,13 @@ use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Exception\Duplicate as DuplicateException; -use Utopia\Database\Exception\NotFound as NotFoundException; -use Utopia\Database\Exception\Structure as StructureException; -use Utopia\Database\Helpers\ID; -use Utopia\Database\Helpers\Permission; -use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\JSON; -class Create extends Action +class Create extends DocumentCreate { use HTTP; @@ -37,12 +28,18 @@ class Create extends Action return 'createRow'; } + protected function getResponseModel(): string + { + return UtopiaResponse::MODEL_ROW; + } + public function __construct() { + $this->setContext(DATABASE_ROWS_CONTEXT); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/documents') ->desc('Create row') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].create') @@ -56,14 +53,14 @@ class Create extends Action ->label('sdk', [ new Method( namespace: 'databases', - group: 'rows', - name: 'createRow', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/create-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_CREATED, - model: UtopiaResponse::MODEL_ROW, + model: self::getResponseModel(), ) ], contentType: ContentType::JSON @@ -79,236 +76,8 @@ class Create extends Action ->inject('user') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $rowId, string $tableId, string|array $data, ?array $permissions, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage): void - { - $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array - - if (empty($data)) { - throw new Exception(Exception::ROW_MISSING_DATA); - } - - if (isset($data['$id'])) { - throw new Exception(Exception::ROW_INVALID_STRUCTURE, '$id is not allowed for creating new rows, try update instead'); - } - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - - if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - $allowedPermissions = [ - Database::PERMISSION_READ, - Database::PERMISSION_UPDATE, - Database::PERMISSION_DELETE, - ]; - - // Map aggregate permissions to into the set of individual permissions they represent. - $permissions = Permission::aggregate($permissions, $allowedPermissions); - - // Add permissions for current the user if none were provided. - if (\is_null($permissions)) { - $permissions = []; - if (!empty($user->getId())) { - foreach ($allowedPermissions as $permission) { - $permissions[] = (new Permission($permission, 'user', $user->getId()))->toString(); - } - } - } - - // Users can only manage their own roles, API keys and Admin users can manage any - if (!$isAPIKey && !$isPrivilegedUser) { - foreach (Database::PERMISSIONS as $type) { - foreach ($permissions as $permission) { - $permission = Permission::parse($permission); - if ($permission->getPermission() != $type) { - continue; - } - $role = (new Role( - $permission->getRole(), - $permission->getIdentifier(), - $permission->getDimension() - ))->toString(); - if (!Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')'); - } - } - } - } - - $data['$collection'] = $table->getId(); // Adding this param to make API easier for developers - $data['$id'] = $rowId == 'unique()' ? ID::unique() : $rowId; - $data['$permissions'] = $permissions; - $row = new Document($data); - - $operations = 0; - - $checkPermissions = function (Document $table, Document $row, string $permission) use (&$checkPermissions, $dbForProject, $database, &$operations) { - $operations++; - - $documentSecurity = $table->getAttribute('documentSecurity', false); - $validator = new Authorization($permission); - - $valid = $validator->isValid($table->getPermissionsByType($permission)); - if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); - } - - if ($permission === Database::PERMISSION_UPDATE) { - $valid = $valid || $validator->isValid($row->getUpdate()); - if ($documentSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); - } - } - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - - $isList = \is_array($related) && \array_values($related) === $related; - - if ($isList) { - $relations = $related; - } else { - $relations = [$related]; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - $relatedTable = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) - ); - - foreach ($relations as &$relation) { - if ( - \is_array($relation) - && \array_values($relation) !== $relation - && !isset($relation['$id']) - ) { - $relation['$id'] = ID::unique(); - $relation = new Document($relation); - } - if ($relation instanceof Document) { - $current = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(), $relation->getId()) - ); - - if ($current->isEmpty()) { - $type = Database::PERMISSION_CREATE; - - if (isset($relation['$id']) && $relation['$id'] === 'unique()') { - $relation['$id'] = ID::unique(); - } - } else { - $relation->removeAttribute('$collectionId'); - $relation->removeAttribute('$databaseId'); - $relation->setAttribute('$collection', $relatedTable->getId()); - $type = Database::PERMISSION_UPDATE; - } - - $checkPermissions($relatedTable, $relation, $type); - } - } - - if ($isList) { - $row->setAttribute($relationship->getAttribute('key'), \array_values($relations)); - } else { - $row->setAttribute($relationship->getAttribute('key'), \reset($relations)); - } - } - }; - - $checkPermissions($table, $row, Database::PERMISSION_CREATE); - - try { - $row = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $row); - } catch (StructureException $e) { - throw new Exception(Exception::ROW_INVALID_STRUCTURE, $e->getMessage()); - } catch (DuplicateException) { - throw new Exception(Exception::ROW_ALREADY_EXISTS); - } catch (NotFoundException) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - - // Add $tableId and $databaseId for all rows - $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) { - $row->setAttribute('$databaseId', $database->getId()); - $row->setAttribute('$collectionId', $table->getId()); - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - $relatedTable = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processRow($relatedTable, $relation); - } - } - } - }; - - $processRow($table, $row); - - $queueForStatsUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); // per collection - - $response->addHeader('X-Debug-Operations', $operations); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) - ->dynamic($row, UtopiaResponse::MODEL_ROW); - - $relationships = \array_map( - fn ($row) => $row->getAttribute('key'), - \array_filter( - $table->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP - ) - ); - - $queueForEvents - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('rowId', $row->getId()) - ->setContext('table', $table) - ->setContext('database', $database) - ->setPayload($response->getPayload(), sensitive: $relationships); + ->callback(function (string $databaseId, string $rowId, string $tableId, string|array $data, ?array $permissions, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage) { + parent::action($databaseId, $rowId, $tableId, $databaseId, $permissions, $response, $dbForProject, $user, $queueForEvents, $queueForStatsUsage); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php index 61cd4d218a..476e4b83f2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Delete.php @@ -2,25 +2,20 @@ namespace Appwrite\Platform\Modules\Databases\Http\Rows; -use Appwrite\Auth\Auth; use Appwrite\Event\Event; use Appwrite\Event\StatsUsage; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Documents\Delete as DocumentDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; -use Utopia\Database\Exception\NotFound as NotFoundException; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; -class Delete extends Action +class Delete extends DocumentDelete { use HTTP; @@ -29,12 +24,24 @@ class Delete extends Action return 'deleteRow'; } + /** + * Same explanation as the parent action. + * + * 1. `SDKResponse` uses `UtopiaResponse::MODEL_NONE`. + * 2. But we later need the actual return type for events queue below! + */ + protected function getResponseModel(): string + { + return UtopiaResponse::MODEL_ROW; + } + public function __construct() { + $this->setContext(DATABASE_ROWS_CONTEXT); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId') ->desc('Delete row') ->groups(['api', 'database']) ->label('scope', 'documents.write') @@ -47,8 +54,8 @@ class Delete extends Action ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', new Method( namespace: 'databases', - group: 'rows', - name: 'deleteRow', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/delete-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], responses: [ @@ -67,101 +74,8 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, string $rowId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): void - { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - - if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - // Read permission should not be required for delete - $row = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); - - if ($row->isEmpty()) { - throw new Exception(Exception::ROW_NOT_FOUND); - } - - try { - $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $table, $rowId) { - $dbForProject->deleteDocument( - 'database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), - $rowId - ); + ->callback(function (string $databaseId, string $tableId, string $rowId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { + parent::action($databaseId, $tableId, $rowId, $requestTimestamp, $response, $dbForProject, $queueForEvents, $queueForStatsUsage); }); - } catch (NotFoundException) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - // Add $tableId and $databaseId for all rows - $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) { - $row->setAttribute('$databaseId', $database->getId()); - $row->setAttribute('$collectionId', $table->getId()); - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - $relatedTable = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processRow($relatedTable, $relation); - } - } - } - }; - - $processRow($table, $row); - - $queueForStatsUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1); // per collection - - $response->addHeader('X-Debug-Operations', 1); - - $relationships = \array_map( - fn ($row) => $row->getAttribute('key'), - \array_filter( - $table->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP - ) - ); - - $queueForEvents - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('rowId', $row->getId()) - ->setContext('table', $table) - ->setContext('database', $database) - ->setPayload($response->output($row, UtopiaResponse::MODEL_ROW), sensitive: $relationships); - - $response->noContent(); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php index fb600f5a7f..8eb07ef94e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php @@ -2,28 +2,21 @@ namespace Appwrite\Platform\Modules\Databases\Http\Rows; -use Appwrite\Auth\Auth; use Appwrite\Event\StatsUsage; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Documents\Get as DocumentGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; -use Utopia\Database\Exception\Authorization as AuthorizationException; -use Utopia\Database\Exception\Query as QueryException; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Text; -class Get extends Action +class Get extends DocumentGet { use HTTP; @@ -32,8 +25,15 @@ class Get extends Action return 'getRow'; } + protected function getResponseModel(): string + { + return UtopiaResponse::MODEL_ROW; + } + public function __construct() { + $this->setContext(DATABASE_ROWS_CONTEXT); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') @@ -44,14 +44,14 @@ class Get extends Action ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'rows', - name: 'getRow', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/get-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ROW, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -63,92 +63,8 @@ class Get extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, string $rowId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage): void - { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - - if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - try { - $queries = Query::parseQueries($queries); - $row = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId, $queries); - } catch (AuthorizationException) { - throw new Exception(Exception::USER_UNAUTHORIZED); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } - - if ($row->isEmpty()) { - throw new Exception(Exception::ROW_NOT_FOUND); - } - - $operations = 0; - - // Add $tableId and $databaseId for all rows - $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database, &$operations) { - if ($row->isEmpty()) { - return; - } - - $operations++; - - $row->setAttribute('$databaseId', $database->getId()); - $row->setAttribute('$collectionId', $table->getId()); - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - if (\in_array(\gettype($related), ['array', 'object'])) { - $operations++; - } - - continue; - } - - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - $relatedTable = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processRow($relatedTable, $relation); - } - } - } - }; - - $processRow($table, $row); - - $queueForStatsUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); - - $response->addHeader('X-Debug-Operations', $operations); - - $response->dynamic($row, UtopiaResponse::MODEL_ROW); + ->callback(function (string $databaseId, string $tableId, string $rowId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage) { + parent::action($databaseId, $tableId, $rowId, $queries, $response, $dbForProject, $queueForStatsUsage); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php index 238815d849..ebf5bcca1b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Logs/XList.php @@ -2,31 +2,23 @@ namespace Appwrite\Platform\Modules\Databases\Http\Rows\Logs; -use Appwrite\Detector\Detector; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Documents\Logs\XList as DocumentLogXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use MaxMind\Db\Reader; -use Utopia\Audit\Audit; use Utopia\Database\Database; -use Utopia\Database\DateTime; -use Utopia\Database\Document; -use Utopia\Database\Exception\Query as QueryException; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; -class XList extends Action +class XList extends DocumentLogXList { use HTTP; @@ -37,10 +29,11 @@ class XList extends Action public function __construct() { + $this->setContext(DATABASE_ROWS_CONTEXT); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId/logs') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId/logs') ->desc('List row logs') ->groups(['api', 'database']) ->label('scope', 'documents.read') @@ -48,13 +41,13 @@ class XList extends Action ->label('sdk', new Method( namespace: 'databases', group: 'logs', - name: 'listRowLogs', + name: self::getName(), description: '/docs/references/databases/get-document-logs.md', auth: [AuthType::ADMIN], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_LOG_LIST, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON, @@ -67,93 +60,8 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, string $rowId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void - { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - $row = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId); - - if ($row->isEmpty()) { - throw new Exception(Exception::ROW_NOT_FOUND); - } - - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } - - // Temp fix for logs - $queries[] = Query::or([ - Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), - Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), - ]); - - $audit = new Audit($dbForProject); - $resource = 'database/' . $databaseId . '/table/' . $tableId . '/row/' . $row->getId(); - $logs = $audit->getLogsByResource($resource, $queries); - - $output = []; - - foreach ($logs as $i => &$log) { - $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; - - $detector = new Detector($log['userAgent']); - $detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then) - - $os = $detector->getOS(); - $client = $detector->getClient(); - $device = $detector->getDevice(); - - $output[$i] = new Document([ - 'event' => $log['event'], - 'userId' => $log['data']['userId'], - 'userEmail' => $log['data']['userEmail'] ?? null, - 'userName' => $log['data']['userName'] ?? null, - 'mode' => $log['data']['mode'] ?? null, - 'ip' => $log['ip'], - 'time' => $log['time'], - 'osCode' => $os['osCode'], - 'osName' => $os['osName'], - 'osVersion' => $os['osVersion'], - 'clientType' => $client['clientType'], - 'clientCode' => $client['clientCode'], - 'clientName' => $client['clientName'], - 'clientVersion' => $client['clientVersion'], - 'clientEngine' => $client['clientEngine'], - 'clientEngineVersion' => $client['clientEngineVersion'], - 'deviceName' => $device['deviceName'], - 'deviceBrand' => $device['deviceBrand'], - 'deviceModel' => $device['deviceModel'] - ]); - - $record = $geodb->get($log['ip']); - - if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); - } else { - $output[$i]['countryCode'] = '--'; - $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); - } - } - - $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource, $queries), - 'logs' => $output, - ]), UtopiaResponse::MODEL_LOG_LIST); + ->callback(function (string $databaseId, string $tableId, string $rowId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb) { + parent::action($databaseId, $tableId, $rowId, $queries, $response, $dbForProject, $locale, $geodb); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php index 5590aa6c67..d29a8dcd12 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php @@ -2,33 +2,22 @@ namespace Appwrite\Platform\Modules\Databases\Http\Rows; -use Appwrite\Auth\Auth; use Appwrite\Event\Event; use Appwrite\Event\StatsUsage; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Documents\Update as DocumentUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; -use Utopia\Database\Exception\Authorization as AuthorizationException; -use Utopia\Database\Exception\Duplicate as DuplicateException; -use Utopia\Database\Exception\NotFound as NotFoundException; -use Utopia\Database\Exception\Structure as StructureException; -use Utopia\Database\Helpers\ID; -use Utopia\Database\Helpers\Permission; -use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\JSON; -class Update extends Action +class Update extends DocumentUpdate { use HTTP; @@ -37,8 +26,15 @@ class Update extends Action return 'updateRow'; } + protected function getResponseModel(): string + { + return UtopiaResponse::MODEL_ROW; + } + public function __construct() { + $this->setContext(DATABASE_ROWS_CONTEXT); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') @@ -55,14 +51,14 @@ class Update extends Action ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', new Method( namespace: 'databases', - group: 'rows', - name: 'updateRow', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/update-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ROW, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -77,226 +73,8 @@ class Update extends Action ->inject('dbForProject') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, string $rowId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): void - { - - $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array - - if (empty($data) && \is_null($permissions)) { - throw new Exception(Exception::ROW_MISSING_PAYLOAD); - } - - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - - if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - // Read permission should not be required for update - /** @var Document $row */ - $row = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); - - if ($row->isEmpty()) { - throw new Exception(Exception::ROW_NOT_FOUND); - } - - // Map aggregate permissions into the multiple permissions they represent. - $permissions = Permission::aggregate($permissions, [ - Database::PERMISSION_READ, - Database::PERMISSION_UPDATE, - Database::PERMISSION_DELETE, - ]); - - // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); - if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { - foreach (Database::PERMISSIONS as $type) { - foreach ($permissions as $permission) { - $permission = Permission::parse($permission); - if ($permission->getPermission() != $type) { - continue; - } - $role = (new Role( - $permission->getRole(), - $permission->getIdentifier(), - $permission->getDimension() - ))->toString(); - if (!Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); - } - } - } - } - - if (\is_null($permissions)) { - $permissions = $row->getPermissions() ?? []; - } - - $data['$id'] = $rowId; - $data['$permissions'] = $permissions; - $newRow = new Document($data); - - $operations = 0; - - $setTable = (function (Document $table, Document $row) use (&$setTable, $dbForProject, $database, &$operations) { - - $operations++; - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - - $isList = \is_array($related) && \array_values($related) === $related; - - if ($isList) { - $relations = $related; - } else { - $relations = [$related]; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - $relatedTable = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) - ); - - foreach ($relations as &$relation) { - // If the relation is an array it can be either update or create a child document. - if ( - \is_array($relation) - && \array_values($relation) !== $relation - && !isset($relation['$id']) - ) { - $relation['$id'] = ID::unique(); - $relation = new Document($relation); - } - if ($relation instanceof Document) { - $oldRow = Authorization::skip(fn () => $dbForProject->getDocument( - 'database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(), - $relation->getId() - )); - $relation->removeAttribute('$collectionId'); - $relation->removeAttribute('$databaseId'); - // Attribute $collection is required for Utopia. - $relation->setAttribute( - '$collection', - 'database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId() - ); - - if ($oldRow->isEmpty()) { - if (isset($relation['$id']) && $relation['$id'] === 'unique()') { - $relation['$id'] = ID::unique(); - } - } - $setTable($relatedTable, $relation); - } - } - - if ($isList) { - $row->setAttribute($relationship->getAttribute('key'), \array_values($relations)); - } else { - $row->setAttribute($relationship->getAttribute('key'), \reset($relations)); - } - } - }); - - $setTable($table, $newRow); - - $queueForStatsUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); - - $response->addHeader('X-Debug-Operations', $operations); - - try { - $row = $dbForProject->withRequestTimestamp( - $requestTimestamp, - fn () => $dbForProject->updateDocument( - 'database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), - $row->getId(), - $newRow - ) - ); - } catch (AuthorizationException) { - throw new Exception(Exception::USER_UNAUTHORIZED); - } catch (DuplicateException) { - throw new Exception(Exception::ROW_ALREADY_EXISTS); - } catch (StructureException $e) { - throw new Exception(Exception::ROW_INVALID_STRUCTURE, $e->getMessage()); - } catch (NotFoundException) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - // Add $tableId and $databaseId for all rows - $processRow = function (Document $table, Document $row) use (&$processRow, $dbForProject, $database) { - $row->setAttribute('$databaseId', $database->getId()); - $row->setAttribute('$collectionId', $table->getId()); - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - $relatedTable = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processRow($relatedTable, $relation); - } - } - } - }; - - $processRow($table, $row); - - $response->dynamic($row, UtopiaResponse::MODEL_ROW); - - $relationships = \array_map( - fn ($row) => $row->getAttribute('key'), - \array_filter( - $table->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP - ) - ); - - $queueForEvents - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('rowId', $row->getId()) - ->setContext('table', $table) - ->setContext('database', $database) - ->setPayload($response->getPayload(), sensitive: $relationships); + ->callback(function (string $databaseId, string $tableId, string $rowId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { + parent::action($databaseId, $tableId, $rowId, $data, $permissions, $requestTimestamp, $response, $dbForProject, $queueForEvents, $queueForStatsUsage); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php index 781c0d7c83..a954312493 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php @@ -2,29 +2,21 @@ namespace Appwrite\Platform\Modules\Databases\Http\Rows; -use Appwrite\Auth\Auth; use Appwrite\Event\StatsUsage; -use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Http\Documents\XList as DocumentXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; -use Utopia\Database\Exception\Order as OrderException; -use Utopia\Database\Exception\Query as QueryException; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; -use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Text; -class XList extends Action +class XList extends DocumentXList { use HTTP; @@ -33,8 +25,15 @@ class XList extends Action return 'listRows'; } + protected function getResponseModel(): string + { + return UtopiaResponse::MODEL_ROW_LIST; + } + public function __construct() { + $this->setContext(DATABASE_ROWS_CONTEXT); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') @@ -45,14 +44,14 @@ class XList extends Action ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'rows', - name: 'listRows', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/list-documents.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_ROW_LIST, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON @@ -63,161 +62,8 @@ class XList extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); - } - - public function action(string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage): void - { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $table = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId)); - - if ($table->isEmpty() || (!$table->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::TABLE_NOT_FOUND); - } - - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } - - /** - * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries - */ - $cursor = \array_filter($queries, function ($query) { - return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); - }); - - $cursor = \reset($cursor); - - if ($cursor) { - $validator = new Cursor(); - if (!$validator->isValid($cursor)) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); - } - - $rowId = $cursor->getValue(); - - $cursorRow = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $rowId)); - - if ($cursorRow->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Row '{$rowId}' for the 'cursor' value not found."); - } - - $cursor->setValue($cursorRow); - } - try { - $rows = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $queries); - $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $queries, APP_LIMIT_COUNT); - } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); - } - - $operations = 0; - - // Add $tableId and $databaseId for all rows - $processRow = (function (Document $table, Document $row) use (&$processRow, $dbForProject, $database, &$operations): bool { - if ($row->isEmpty()) { - return false; - } - - $operations++; - - $row->removeAttribute('$collection'); - $row->setAttribute('$databaseId', $database->getId()); - $row->setAttribute('$collectionId', $table->getId()); - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - if (\in_array(\gettype($related), ['array', 'object'])) { - $operations++; - } - - continue; - } - - if (!\is_array($related)) { - $relations = [$related]; - } else { - $relations = $related; - } - - $relatedTableId = $relationship->getAttribute('relatedCollection'); - // todo: Use local cache for this getDocument - $relatedTable = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId)); - - foreach ($relations as $index => $doc) { - if ($doc instanceof Document) { - if (!$processRow($relatedTable, $doc)) { - unset($relations[$index]); - } - } - } - - if (\is_array($related)) { - $row->setAttribute($relationship->getAttribute('key'), \array_values($relations)); - } elseif (empty($relations)) { - $row->setAttribute($relationship->getAttribute('key'), null); - } - } - - return true; - }); - - foreach ($rows as $row) { - $processRow($table, $row); - } - - $queueForStatsUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); - - $response->addHeader('X-Debug-Operations', $operations); - - $select = \array_reduce($queries, function ($result, $query) { - return $result || ($query->getMethod() === Query::TYPE_SELECT); - }, false); - - // Check if the SELECT query includes $databaseId and $collectionId - $hasDatabaseId = false; - $hasTableId = false; - if ($select) { - $hasDatabaseId = \array_reduce($queries, function ($result, $query) { - return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$databaseId', $query->getValues())); - }, false); - $hasTableId = \array_reduce($queries, function ($result, $query) { - return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$collectionId', $query->getValues())); - }, false); - } - - if ($select) { - foreach ($rows as $row) { - if (!$hasDatabaseId) { - $row->removeAttribute('$databaseId'); - } - if (!$hasTableId) { - $row->removeAttribute('$collectionId'); - } - } - } - - $response->dynamic(new Document([ - 'total' => $total, - 'rows' => $rows, - ]), UtopiaResponse::MODEL_ROW_LIST); + ->callback(function (string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage) { + parent::action($databaseId, $tableId, $queries, $response, $dbForProject, $queueForStatsUsage); + }); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php index 9b86dcff8f..90983dc84b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Tables/Logs/XList.php @@ -27,11 +27,6 @@ class XList extends CollectionLogXList return 'listTableLogs'; } - protected function getResponseModel(): string - { - return UtopiaResponse::MODEL_LOG_LIST; - } - public function __construct() { $this->setContext(DATABASE_TABLES_CONTEXT); From 96b89693fc2a569f72ffd2b9adaddca2f3f35480 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 12:47:21 +0530 Subject: [PATCH 082/343] update: use `abstract` for `getResponseModel`. --- .../Databases/Http/Attributes/Action.php | 24 ++----------------- .../Http/Attributes/Boolean/Create.php | 22 ++++++----------- .../Http/Attributes/Boolean/Update.php | 20 ++++++---------- .../Http/Attributes/Datetime/Create.php | 21 ++++++---------- .../Http/Attributes/Datetime/Update.php | 20 ++++++---------- .../Databases/Http/Attributes/Delete.php | 22 +++++++---------- .../Http/Attributes/Email/Create.php | 21 ++++++---------- .../Http/Attributes/Email/Update.php | 20 ++++++---------- .../Databases/Http/Attributes/Enum/Create.php | 22 ++++++----------- .../Databases/Http/Attributes/Enum/Update.php | 21 ++++++---------- .../Http/Attributes/Float/Create.php | 23 ++++++------------ .../Http/Attributes/Float/Update.php | 22 ++++++----------- .../Modules/Databases/Http/Attributes/Get.php | 22 ++++++++--------- .../Databases/Http/Attributes/IP/Create.php | 21 ++++++---------- .../Databases/Http/Attributes/IP/Update.php | 20 ++++++---------- .../Http/Attributes/Integer/Create.php | 23 ++++++------------ .../Http/Attributes/Integer/Update.php | 22 ++++++----------- .../Http/Attributes/Relationship/Create.php | 23 ++++++------------ .../Http/Attributes/Relationship/Update.php | 7 ++++-- .../Http/Attributes/String/Create.php | 7 ++++-- .../Http/Attributes/String/Update.php | 7 ++++-- .../Databases/Http/Attributes/URL/Create.php | 7 ++++-- .../Databases/Http/Attributes/URL/Update.php | 7 ++++-- .../Databases/Http/Attributes/XList.php | 17 +++++++------ .../Databases/Http/Collections/Action.php | 10 ++++---- .../Databases/Http/Columns/Boolean/Create.php | 6 ++++- .../Databases/Http/Columns/Boolean/Update.php | 6 ++++- .../Http/Columns/Datetime/Create.php | 6 ++++- .../Http/Columns/Datetime/Update.php | 6 ++++- .../Modules/Databases/Http/Columns/Delete.php | 9 ++++--- .../Databases/Http/Columns/Email/Create.php | 6 ++++- .../Databases/Http/Columns/Email/Update.php | 6 ++++- .../Databases/Http/Columns/Enum/Create.php | 6 ++++- .../Databases/Http/Columns/Enum/Update.php | 6 ++++- .../Databases/Http/Columns/Float/Create.php | 6 ++++- .../Databases/Http/Columns/Float/Update.php | 6 ++++- .../Modules/Databases/Http/Columns/Get.php | 13 ++++++---- .../Databases/Http/Columns/IP/Create.php | 6 ++++- .../Databases/Http/Columns/IP/Update.php | 6 ++++- .../Databases/Http/Columns/Integer/Create.php | 6 ++++- .../Databases/Http/Columns/Integer/Update.php | 6 ++++- .../Http/Columns/Relationship/Create.php | 6 ++++- .../Http/Columns/Relationship/Update.php | 7 ++++-- .../Databases/Http/Columns/String/Create.php | 6 ++++- .../Databases/Http/Columns/String/Update.php | 6 ++++- .../Databases/Http/Columns/URL/Create.php | 6 ++++- .../Databases/Http/Columns/URL/Update.php | 7 ++++-- .../Modules/Databases/Http/Columns/XList.php | 6 ++++- .../Modules/Databases/Http/Indexes/Create.php | 2 +- .../Modules/Databases/Http/Indexes/Delete.php | 2 +- .../Modules/Databases/Http/Indexes/Get.php | 1 - .../Modules/Databases/Http/Indexes/XList.php | 1 - .../Modules/Databases/Http/Rows/Get.php | 1 - .../Modules/Databases/Http/Rows/Update.php | 1 - .../Modules/Databases/Http/Rows/XList.php | 1 - 55 files changed, 287 insertions(+), 323 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php index 3cad730b6d..0ac013fc4f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Action.php @@ -30,9 +30,9 @@ abstract class Action extends UtopiaAction private ?string $context = DATABASE_ATTRIBUTES_CONTEXT; /** - * @var string|array|null The current response model for the attribute/column type. + * Get the correct response model. */ - private string|array|null $responseModel = null; + abstract protected function getResponseModel(): string|array; /** * Set the context to either `column` or `attribute`. @@ -92,26 +92,6 @@ abstract class Action extends UtopiaAction return $this->getContext() . 'Id'; } - /** - * Set the correct response model. - */ - final protected function setResponseModel(string|array $model): void - { - $this->responseModel = $model; - } - - /** - * Get the correct response model. - */ - final protected function getResponseModel(): string|array - { - if ($this->responseModel === null) { - throw new \LogicException("Missing response model: you must call setResponseModel() before using it."); - } - - return $this->responseModel; - } - /** * Get the appropriate parent level not found exception. */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php index 57cff8a75f..8fdbbefbcd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Create.php @@ -26,10 +26,13 @@ class Create extends Action return 'createBooleanColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/boolean') @@ -66,19 +69,8 @@ class Create extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - ?bool $required, - ?bool $default, - bool $array, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { - + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { $attribute = $this->createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, 'type' => Database::VAR_BOOLEAN, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Update.php index 7a2db8e74f..b2fdc527b3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Boolean/Update.php @@ -26,10 +26,13 @@ class Update extends Action return 'updateBooleanColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/boolean/:key') @@ -66,17 +69,8 @@ class Update extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - ?bool $required, - ?bool $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { $attribute = $this->updateAttribute( databaseId: $databaseId, collectionId: $collectionId, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Create.php index 40d7aed1e9..07f7158475 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Create.php @@ -27,10 +27,13 @@ class Create extends Action return 'createDatetimeAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_DATETIME; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_DATETIME); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/datetime') @@ -67,18 +70,8 @@ class Create extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - ?bool $required, - ?string $default, - bool $array, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { $attribute = $this->createAttribute( $databaseId, $collectionId, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Update.php index 386d6682ad..0709415d81 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Datetime/Update.php @@ -27,10 +27,13 @@ class Update extends Action return 'updateDatetimeAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_DATETIME; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_DATETIME); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/datetime/:key') @@ -67,17 +70,8 @@ class Update extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - ?bool $required, - ?string $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { $attribute = $this->updateAttribute( databaseId: $databaseId, collectionId: $collectionId, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Delete.php index da29fd09ee..bcb4d1d406 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Delete.php @@ -27,11 +27,14 @@ class Delete extends Action return 'deleteAttribute'; } - public function __construct() + protected function getResponseModel(): string|array { // we should correctly & carefully set the context later. - $this->setResponseModel(UtopiaResponse::MODEL_NONE); + return UtopiaResponse::MODEL_NONE; + } + public function __construct() + { $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') @@ -44,8 +47,8 @@ class Delete extends Action ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( namespace: 'databases', - group: 'attributes', - name: 'deleteAttribute', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/delete-attribute.md', auth: [AuthType::KEY], responses: [ @@ -66,15 +69,8 @@ class Delete extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Create.php index c33ce9daeb..bd8512a271 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Create.php @@ -27,10 +27,13 @@ class Create extends Action return 'createEmailAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_EMAIL; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_EMAIL); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/email') @@ -67,18 +70,8 @@ class Create extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - ?bool $required, - ?string $default, - bool $array, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { $attribute = $this->createAttribute( $databaseId, $collectionId, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Update.php index 0c41961099..2c39e37b19 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Email/Update.php @@ -27,10 +27,13 @@ class Update extends Action return 'updateEmailAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_EMAIL; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_EMAIL); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/email/:key') @@ -67,17 +70,8 @@ class Update extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - ?bool $required, - ?string $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { $attribute = $this->updateAttribute( databaseId: $databaseId, collectionId: $collectionId, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Create.php index 61298cbe94..fa30639bd1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Create.php @@ -29,10 +29,13 @@ class Create extends Action return 'createEnumAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_ENUM; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_ENUM); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') @@ -70,19 +73,8 @@ class Create extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - array $elements, - ?bool $required, - ?string $default, - bool $array, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { if (!is_null($default) && !\in_array($default, $elements, true)) { throw new Exception($this->getInvalidValueException(), 'Default value not found in elements'); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Update.php index 37d8065608..089407ad01 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Enum/Update.php @@ -28,10 +28,13 @@ class Update extends Action return 'updateEnumAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_ENUM; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_ENUM); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/enum/:key') @@ -69,18 +72,8 @@ class Update extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - ?array $elements, - ?bool $required, - ?string $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { $attribute = $this->updateAttribute( databaseId: $databaseId, collectionId: $collectionId, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Create.php index 9603cf4c9a..e1f22ffdd8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Create.php @@ -29,10 +29,13 @@ class Create extends Action return 'createFloatAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_FLOAT; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_FLOAT); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/float') @@ -71,20 +74,8 @@ class Create extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - ?bool $required, - ?float $min, - ?float $max, - ?float $default, - bool $array, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { $min ??= -PHP_FLOAT_MAX; $max ??= PHP_FLOAT_MAX; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Update.php index 012e8239c9..42cc5444d5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Float/Update.php @@ -27,10 +27,13 @@ class Update extends Action return 'updateFloatAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_FLOAT; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_FLOAT); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/float/:key') @@ -69,19 +72,8 @@ class Update extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - ?bool $required, - ?float $min, - ?float $max, - ?float $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { $attribute = $this->updateAttribute( databaseId: $databaseId, collectionId: $collectionId, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Get.php index e782897be2..95612b45ca 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Get.php @@ -23,9 +23,9 @@ class Get extends Action return 'getColumn'; } - public function __construct() + protected function getResponseModel(): string|array { - $this->setResponseModel([ + return [ UtopiaResponse::MODEL_ATTRIBUTE_BOOLEAN, UtopiaResponse::MODEL_ATTRIBUTE_INTEGER, UtopiaResponse::MODEL_ATTRIBUTE_FLOAT, @@ -36,8 +36,11 @@ class Get extends Action UtopiaResponse::MODEL_ATTRIBUTE_DATETIME, UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP, UtopiaResponse::MODEL_ATTRIBUTE_STRING, - ]); + ]; + } + public function __construct() + { $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') @@ -47,8 +50,8 @@ class Get extends Action ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'columns', - name: 'getColumn', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/get-attribute.md', auth: [AuthType::KEY], responses: [ @@ -66,13 +69,8 @@ class Get extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $tableId, - string $key, - UtopiaResponse $response, - Database $dbForProject - ): void { + public function action(string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject): void + { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Create.php index 8176b03bba..927d55c9c0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Create.php @@ -27,10 +27,13 @@ class Create extends Action return 'createIpAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_IP; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_IP); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') @@ -67,18 +70,8 @@ class Create extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - ?bool $required, - ?string $default, - bool $array, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { $attribute = $this->createAttribute( $databaseId, $collectionId, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Update.php index 868b735bbb..a489675bd2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/IP/Update.php @@ -27,10 +27,13 @@ class Update extends Action return 'updateIpAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_IP; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_IP); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/ip/:key') @@ -67,17 +70,8 @@ class Update extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - ?bool $required, - ?string $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { $attribute = $this->updateAttribute( databaseId: $databaseId, collectionId: $collectionId, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Create.php index 99371b26d9..9dd013362c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Create.php @@ -29,10 +29,13 @@ class Create extends Action return 'createIntegerAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_INTEGER; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_INTEGER); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/integer') @@ -71,20 +74,8 @@ class Create extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - ?bool $required, - ?int $min, - ?int $max, - ?int $default, - bool $array, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { $min ??= \PHP_INT_MIN; $max ??= \PHP_INT_MAX; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Update.php index 51c72af363..6e1379daff 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Integer/Update.php @@ -27,10 +27,13 @@ class Update extends Action return 'updateIntegerAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_INTEGER; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_INTEGER); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/integer/:key') @@ -69,19 +72,8 @@ class Update extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $key, - ?bool $required, - ?int $min, - ?int $max, - ?int $default, - ?string $newKey, - UtopiaResponse $response, - Database $dbForProject, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void + { $attribute = $this->updateAttribute( databaseId: $databaseId, collectionId: $collectionId, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Create.php index cdc1861c26..49d853bed6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Create.php @@ -29,10 +29,13 @@ class Create extends Action return 'createRelationshipAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/relationship') @@ -80,20 +83,8 @@ class Create extends Action ->callback([$this, 'action']); } - public function action( - string $databaseId, - string $collectionId, - string $relatedCollectionId, - string $type, - bool $twoWay, - ?string $key, - ?string $twoWayKey, - string $onDelete, - UtopiaResponse $response, - Database $dbForProject, - EventDatabase $queueForDatabase, - Event $queueForEvents - ): void { + public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + { $key ??= $relatedCollectionId; $twoWayKey ??= $collectionId; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Update.php index 6416e7793e..9c95bd2a65 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/Relationship/Update.php @@ -25,10 +25,13 @@ class Update extends Action return 'updateRelationshipAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_RELATIONSHIP); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/relationship') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Create.php index 29e3ce757d..47386f7530 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Create.php @@ -30,10 +30,13 @@ class Create extends Action return 'createStringAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_STRING; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_STRING); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/string') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Update.php index b76a34951e..08c55e6021 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/String/Update.php @@ -29,10 +29,13 @@ class Update extends Action return 'updateStringAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_STRING; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_STRING); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/string/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Create.php index 5b1906ac2b..38f5a4773a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Create.php @@ -27,10 +27,13 @@ class Create extends Action return 'createUrlAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_URL; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_URL); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/url') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Update.php index 253649f15a..45309326aa 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/URL/Update.php @@ -27,10 +27,13 @@ class Update extends Action return 'updateUrlAttribute'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_URL; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_URL); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/url/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/XList.php index 072f6987d2..5a190bd671 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Attributes/XList.php @@ -28,10 +28,13 @@ class XList extends Action return 'listAttributes'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_ATTRIBUTE_LIST; + } + public function __construct() { - $this->setResponseModel(UtopiaResponse::MODEL_ATTRIBUTE_LIST); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes') @@ -67,8 +70,8 @@ class XList extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); - if ($table->isEmpty()) { + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } @@ -77,7 +80,7 @@ class XList extends Action \array_push( $queries, Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$table->getInternalId()]) + Query::equal('collectionInternalId', [$collection->getInternalId()]) ); $cursor = \array_filter( @@ -96,7 +99,7 @@ class XList extends Action $cursorDocument = Authorization::skip( fn () => $dbForProject->find('attributes', [ Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$table->getInternalId()]), + Query::equal('collectionInternalId', [$collection->getInternalId()]), Query::equal('key', [$attributeId]), Query::limit(1), ]) @@ -104,7 +107,7 @@ class XList extends Action if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { $type = ucfirst($this->getContext()); - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "$type '{$attributeId}' for the 'cursor' value not found."); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "$type '$attributeId' for the 'cursor' value not found."); } $cursor->setValue($cursorDocument[0]); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php index 2ebcdb4c3f..83500fa964 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php @@ -18,6 +18,11 @@ abstract class Action extends UtopiaAction */ private ?string $context = DATABASE_COLLECTIONS_CONTEXT; + /** + * Get the response model used in the SDK and HTTP responses. + */ + abstract protected function getResponseModel(): string; + /** * Set the current API context. * @@ -50,11 +55,6 @@ abstract class Action extends UtopiaAction return $this->getContext() . 'Id'; } - /** - * Get the response model used in the SDK and HTTP responses. - */ - abstract protected function getResponseModel(): string; - /** * Determine if the current action is for the Collections API. */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php index 385c631493..fafed3bf8d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Create.php @@ -25,10 +25,14 @@ class Create extends BooleanCreate return 'createBooleanColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_BOOLEAN; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_BOOLEAN); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php index 7b0754ccc7..7bb9e640ad 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Boolean/Update.php @@ -26,10 +26,14 @@ class Update extends BooleanUpdate return 'updateBooleanColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_BOOLEAN; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_BOOLEAN); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php index 80031d61ab..7d9dc8dcce 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Create.php @@ -26,10 +26,14 @@ class Create extends DatetimeCreate return 'createDatetimeColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_DATETIME; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_DATETIME); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php index d7124981d1..7e1b1e196d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Datetime/Update.php @@ -27,10 +27,14 @@ class Update extends DatetimeUpdate return 'updateDatetimeColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_DATETIME; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_DATETIME); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php index eb2c6a9ccf..e712f7cdde 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Delete.php @@ -25,13 +25,16 @@ class Delete extends AttributesDelete return 'deleteColumn'; } + // parent handles multiple model types internally + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_NONE; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - // parent action handles multiple model types internally - $this->setResponseModel(UtopiaResponse::MODEL_NONE); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php index 2fdb994251..a3dfc0d6a2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Create.php @@ -26,10 +26,14 @@ class Create extends EmailCreate return 'createEmailColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_EMAIL; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_EMAIL); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php index 255e636a39..2f8494250e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Email/Update.php @@ -27,10 +27,14 @@ class Update extends EmailUpdate return 'updateEmailColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_EMAIL; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_EMAIL); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php index 2408aeeae4..06fc55891e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Create.php @@ -27,10 +27,14 @@ class Create extends EnumCreate return 'createEnumColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_ENUM; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_ENUM); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php index c47766b4dd..28a4538b66 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Enum/Update.php @@ -28,10 +28,14 @@ class Update extends EnumUpdate return 'updateEnumColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_ENUM; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_ENUM); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php index c8b9a7ec7b..4f5db64d57 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Create.php @@ -26,10 +26,14 @@ class Create extends FloatCreate return 'createFloatColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_FLOAT; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_FLOAT); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php index 1e008de2c0..c7ab1795db 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Float/Update.php @@ -27,10 +27,14 @@ class Update extends FloatUpdate return 'updateFloatColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_FLOAT; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_FLOAT); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php index d8847f0122..ff69757b6d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Get.php @@ -22,11 +22,9 @@ class Get extends AttributesGet return 'getColumn'; } - public function __construct() + protected function getResponseModel(): string|array { - $this->setContext(DATABASE_COLUMNS_CONTEXT); - - $this->setResponseModel([ + return [ UtopiaResponse::MODEL_COLUMN_BOOLEAN, UtopiaResponse::MODEL_COLUMN_INTEGER, UtopiaResponse::MODEL_COLUMN_FLOAT, @@ -37,7 +35,12 @@ class Get extends AttributesGet UtopiaResponse::MODEL_COLUMN_DATETIME, UtopiaResponse::MODEL_COLUMN_RELATIONSHIP, UtopiaResponse::MODEL_COLUMN_STRING, - ]); + ]; + } + + public function __construct() + { + $this->setContext(DATABASE_COLUMNS_CONTEXT); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php index a69cc6ccfe..b42f9aaf6b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Create.php @@ -26,10 +26,14 @@ class Create extends IPCreate return 'createIpColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_IP; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_IP); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php index d4c6db12fe..101041a790 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/IP/Update.php @@ -27,10 +27,14 @@ class Update extends IPUpdate return 'updateIpColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_IP; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_IP); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php index 2c394dd042..b0b5eb59bb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Create.php @@ -26,10 +26,14 @@ class Create extends IntegerCreate return 'createIntegerColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_INTEGER; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_INTEGER); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php index 4eacb2b0df..faa42aa3ca 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Integer/Update.php @@ -27,10 +27,14 @@ class Update extends IntegerUpdate return 'updateIntegerColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_INTEGER; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_INTEGER); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php index d0b080b237..2807041377 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Create.php @@ -26,10 +26,14 @@ class Create extends RelationshipCreate return 'createRelationshipColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_RELATIONSHIP; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_RELATIONSHIP); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php index 85e4e207a5..81040584b3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/Relationship/Update.php @@ -25,15 +25,18 @@ class Update extends RelationshipUpdate return 'updateRelationshipColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_RELATIONSHIP; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_RELATIONSHIP); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key/relationship') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/:key/relationship') ->desc('Update relationship column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php index e00bdf679e..a75563a271 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Create.php @@ -28,10 +28,14 @@ class Create extends StringCreate return 'createStringColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_STRING; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_STRING); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php index 9db47fba69..0b1f370696 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/String/Update.php @@ -29,10 +29,14 @@ class Update extends StringUpdate return 'updateStringColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_STRING; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_STRING); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php index ee770e9e4d..5c575acb56 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Create.php @@ -26,10 +26,14 @@ class Create extends URLCreate return 'createUrlColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_URL; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_URL); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php index 360445750b..c37a74198a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/URL/Update.php @@ -27,15 +27,18 @@ class Update extends URLUpdate return 'updateUrlColumn'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_URL; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_URL); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/url/:key') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/attributes/url/:key') ->desc('Update URL column') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php index 06d7a57dcf..280e56fa48 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Columns/XList.php @@ -22,10 +22,14 @@ class XList extends AttributesXList return 'listColumns'; } + protected function getResponseModel(): string|array + { + return UtopiaResponse::MODEL_COLUMN_LIST; + } + public function __construct() { $this->setContext(DATABASE_COLUMNS_CONTEXT); - $this->setResponseModel(UtopiaResponse::MODEL_COLUMN_LIST); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php index 537d8e27f0..e9dd4c7092 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Create.php @@ -39,13 +39,13 @@ class Create extends Action $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/indexes') ->desc('Create index') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'index.create') + // TODO: audits table or collections, check the context type if possible, move into another module. ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Delete.php index 78e1799164..dd7c4bd5e7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Delete.php @@ -32,13 +32,13 @@ class Delete extends Action $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes/:key') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/indexes/:key') ->desc('Delete index') ->groups(['api', 'database']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].update') ->label('audits.event', 'index.delete') + // TODO: audits table or collections, check the context type if possible ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( namespace: 'databases', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Get.php index b1689481ed..a89819d844 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/Get.php @@ -30,7 +30,6 @@ class Get extends Action $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes/:key') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/indexes/:key') ->desc('Get index') ->groups(['api', 'database']) ->label('scope', 'collections.read') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/XList.php index 53c623f9f4..b11806cfd0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Indexes/XList.php @@ -34,7 +34,6 @@ class XList extends Action $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/indexes') ->desc('List indexes') ->groups(['api', 'database']) ->label('scope', 'collections.read') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php index 8eb07ef94e..3ec0ea6213 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Get.php @@ -37,7 +37,6 @@ class Get extends DocumentGet $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId') ->desc('Get row') ->groups(['api', 'database']) ->label('scope', 'documents.read') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php index d29a8dcd12..34d947796e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/Update.php @@ -38,7 +38,6 @@ class Update extends DocumentUpdate $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/documents/:rowId') ->desc('Update row') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].update') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php index a954312493..041f532840 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Rows/XList.php @@ -37,7 +37,6 @@ class XList extends DocumentXList $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') - ->httpAlias('/v1/databases/:databaseId/collections/:tableId/documents') ->desc('List rows') ->groups(['api', 'database']) ->label('scope', 'documents.read') From da70da985ba1e61ca0eda5c0f29b74b8c82c590d Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 12:55:54 +0530 Subject: [PATCH 083/343] update: use nested directory structure. --- .../Databases/Http/{ => Databases}/Collections/Action.php | 2 +- .../Http/{ => Databases/Collections}/Attributes/Action.php | 2 +- .../{ => Databases/Collections}/Attributes/Boolean/Create.php | 4 ++-- .../{ => Databases/Collections}/Attributes/Boolean/Update.php | 4 ++-- .../Collections}/Attributes/Datetime/Create.php | 4 ++-- .../Collections}/Attributes/Datetime/Update.php | 4 ++-- .../Http/{ => Databases/Collections}/Attributes/Delete.php | 2 +- .../{ => Databases/Collections}/Attributes/Email/Create.php | 4 ++-- .../{ => Databases/Collections}/Attributes/Email/Update.php | 4 ++-- .../{ => Databases/Collections}/Attributes/Enum/Create.php | 4 ++-- .../{ => Databases/Collections}/Attributes/Enum/Update.php | 4 ++-- .../{ => Databases/Collections}/Attributes/Float/Create.php | 4 ++-- .../{ => Databases/Collections}/Attributes/Float/Update.php | 4 ++-- .../Http/{ => Databases/Collections}/Attributes/Get.php | 2 +- .../Http/{ => Databases/Collections}/Attributes/IP/Create.php | 4 ++-- .../Http/{ => Databases/Collections}/Attributes/IP/Update.php | 4 ++-- .../{ => Databases/Collections}/Attributes/Integer/Create.php | 4 ++-- .../{ => Databases/Collections}/Attributes/Integer/Update.php | 4 ++-- .../Collections}/Attributes/Relationship/Create.php | 4 ++-- .../Collections}/Attributes/Relationship/Update.php | 4 ++-- .../{ => Databases/Collections}/Attributes/String/Create.php | 4 ++-- .../{ => Databases/Collections}/Attributes/String/Update.php | 4 ++-- .../{ => Databases/Collections}/Attributes/URL/Create.php | 4 ++-- .../{ => Databases/Collections}/Attributes/URL/Update.php | 4 ++-- .../Http/{ => Databases/Collections}/Attributes/XList.php | 2 +- .../Databases/Http/{ => Databases}/Collections/Create.php | 2 +- .../Databases/Http/{ => Databases}/Collections/Delete.php | 2 +- .../Http/{ => Databases/Collections}/Documents/Action.php | 2 +- .../Http/{ => Databases/Collections}/Documents/Create.php | 2 +- .../Http/{ => Databases/Collections}/Documents/Delete.php | 2 +- .../Http/{ => Databases/Collections}/Documents/Get.php | 2 +- .../Http/{ => Databases/Collections}/Documents/Logs/XList.php | 4 ++-- .../Http/{ => Databases/Collections}/Documents/Update.php | 2 +- .../Http/{ => Databases/Collections}/Documents/XList.php | 2 +- .../Databases/Http/{ => Databases}/Collections/Get.php | 2 +- .../Http/{ => Databases/Collections}/Indexes/Create.php | 0 .../Http/{ => Databases/Collections}/Indexes/Delete.php | 0 .../Http/{ => Databases/Collections}/Indexes/Get.php | 0 .../Http/{ => Databases/Collections}/Indexes/XList.php | 0 .../Databases/Http/{ => Databases}/Collections/Logs/XList.php | 4 ++-- .../Databases/Http/{ => Databases}/Collections/Update.php | 2 +- .../Databases/Http/{ => Databases}/Collections/Usage/Get.php | 4 ++-- .../Databases/Http/{ => Databases}/Collections/XList.php | 2 +- .../Http/{ => Databases/Tables}/Columns/Boolean/Create.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/Boolean/Update.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/Datetime/Create.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/Datetime/Update.php | 4 ++-- .../Databases/Http/{ => Databases/Tables}/Columns/Delete.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/Email/Create.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/Email/Update.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/Enum/Create.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/Enum/Update.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/Float/Create.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/Float/Update.php | 4 ++-- .../Databases/Http/{ => Databases/Tables}/Columns/Get.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/IP/Create.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/IP/Update.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/Integer/Create.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/Integer/Update.php | 4 ++-- .../{ => Databases/Tables}/Columns/Relationship/Create.php | 4 ++-- .../{ => Databases/Tables}/Columns/Relationship/Update.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/String/Create.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/String/Update.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/URL/Create.php | 4 ++-- .../Http/{ => Databases/Tables}/Columns/URL/Update.php | 4 ++-- .../Databases/Http/{ => Databases/Tables}/Columns/XList.php | 4 ++-- .../Modules/Databases/Http/{ => Databases}/Tables/Create.php | 4 ++-- .../Modules/Databases/Http/{ => Databases}/Tables/Delete.php | 4 ++-- .../Modules/Databases/Http/{ => Databases}/Tables/Get.php | 4 ++-- .../Databases/Http/{ => Databases}/Tables/Logs/XList.php | 4 ++-- .../Databases/Http/{ => Databases/Tables}/Rows/Create.php | 4 ++-- .../Databases/Http/{ => Databases/Tables}/Rows/Delete.php | 4 ++-- .../Databases/Http/{ => Databases/Tables}/Rows/Get.php | 4 ++-- .../Databases/Http/{ => Databases/Tables}/Rows/Logs/XList.php | 4 ++-- .../Databases/Http/{ => Databases/Tables}/Rows/Update.php | 4 ++-- .../Databases/Http/{ => Databases/Tables}/Rows/XList.php | 4 ++-- .../Modules/Databases/Http/{ => Databases}/Tables/Update.php | 4 ++-- .../Databases/Http/{ => Databases}/Tables/Usage/Get.php | 4 ++-- .../Modules/Databases/Http/{ => Databases}/Tables/XList.php | 4 ++-- 79 files changed, 134 insertions(+), 134 deletions(-) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Collections/Action.php (97%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Action.php (99%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Boolean/Create.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Boolean/Update.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Datetime/Create.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Datetime/Update.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Delete.php (98%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Email/Create.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Email/Update.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Enum/Create.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Enum/Update.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Float/Create.php (96%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Float/Update.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Get.php (97%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/IP/Create.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/IP/Update.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Integer/Create.php (96%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Integer/Update.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Relationship/Create.php (97%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/Relationship/Update.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/String/Create.php (96%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/String/Update.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/URL/Create.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/URL/Update.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Attributes/XList.php (98%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Collections/Create.php (98%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Collections/Delete.php (98%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Documents/Action.php (97%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Documents/Create.php (99%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Documents/Delete.php (98%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Documents/Get.php (98%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Documents/Logs/XList.php (97%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Documents/Update.php (99%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Documents/XList.php (99%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Collections/Get.php (97%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Indexes/Create.php (100%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Indexes/Delete.php (100%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Indexes/Get.php (100%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Collections}/Indexes/XList.php (100%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Collections/Logs/XList.php (97%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Collections/Update.php (98%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Collections/Usage/Get.php (97%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Collections/XList.php (98%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Boolean/Create.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Boolean/Update.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Datetime/Create.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Datetime/Update.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Delete.php (93%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Email/Create.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Email/Update.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Enum/Create.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Enum/Update.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Float/Create.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Float/Update.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Get.php (93%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/IP/Create.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/IP/Update.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Integer/Create.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Integer/Update.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Relationship/Create.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/Relationship/Update.php (93%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/String/Create.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/String/Update.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/URL/Create.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/URL/Update.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Columns/XList.php (93%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Tables/Create.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Tables/Delete.php (93%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Tables/Get.php (92%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Tables/Logs/XList.php (93%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Rows/Create.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Rows/Delete.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Rows/Get.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Rows/Logs/XList.php (93%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Rows/Update.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases/Tables}/Rows/XList.php (94%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Tables/Update.php (95%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Tables/Usage/Get.php (92%) rename src/Appwrite/Platform/Modules/Databases/Http/{ => Databases}/Tables/XList.php (94%) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php similarity index 97% rename from src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php rename to src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php index 83500fa964..eaaa08d237 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Collections/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php @@ -1,6 +1,6 @@ Date: Thu, 8 May 2025 14:15:00 +0530 Subject: [PATCH 084/343] add: indexes api to tables. --- app/config/errors.php | 27 +++ app/controllers/general.php | 8 +- app/init/constants.php | 2 + src/Appwrite/Extend/Exception.php | 7 + .../Http/Databases/Collections/Action.php | 8 - .../Collections/Attributes/Action.php | 14 +- .../Collections/Attributes/Delete.php | 2 +- .../Databases/Collections/Indexes/Action.php | 163 ++++++++++++++++++ .../Databases/Collections/Indexes/Create.php | 106 +++++++----- .../Databases/Collections/Indexes/Delete.php | 64 ++++--- .../Databases/Collections/Indexes/Get.php | 33 ++-- .../Databases/Collections/Indexes/XList.php | 38 ++-- .../Http/Databases/Tables/Indexes/Create.php | 72 ++++++++ .../Http/Databases/Tables/Indexes/Delete.php | 71 ++++++++ .../Http/Databases/Tables/Indexes/Get.php | 60 +++++++ .../Http/Databases/Tables/Indexes/XList.php | 60 +++++++ 16 files changed, 624 insertions(+), 111 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php diff --git a/app/config/errors.php b/app/config/errors.php index 182b6286e8..de26b077fc 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -903,6 +903,33 @@ return [ 'code' => 409, ], + /** Column Indexes, same as Indexes but with different type */ + Exception::COLUMN_INDEX_NOT_FOUND => [ + 'name' => Exception::COLUMN_INDEX_NOT_FOUND, + 'description' => 'Index with the requested ID could not be found.', + 'code' => 404, + ], + Exception::COLUMN_INDEX_LIMIT_EXCEEDED => [ + 'name' => Exception::COLUMN_INDEX_LIMIT_EXCEEDED, + 'description' => 'The maximum number of indexes has been reached.', + 'code' => 400, + ], + Exception::COLUMN_INDEX_ALREADY_EXISTS => [ + 'name' => Exception::COLUMN_INDEX_ALREADY_EXISTS, + 'description' => 'Index with the requested key already exists. Try again with a different key.', + 'code' => 409, + ], + Exception::COLUMN_INDEX_INVALID => [ + 'name' => Exception::COLUMN_INDEX_INVALID, + 'description' => 'Index invalid.', + 'code' => 400, + ], + Exception::COLUMN_INDEX_DEPENDENCY => [ + 'name' => Exception::COLUMN_INDEX_DEPENDENCY, + 'description' => 'Column cannot be renamed or deleted. Please remove the associated index first.', + 'code' => 409, + ], + /** Project Errors */ Exception::PROJECT_NOT_FOUND => [ 'name' => Exception::PROJECT_NOT_FOUND, diff --git a/app/controllers/general.php b/app/controllers/general.php index da68d4758c..b7ee606c69 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1216,7 +1216,13 @@ App::error() ); break; case 'Utopia\Database\Exception\Dependency': - $error = new AppwriteException(AppwriteException::INDEX_DEPENDENCY, null, previous: $error); + $error = new AppwriteException( + $isTablesAPI + ? AppwriteException::COLUMN_INDEX_DEPENDENCY + : AppwriteException::INDEX_DEPENDENCY, + null, + previous: $error + ); break; } diff --git a/app/init/constants.php b/app/init/constants.php index 29a861c45a..c3b6d4a058 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -271,7 +271,9 @@ const TOKENS_RESOURCE_TYPE_DATABASES = 'databases'; const DATABASE_ROWS_CONTEXT = 'row'; const DATABASE_TABLES_CONTEXT = 'table'; const DATABASE_COLUMNS_CONTEXT = 'column'; +const DATABASE_INDEX_CONTEXT = 'index'; const DATABASE_DOCUMENTS_CONTEXT = 'document'; const DATABASE_ATTRIBUTES_CONTEXT = 'attribute'; const DATABASE_COLLECTIONS_CONTEXT = 'collection'; +const DATABASE_COLUMN_INDEX_CONTEXT = 'columnIndex'; diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 15b964577d..38a562571c 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -253,6 +253,13 @@ class Exception extends \Exception public const INDEX_INVALID = 'index_invalid'; public const INDEX_DEPENDENCY = 'index_dependency'; + /** Column Indexes */ + public const COLUMN_INDEX_NOT_FOUND = 'column_index_not_found'; + public const COLUMN_INDEX_LIMIT_EXCEEDED = 'column_index_limit_exceeded'; + public const COLUMN_INDEX_ALREADY_EXISTS = 'column_index_already_exists'; + public const COLUMN_INDEX_INVALID = 'column_index_invalid'; + public const COLUMN_INDEX_DEPENDENCY = 'column_index_dependency'; + /** Projects */ public const PROJECT_NOT_FOUND = 'project_not_found'; public const PROJECT_PROVIDER_DISABLED = 'project_provider_disabled'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php index eaaa08d237..abec90f1a6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php @@ -5,12 +5,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections; use Appwrite\Extend\Exception; use Utopia\Platform\Action as UtopiaAction; -/** - * Abstract base action for Collection and Table database routes. - * - * Provides shared utilities to determine API type, response model, - * SDK group, and context-specific exceptions. - */ abstract class Action extends UtopiaAction { /** @@ -39,8 +33,6 @@ abstract class Action extends UtopiaAction /** * Get the current API context. - * - * @throws \Exception if context has not been set. */ final protected function getContext(): string { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 1c779f4d3b..fff070d58f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -42,7 +42,7 @@ abstract class Action extends UtopiaAction final protected function setContext(string $context): void { if (!\in_array($context, [DATABASE_COLUMNS_CONTEXT, DATABASE_ATTRIBUTES_CONTEXT], true)) { - throw new \InvalidArgumentException("Invalid context '{$context}'. Use `DATABASE_COLUMNS_CONTEXT` or `DATABASE_ATTRIBUTES_CONTEXT`"); + throw new \InvalidArgumentException("Invalid context '$context'. Use `DATABASE_COLUMNS_CONTEXT` or `DATABASE_ATTRIBUTES_CONTEXT`"); } $this->context = $context; @@ -112,6 +112,16 @@ abstract class Action extends UtopiaAction : Exception::COLUMN_NOT_FOUND; } + /** + * Get the appropriate not found exception. + */ + final protected function getIndexDependencyException(): string + { + return $this->isCollectionsAPI() + ? Exception::INDEX_DEPENDENCY + : Exception::COLUMN_INDEX_DEPENDENCY; + } + /** * Get the appropriate already exists exception. */ @@ -275,7 +285,7 @@ abstract class Action extends UtopiaAction if (!empty($format)) { if (!Structure::hasFormat($format, $type)) { - throw new Exception($this->getFormatUnsupportedException(), "Format {$format} not available for {$type} columns."); + throw new Exception($this->getFormatUnsupportedException(), "Format $format not available for $type columns."); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 9597070be6..444fa41a7f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -91,7 +91,7 @@ class Delete extends Action $dbForProject->getAdapter()->getSupportForCastIndexArray(), ); if (!$validator->isValid($attribute)) { - throw new Exception(Exception::INDEX_DEPENDENCY); + throw new Exception($this->getIndexDependencyException()); } if ($attribute->getAttribute('status') === 'available') { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php new file mode 100644 index 0000000000..102acdb639 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php @@ -0,0 +1,163 @@ +context = $context; + } + + /** + * Get the current API's parent context. + */ + final protected function getParentContext(): string + { + return $this->getContext() === DATABASE_INDEX_CONTEXT + ? DATABASE_ATTRIBUTES_CONTEXT + : DATABASE_COLUMNS_CONTEXT; + } + + /** + * Get the current API context. + */ + final protected function getContext(): string + { + return $this->context; + } + + /** + * Get the correct grand parent param key (e.g. `tableId` or `collectionId`) + */ + final protected function getGrandParentEventsParamKey(): string + { + return $this->isCollectionsAPI() ? 'collectionId' : 'tableId'; + } + + /** + * Get the key used in event parameters. + */ + final protected function getEventsParamKey(): string + { + return 'indexId'; + } + + /** + * Determine if the current action is for the Collections API. + */ + final protected function isCollectionsAPI(): bool + { + return $this->getParentContext() === DATABASE_ATTRIBUTES_CONTEXT; + } + + /** + * Get the SDK group name for the current action. + */ + final protected function getSdkGroup(): string + { + return 'indexes'; + } + + /** + * Get the exception to throw when the parent is unknown. + */ + final protected function getParentUnknownException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_UNKNOWN + : Exception::COLUMN_UNKNOWN; + } + + /** + * Get the appropriate grandparent level not found exception. + */ + final protected function getGrantParentNotFoundException(): string + { + return $this->isCollectionsAPI() + ? Exception::COLLECTION_NOT_FOUND + : Exception::TABLE_NOT_FOUND; + } + + /** + * Get the appropriate not found exception. + */ + final protected function getNotFoundException(): string + { + return $this->isCollectionsAPI() + ? Exception::INDEX_NOT_FOUND + : Exception::COLUMN_INDEX_NOT_FOUND; + } + + /** + * Get the exception to throw when the parent type is invalid. + */ + final protected function getParentInvalidTypeException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_TYPE_INVALID + : Exception::COLUMN_TYPE_INVALID; + } + + /** + * Get the exception to throw when the index type is invalid. + */ + final protected function getInvalidTypeException(): string + { + return $this->isCollectionsAPI() + ? Exception::INDEX_INVALID + : Exception::COLUMN_INDEX_INVALID; + } + + /** + * Get the exception to throw when the resource already exists. + */ + final protected function getDuplicateException(): string + { + return $this->isCollectionsAPI() + ? Exception::INDEX_ALREADY_EXISTS + : Exception::COLUMN_INDEX_ALREADY_EXISTS; + } + + /** + * Get the exception to throw when the resource limit is exceeded. + */ + final protected function getLimitException(): string + { + return $this->isCollectionsAPI() + ? Exception::INDEX_LIMIT_EXCEEDED + : Exception::COLUMN_INDEX_LIMIT_EXCEEDED; + } + + /** + * Get the exception to throw when the parent attribute/column is not in `available` state. + */ + final protected function getParentNotAvailableException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_NOT_AVAILABLE + : Exception::COLUMN_NOT_AVAILABLE; + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index e9dd4c7092..aa4729e605 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -1,6 +1,6 @@ setHttpMethod(self::HTTP_REQUEST_METHOD_POST) - ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes') + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/indexes') ->desc('Create index') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].create') + ->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'index.create') - // TODO: audits table or collections, check the context type if possible, move into another module. - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( namespace: 'databases', - group: 'tables', - name: 'createIndex', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/create-index.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_ACCEPTED, - model: UtopiaResponse::MODEL_INDEX, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', null, new Key(), 'Index Key.') ->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE]), 'Index type.') - ->param('columns', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of columns to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' columns are allowed, each 32 characters long.') + ->param('attributes', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' attributes are allowed, each 32 characters long.') ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true) ->inject('response') ->inject('dbForProject') @@ -74,7 +77,7 @@ class Create extends Action ->callback([$this, 'action']); } - public function action(string $databaseId, string $tableId, string $key, string $type, array $columns, array $orders, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -82,27 +85,28 @@ class Create extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); + $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); + if ($collection->isEmpty()) { + // table or collection. + throw new Exception($this->getGrantParentNotFoundException()); } $count = $dbForProject->count('indexes', [ - Query::equal('collectionInternalId', [$table->getInternalId()]), + Query::equal('collectionInternalId', [$collection->getInternalId()]), Query::equal('databaseInternalId', [$db->getInternalId()]) ], 61); $limit = $dbForProject->getLimitForIndexes(); if ($count >= $limit) { - throw new Exception(Exception::INDEX_LIMIT_EXCEEDED, 'Index limit exceeded'); + throw new Exception($this->getLimitException(), 'Index limit exceeded'); } // Convert Document[] to array of attribute metadata - $oldColumns = \array_map(fn ($a) => $a->getArrayCopy(), $table->getAttribute('attributes')); + $oldAttributes = \array_map(fn ($a) => $a->getArrayCopy(), $collection->getAttribute('attributes')); - $oldColumns[] = [ + $oldAttributes[] = [ 'key' => '$id', 'type' => Database::VAR_STRING, 'status' => 'available', @@ -112,7 +116,7 @@ class Create extends Action 'size' => Database::LENGTH_KEY ]; - $oldColumns[] = [ + $oldAttributes[] = [ 'key' => '$createdAt', 'type' => Database::VAR_DATETIME, 'status' => 'available', @@ -123,7 +127,7 @@ class Create extends Action 'size' => 0 ]; - $oldColumns[] = [ + $oldAttributes[] = [ 'key' => '$updatedAt', 'type' => Database::VAR_DATETIME, 'status' => 'available', @@ -137,25 +141,27 @@ class Create extends Action // lengths hidden by default $lengths = []; - foreach ($columns as $i => $column) { + $contextType = $this->getParentContext(); + foreach ($attributes as $i => $attribute) { // find attribute metadata in collection document - $columnIndex = \array_search($column, array_column($oldColumns, 'key')); + $attributeIndex = \array_search($attribute, array_column($oldAttributes, 'key')); - if ($columnIndex === false) { - throw new Exception(Exception::COLUMN_UNKNOWN, 'Unknown column: ' . $column . '. Verify the column name or create the column.'); + if ($attributeIndex === false) { + throw new Exception($this->getParentUnknownException(), "Unknown $contextType: " . $attribute . ". Verify the $contextType name or create the $contextType."); } - $columnStatus = $oldColumns[$columnIndex]['status']; - $columnType = $oldColumns[$columnIndex]['type']; - $columnArray = $oldColumns[$columnIndex]['array'] ?? false; + $columnStatus = $oldAttributes[$attributeIndex]['status']; + $columnType = $oldAttributes[$attributeIndex]['type']; + $columnArray = $oldAttributes[$attributeIndex]['array'] ?? false; if ($columnType === Database::VAR_RELATIONSHIP) { - throw new Exception(Exception::COLUMN_TYPE_INVALID, 'Cannot create an index for a relationship column: ' . $oldColumns[$columnIndex]['key']); + throw new Exception($this->getParentInvalidTypeException(), "Cannot create an index for a relationship $contextType: " . $oldAttributes[$attributeIndex]['key']); } // ensure attribute is available if ($columnStatus !== 'available') { - throw new Exception(Exception::COLUMN_NOT_AVAILABLE, 'Column not available: ' . $oldColumns[$columnIndex]['key']); + $contextType = ucfirst($contextType); + throw new Exception($this->getParentNotAvailableException(), "$contextType not available: " . $oldAttributes[$attributeIndex]['key']); } $lengths[$i] = null; @@ -167,51 +173,59 @@ class Create extends Action } $index = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $table->getInternalId() . '_' . $key), + '$id' => ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), 'key' => $key, 'status' => 'processing', // processing, available, failed, deleting, stuck 'databaseInternalId' => $db->getInternalId(), 'databaseId' => $databaseId, - 'collectionInternalId' => $table->getInternalId(), - 'collectionId' => $tableId, + 'collectionInternalId' => $collection->getInternalId(), + 'collectionId' => $collectionId, 'type' => $type, - 'attributes' => $columns, + 'attributes' => $attributes, 'lengths' => $lengths, 'orders' => $orders, ]); $validator = new IndexValidator( - $table->getAttribute('attributes'), + $collection->getAttribute('attributes'), $dbForProject->getAdapter()->getMaxIndexLength(), $dbForProject->getAdapter()->getInternalIndexesKeys(), ); if (!$validator->isValid($index)) { - throw new Exception(Exception::INDEX_INVALID, $validator->getDescription()); + throw new Exception($this->getInvalidTypeException(), $validator->getDescription()); } try { $index = $dbForProject->createDocument('indexes', $index); } catch (DuplicateException) { - throw new Exception(Exception::INDEX_ALREADY_EXISTS); + throw new Exception($this->getDuplicateException()); } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); $queueForDatabase ->setType(DATABASE_TYPE_CREATE_INDEX) - ->setDatabase($db) - ->setTable($table) - ->setRow($index); + ->setDatabase($db); + + if ($this->isCollectionsAPI()) { + $queueForDatabase + ->setCollection($collection) + ->setDocument($index); + } else { + $queueForDatabase + ->setTable($collection) + ->setRow($index); + } $queueForEvents + ->setContext('database', $db) ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('indexId', $index->getId()) - ->setContext('table', $table) - ->setContext('database', $db); + ->setParam($this->getEventsParamKey(), $index->getId()) + ->setParam($this->getGrandParentEventsParamKey(), $collection->getId()) + ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($index, UtopiaResponse::MODEL_INDEX); + ->dynamic($index, $this->getResponseModel()); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index dd7c4bd5e7..157e4ef7de 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -1,6 +1,6 @@ setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) - ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes/:key') + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->desc('Delete index') ->groups(['api', 'database']) ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].update') + ->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].update') ->label('audits.event', 'index.delete') - // TODO: audits table or collections, check the context type if possible - ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( namespace: 'databases', - group: 'indexes', - name: 'deleteIndex', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/delete-index.md', auth: [AuthType::KEY], responses: [ @@ -55,7 +62,7 @@ class Delete extends Action contentType: ContentType::NONE )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') @@ -64,23 +71,24 @@ class Delete extends Action ->callback([$this, 'action']); } - public function action(string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $table = $dbForProject->getDocument('database_' . $db->getInternalId(), $tableId); + $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); + if ($collection->isEmpty()) { + // table or collection. + throw new Exception($this->getGrantParentNotFoundException()); } - $index = $dbForProject->getDocument('indexes', $db->getInternalId() . '_' . $table->getInternalId() . '_' . $key); + $index = $dbForProject->getDocument('indexes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); if (empty($index->getId())) { - throw new Exception(Exception::INDEX_NOT_FOUND); + throw new Exception($this->getNotFoundException()); } // Only update status if removing available index @@ -88,21 +96,29 @@ class Delete extends Action $index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $tableId); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_INDEX) - ->setDatabase($db) - ->setTable($table) - ->setRow($index); + ->setDatabase($db); + + if ($this->isCollectionsAPI()) { + $queueForDatabase + ->setCollection($collection) + ->setDocument($index); + } else { + $queueForDatabase + ->setTable($collection) + ->setRow($index); + } $queueForEvents - ->setParam('databaseId', $databaseId) - ->setParam('tableId', $table->getId()) - ->setParam('indexId', $index->getId()) - ->setContext('table', $table) ->setContext('database', $db) - ->setPayload($response->output($index, UtopiaResponse::MODEL_INDEX)); + ->setParam('databaseId', $databaseId) + ->setParam($this->getEventsParamKey(), $index->getId()) + ->setPayload($response->output($index, $this->getResponseModel())) + ->setParam($this->getGrandParentEventsParamKey(), $collection->getId()) + ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); $response->noContent(); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php index a89819d844..3e8a67b395 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php @@ -1,6 +1,6 @@ setHttpMethod(self::HTTP_REQUEST_METHOD_GET) - ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes/:key') + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->desc('Get index') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'indexes', - name: 'getIndex', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/get-index.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_INDEX, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') ->callback([$this, 'action']); } - public function action(string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); + if ($collection->isEmpty()) { + // table or collection. + throw new Exception($this->getGrantParentNotFoundException()); } - $index = $table->find('key', $key, 'indexes'); + $index = $collection->find('key', $key, 'indexes'); if (empty($index)) { - throw new Exception(Exception::INDEX_NOT_FOUND); + throw new Exception($this->getNotFoundException()); } - $response->dynamic($index, UtopiaResponse::MODEL_INDEX); + $response->dynamic($index, $this->getResponseModel()); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index b11806cfd0..45627654dc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -1,6 +1,6 @@ setHttpMethod(self::HTTP_REQUEST_METHOD_GET) - ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes') + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/indexes') ->desc('List indexes') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: 'indexes', - name: 'listIndexes', + group: $this->getSdkGroup(), + name: self::getName(), description: '/docs/references/databases/list-indexes.md', auth: [AuthType::KEY], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_OK, - model: UtopiaResponse::MODEL_INDEX_LIST, + model: $this->getResponseModel(), ) ], contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') ->callback([$this, 'action']); } - public function action(string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject): void { /** @var Document $database */ $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -69,10 +73,11 @@ class XList extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $table = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - if ($table->isEmpty()) { - throw new Exception(Exception::TABLE_NOT_FOUND); + if ($collection->isEmpty()) { + // table or collection. + throw new Exception($this->getGrantParentNotFoundException()); } $queries = Query::parseQueries($queries); @@ -80,7 +85,7 @@ class XList extends Action \array_push( $queries, Query::equal('databaseId', [$databaseId]), - Query::equal('collectionId', [$tableId]), + Query::equal('collectionId', [$collectionId]), ); /** @@ -99,7 +104,7 @@ class XList extends Action $indexId = $cursor->getValue(); $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ - Query::equal('collectionInternalId', [$table->getInternalId()]), + Query::equal('collectionInternalId', [$collection->getInternalId()]), Query::equal('databaseInternalId', [$database->getInternalId()]), Query::equal('key', [$indexId]), Query::limit(1) @@ -117,12 +122,15 @@ class XList extends Action $total = $dbForProject->count('indexes', $filterQueries, APP_LIMIT_COUNT); $indexes = $dbForProject->find('indexes', $queries); } catch (OrderException $e) { - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); + $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; + $attribute = $this->isCollectionsAPI() ? 'attribute' : 'column'; + $message = "The order $attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all $documents order $attribute values are non-null."; + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, $message); } $response->dynamic(new Document([ 'total' => $total, 'indexes' => $indexes, - ]), UtopiaResponse::MODEL_INDEX_LIST); + ]), $this->getResponseModel()); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php new file mode 100644 index 0000000000..844a317de7 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php @@ -0,0 +1,72 @@ +setContext(DATABASE_COLUMN_INDEX_CONTEXT); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/:databaseId/tables/:tables/indexes') + ->desc('Create index') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].tables.[tables].indexes.[indexId].create') + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'index.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/create-index.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_ACCEPTED, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', null, new Key(), 'Index Key.') + ->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE]), 'Index type.') + ->param('columns', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of columns to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' columns are allowed, each 32 characters long.') + ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback(function (string $databaseId, string $tableId, string $key, string $type, array $columns, array $orders, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $type, $columns, $orders, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php new file mode 100644 index 0000000000..d4185cfcbe --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php @@ -0,0 +1,71 @@ +setContext(DATABASE_COLUMN_INDEX_CONTEXT); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes/:key') + ->desc('Delete index') + ->groups(['api', 'database']) + ->label('scope', 'collections.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].update') + ->label('audits.event', 'index.delete') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/delete-index.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_NOCONTENT, + model: UtopiaResponse::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', '', new Key(), 'Index Key.') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDatabase') + ->inject('queueForEvents') + ->callback(function (string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + parent::action($databaseId, $tableId, $key, $response, $dbForProject, $queueForDatabase, $queueForEvents); + }); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php new file mode 100644 index 0000000000..ee0432522c --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php @@ -0,0 +1,60 @@ +setContext(DATABASE_COLUMN_INDEX_CONTEXT); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes/:key') + ->desc('Get index') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/get-index.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('key', null, new Key(), 'Index Key.') + ->inject('response') + ->inject('dbForProject') + ->callback(function (string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject) { + parent::action($databaseId, $tableId, $key, $response, $dbForProject); + }); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php new file mode 100644 index 0000000000..50c1eb11d1 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php @@ -0,0 +1,60 @@ +setContext(DATABASE_COLUMN_INDEX_CONTEXT); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes') + ->desc('List indexes') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/list-indexes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) + ->inject('response') + ->inject('dbForProject') + ->callback(function (string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject) { + parent::action($databaseId, $tableId, $queries, $response, $dbForProject); + }); + } +} From 6fba4a5f08e3b2a7ac9258424c6bf040ee275b20 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 14:20:11 +0530 Subject: [PATCH 085/343] update: sdk namespaces. --- .../Http/Databases/Collections/Attributes/Action.php | 8 ++++++++ .../Databases/Collections/Attributes/Boolean/Create.php | 2 +- .../Databases/Collections/Attributes/Boolean/Update.php | 2 +- .../Databases/Collections/Attributes/Datetime/Create.php | 2 +- .../Databases/Collections/Attributes/Datetime/Update.php | 2 +- .../Http/Databases/Collections/Attributes/Delete.php | 2 +- .../Databases/Collections/Attributes/Email/Create.php | 2 +- .../Databases/Collections/Attributes/Email/Update.php | 2 +- .../Http/Databases/Collections/Attributes/Enum/Create.php | 2 +- .../Http/Databases/Collections/Attributes/Enum/Update.php | 2 +- .../Databases/Collections/Attributes/Float/Create.php | 2 +- .../Databases/Collections/Attributes/Float/Update.php | 2 +- .../Http/Databases/Collections/Attributes/Get.php | 2 +- .../Http/Databases/Collections/Attributes/IP/Create.php | 2 +- .../Http/Databases/Collections/Attributes/IP/Update.php | 2 +- .../Databases/Collections/Attributes/Integer/Create.php | 2 +- .../Databases/Collections/Attributes/Integer/Update.php | 2 +- .../Collections/Attributes/Relationship/Create.php | 2 +- .../Collections/Attributes/Relationship/Update.php | 2 +- .../Databases/Collections/Attributes/String/Create.php | 2 +- .../Databases/Collections/Attributes/String/Update.php | 2 +- .../Http/Databases/Collections/Attributes/URL/Create.php | 2 +- .../Http/Databases/Collections/Attributes/URL/Update.php | 2 +- .../Http/Databases/Collections/Attributes/XList.php | 2 +- .../Http/Databases/Collections/Documents/Action.php | 8 ++++++++ .../Http/Databases/Collections/Documents/Create.php | 2 +- .../Http/Databases/Collections/Documents/Delete.php | 2 +- .../Http/Databases/Collections/Documents/Get.php | 2 +- .../Http/Databases/Collections/Documents/Logs/XList.php | 2 +- .../Http/Databases/Collections/Documents/Update.php | 2 +- .../Http/Databases/Collections/Documents/XList.php | 2 +- .../Http/Databases/Collections/Indexes/Action.php | 8 ++++++++ .../Http/Databases/Collections/Indexes/Create.php | 2 +- .../Http/Databases/Collections/Indexes/Delete.php | 2 +- .../Databases/Http/Databases/Collections/Indexes/Get.php | 2 +- .../Http/Databases/Collections/Indexes/XList.php | 2 +- .../Http/Databases/Tables/Columns/Boolean/Create.php | 2 +- .../Http/Databases/Tables/Columns/Boolean/Update.php | 2 +- .../Http/Databases/Tables/Columns/Datetime/Create.php | 2 +- .../Http/Databases/Tables/Columns/Datetime/Update.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Delete.php | 2 +- .../Http/Databases/Tables/Columns/Email/Create.php | 2 +- .../Http/Databases/Tables/Columns/Email/Update.php | 2 +- .../Http/Databases/Tables/Columns/Enum/Create.php | 2 +- .../Http/Databases/Tables/Columns/Enum/Update.php | 2 +- .../Http/Databases/Tables/Columns/Float/Create.php | 2 +- .../Http/Databases/Tables/Columns/Float/Update.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Get.php | 2 +- .../Databases/Http/Databases/Tables/Columns/IP/Create.php | 2 +- .../Databases/Http/Databases/Tables/Columns/IP/Update.php | 2 +- .../Http/Databases/Tables/Columns/Integer/Create.php | 2 +- .../Http/Databases/Tables/Columns/Integer/Update.php | 2 +- .../Http/Databases/Tables/Columns/Relationship/Create.php | 2 +- .../Http/Databases/Tables/Columns/Relationship/Update.php | 2 +- .../Http/Databases/Tables/Columns/String/Create.php | 2 +- .../Http/Databases/Tables/Columns/String/Update.php | 2 +- .../Http/Databases/Tables/Columns/URL/Create.php | 2 +- .../Http/Databases/Tables/Columns/URL/Update.php | 2 +- .../Databases/Http/Databases/Tables/Columns/XList.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Create.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Delete.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Get.php | 2 +- .../Databases/Http/Databases/Tables/Indexes/Create.php | 2 +- .../Databases/Http/Databases/Tables/Indexes/Delete.php | 2 +- .../Databases/Http/Databases/Tables/Indexes/Get.php | 2 +- .../Databases/Http/Databases/Tables/Indexes/XList.php | 2 +- .../Databases/Http/Databases/Tables/Logs/XList.php | 2 +- .../Databases/Http/Databases/Tables/Rows/Create.php | 2 +- .../Databases/Http/Databases/Tables/Rows/Delete.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Rows/Get.php | 2 +- .../Databases/Http/Databases/Tables/Rows/Logs/XList.php | 2 +- .../Databases/Http/Databases/Tables/Rows/Update.php | 2 +- .../Databases/Http/Databases/Tables/Rows/XList.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Update.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Usage/Get.php | 2 +- .../Modules/Databases/Http/Databases/Tables/XList.php | 2 +- 76 files changed, 97 insertions(+), 73 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index fff070d58f..b683ebd64c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -76,6 +76,14 @@ abstract class Action extends UtopiaAction return $this->isCollectionsAPI() ? 'attributes' : 'columns'; } + /** + * Get the SDK namespace for the current action. + */ + final protected function getSdkNamespace(): string + { + return $this->isCollectionsAPI() ? 'collections' : 'tables'; + } + /** * Get the correct parent param key (e.g. `tableId` or `collectionId`) */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php index d70188e621..56c0753f08 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php @@ -44,7 +44,7 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-boolean-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php index 73739e1d91..c8aa734570 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php @@ -44,7 +44,7 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-boolean-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php index 50e20a5c56..e3e0cc359b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php @@ -45,7 +45,7 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-datetime-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php index afac2904ff..eac9ba278c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php @@ -45,7 +45,7 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-datetime-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 444fa41a7f..2432ac5fd0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -46,7 +46,7 @@ class Delete extends Action ->label('audits.event', 'attribute.delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/delete-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php index 2d64c00393..80309609b8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php @@ -45,7 +45,7 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-email-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php index fcf5ab7fca..5c35084508 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php @@ -45,7 +45,7 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-email-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php index ea7370e493..8e4ad25f75 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php @@ -47,7 +47,7 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-attribute-enum.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php index b8e855de99..be04a1ef9a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php @@ -46,7 +46,7 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-enum-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php index 821f3134ab..4e3a8adf75 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php @@ -47,7 +47,7 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-float-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php index 3ef7f5cae4..13a90310e1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php @@ -45,7 +45,7 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-float-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index 226dcefa2b..e04a89295b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -49,7 +49,7 @@ class Get extends Action ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/get-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php index cb472fc2c8..4bf5edc09d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php @@ -45,7 +45,7 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-ip-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php index 233672be03..380fa01123 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php @@ -45,7 +45,7 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-ip-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php index 4bd45adf48..dc28e41264 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php @@ -47,7 +47,7 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-integer-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php index e8197ba0d9..9e864e8b62 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php @@ -45,7 +45,7 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-integer-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php index 5d799c11c9..193e3eaa09 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php @@ -47,7 +47,7 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-relationship-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php index 5375135c28..b489f92c3d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php @@ -43,7 +43,7 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-relationship-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php index 6c8ec7e9e1..6463d2cedf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php @@ -48,7 +48,7 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-string-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php index 059ad1e28c..e746edb766 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php @@ -47,7 +47,7 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-string-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php index f7c948d43e..a802bbf8af 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php @@ -45,7 +45,7 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-url-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php index 8fa53d79b4..9ca1f372dc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php @@ -45,7 +45,7 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-url-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index c89ad043f3..29e8d1d6b9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -43,7 +43,7 @@ class XList extends Action ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/list-attributes.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index 2eabd376cf..b9a3247f96 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -59,6 +59,14 @@ abstract class Action extends UtopiaAction return $this->isCollectionsAPI() ? 'documents' : 'rows'; } + /** + * Get the SDK namespace for the current action. + */ + final protected function getSdkNamespace(): string + { + return $this->isCollectionsAPI() ? 'collections' : 'tables'; + } + /** * Get the correct parent param key (e.g. `tableId` or `collectionId`) */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index 6522ff377c..6db7e802f3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -58,7 +58,7 @@ class Create extends Action ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', [ new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-document.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index dcca07eed4..2f0c4e76db 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -53,7 +53,7 @@ class Delete extends Action ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/delete-document.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index 29cfb19013..f56ab40126 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -46,7 +46,7 @@ class Get extends Action ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/get-document.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php index 6c37d3e238..bb24d41b30 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php @@ -50,7 +50,7 @@ class XList extends Action ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: 'logs', name: self::getName(), description: '/docs/references/databases/get-document-logs.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index 5f6935abcb..4ad045a998 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -57,7 +57,7 @@ class Update extends Action ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-document.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 3ddbf8df7f..7b4f5855e2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -47,7 +47,7 @@ class XList extends Action ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/list-documents.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php index 102acdb639..6186139bfb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php @@ -81,6 +81,14 @@ abstract class Action extends UtopiaAction return 'indexes'; } + /** + * Get the SDK namespace for the current action. + */ + final protected function getSdkNamespace(): string + { + return $this->isCollectionsAPI() ? 'collections' : 'tables'; + } + /** * Get the exception to throw when the parent is unknown. */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index aa4729e605..fe21025740 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -51,7 +51,7 @@ class Create extends Action ->label('audits.event', 'index.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-index.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index 157e4ef7de..2d57a8a5f0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -48,7 +48,7 @@ class Delete extends Action ->label('audits.event', 'index.delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/delete-index.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php index 3e8a67b395..fa10406f2a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php @@ -39,7 +39,7 @@ class Get extends Action ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/get-index.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index 45627654dc..733e6854b2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -43,7 +43,7 @@ class XList extends Action ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/list-indexes.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php index 740bd89c0b..6f48afe57f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php @@ -45,7 +45,7 @@ class Create extends BooleanCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-boolean-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php index a2254a5734..485a9587e3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php @@ -46,7 +46,7 @@ class Update extends BooleanUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-boolean-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php index ef0c61e1f4..1a5f6f65e1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php @@ -46,7 +46,7 @@ class Create extends DatetimeCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-datetime-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php index 14e57d6a70..1eb13852e7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php @@ -47,7 +47,7 @@ class Update extends DatetimeUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-datetime-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php index 064e277942..10604029dd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php @@ -46,7 +46,7 @@ class Delete extends AttributesDelete ->label('audits.event', 'column.delete') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/delete-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php index 635b673e03..2d7b65931f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php @@ -46,7 +46,7 @@ class Create extends EmailCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-email-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php index 0162633ed9..a067334a9d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php @@ -47,7 +47,7 @@ class Update extends EmailUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-email-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php index 942d49d86a..8fdb689b46 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php @@ -47,7 +47,7 @@ class Create extends EnumCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-attribute-enum.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php index 2018170105..85e1c4e5cc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php @@ -48,7 +48,7 @@ class Update extends EnumUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-enum-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php index 13d26d0331..2ad2c11572 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php @@ -46,7 +46,7 @@ class Create extends FloatCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-float-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php index 55c4c13505..ef6080b86c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php @@ -47,7 +47,7 @@ class Update extends FloatUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-float-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php index db83c3ecbc..42ba23ad3a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php @@ -50,7 +50,7 @@ class Get extends AttributesGet ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/get-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php index c0d671183c..34d5ecdfca 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php @@ -46,7 +46,7 @@ class Create extends IPCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-ip-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php index e9092c38c5..34cfe97343 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php @@ -47,7 +47,7 @@ class Update extends IPUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-ip-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php index 26868fa667..13aa90b6e3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php @@ -46,7 +46,7 @@ class Create extends IntegerCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-integer-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php index fa50515a10..6cf3383795 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php @@ -47,7 +47,7 @@ class Update extends IntegerUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-integer-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php index 4693d494c6..2e338ae037 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php @@ -46,7 +46,7 @@ class Create extends RelationshipCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-relationship-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php index e110eafc56..1afdd0c56a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php @@ -45,7 +45,7 @@ class Update extends RelationshipUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-relationship-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php index 354aef6ff9..e17ac07ccf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php @@ -48,7 +48,7 @@ class Create extends StringCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-string-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php index 649d481794..f64d5408eb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php @@ -49,7 +49,7 @@ class Update extends StringUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-string-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php index ce7c5dfe9f..a0f4e2ae8f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php @@ -46,7 +46,7 @@ class Create extends URLCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-url-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php index 298165b2cf..623328e249 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php @@ -47,7 +47,7 @@ class Update extends URLUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-url-attribute.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php index 2e41fe86eb..a6b43518b9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php @@ -39,7 +39,7 @@ class XList extends AttributesXList ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/list-attributes.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php index 1f349b95ed..6984ff0b5d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php @@ -47,7 +47,7 @@ class Create extends CollectionCreate ->label('audits.event', 'table.create') ->label('audits.resource', 'database/{request.databaseId}/table/{response.$id}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-collection.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php index 338d344660..5bce6fa519 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php @@ -44,7 +44,7 @@ class Delete extends CollectionDelete ->label('audits.event', 'table.delete') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/delete-collection.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php index ffa1da443e..b4ca31dbe0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php @@ -39,7 +39,7 @@ class Get extends CollectionGet ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/get-collection.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php index 844a317de7..97ac92d559 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php @@ -42,7 +42,7 @@ class Create extends IndexCreate ->label('audits.event', 'index.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-index.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php index d4185cfcbe..6a86a4767e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php @@ -44,7 +44,7 @@ class Delete extends IndexDelete ->label('audits.event', 'index.delete') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/delete-index.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php index ee0432522c..0cc537d960 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php @@ -35,7 +35,7 @@ class Get extends IndexGet ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/get-index.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php index 50c1eb11d1..5a245cf533 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php @@ -35,7 +35,7 @@ class XList extends IndexXList ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/list-indexes.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php index 9a6d4c4e8e..8783067f69 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php @@ -39,7 +39,7 @@ class XList extends CollectionLogXList ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/get-collection-logs.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php index 26e14b9ca5..1773a4c2ff 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php @@ -52,7 +52,7 @@ class Create extends DocumentCreate ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', [ new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-document.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php index c0cc4b0dd1..05a98d6096 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php @@ -53,7 +53,7 @@ class Delete extends DocumentDelete ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/delete-document.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php index 0b74f19f41..717cec3721 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php @@ -42,7 +42,7 @@ class Get extends DocumentGet ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/get-document.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php index 66ac69323c..23b70ac19e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php @@ -39,7 +39,7 @@ class XList extends DocumentLogXList ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: 'logs', name: self::getName(), description: '/docs/references/databases/get-document-logs.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php index 7148452c74..0a83feee38 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php @@ -49,7 +49,7 @@ class Update extends DocumentUpdate ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-document.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php index 62fe6b52b0..f4bdbaa483 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php @@ -42,7 +42,7 @@ class XList extends DocumentXList ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/list-documents.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php index e60fbb4ac8..88b72322c1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php @@ -46,7 +46,7 @@ class Update extends CollectionUpdate ->label('audits.event', 'table.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-collection.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php index 304884cece..3b2a40584e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php @@ -40,7 +40,7 @@ class Get extends CollectionUsageGet ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: null, name: self::getName(), description: '/docs/references/databases/get-collection-usage.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php index 10913cd491..733703d05f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php @@ -41,7 +41,7 @@ class XList extends CollectionXList ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/list-collections.md', From 97d1a535df35a3b584b5dc1e28280e5f585131a8 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 15:30:52 +0530 Subject: [PATCH 086/343] fix: missing path :\ --- .../Databases/Http/Databases/Collections/Documents/Update.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index 4ad045a998..be009b9cd2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -41,11 +41,11 @@ class Update extends Action return UtopiaResponse::MODEL_DOCUMENT; } - public function __construct() { $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') ->desc('Update document') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].update') From d7023b5a6977d7a116ef8dad3439d77504e9dbc1 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 15:33:00 +0530 Subject: [PATCH 087/343] fix: namespaces. --- .../Platform/Modules/Databases/Http/Databases/Tables/Create.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Tables/Delete.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Tables/Get.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Tables/Update.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Tables/XList.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php index 6984ff0b5d..1f349b95ed 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php @@ -47,7 +47,7 @@ class Create extends CollectionCreate ->label('audits.event', 'table.create') ->label('audits.resource', 'database/{request.databaseId}/table/{response.$id}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: 'databases', group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/create-collection.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php index 5bce6fa519..338d344660 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php @@ -44,7 +44,7 @@ class Delete extends CollectionDelete ->label('audits.event', 'table.delete') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: 'databases', group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/delete-collection.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php index b4ca31dbe0..ffa1da443e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php @@ -39,7 +39,7 @@ class Get extends CollectionGet ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: 'databases', group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/get-collection.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php index 88b72322c1..e60fbb4ac8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php @@ -46,7 +46,7 @@ class Update extends CollectionUpdate ->label('audits.event', 'table.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: 'databases', group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/update-collection.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php index 733703d05f..10913cd491 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php @@ -41,7 +41,7 @@ class XList extends CollectionXList ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: 'databases', group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/list-collections.md', From eafa9bb3934671a36594e3e7bd4f9e3bbd3c6d17 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 15:33:41 +0530 Subject: [PATCH 088/343] fix: namespaces, again. --- .../Modules/Databases/Http/Databases/Tables/Logs/XList.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php index 8783067f69..9a6d4c4e8e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php @@ -39,7 +39,7 @@ class XList extends CollectionLogXList ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: 'databases', group: $this->getSdkGroup(), name: self::getName(), description: '/docs/references/databases/get-collection-logs.md', From c4a26fbb952ac16076989294c69134923b724781 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 15:37:00 +0530 Subject: [PATCH 089/343] =?UTF-8?q?fix:=20another=20pesky=20sdk=20namespac?= =?UTF-8?q?e=20=F0=9F=A4=A8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Modules/Databases/Http/Databases/Tables/Usage/Get.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php index 3b2a40584e..304884cece 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php @@ -40,7 +40,7 @@ class Get extends CollectionUsageGet ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: 'databases', group: null, name: self::getName(), description: '/docs/references/databases/get-collection-usage.md', From 4e83fc856ab2e5debe82edfab3189cd621d6aae0 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 15:38:07 +0530 Subject: [PATCH 090/343] update: split service registrations into smaller registries. --- .../Modules/Databases/Services/Http.php | 169 ++---------------- .../Databases/Services/Registry/Base.php | 24 +++ .../Services/Registry/Collections.php | 140 +++++++++++++++ .../Databases/Services/Registry/Databases.php | 31 ++++ .../Databases/Services/Registry/Tables.php | 142 +++++++++++++++ 5 files changed, 347 insertions(+), 159 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Services/Registry/Base.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Services/Registry/Databases.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Http.php b/src/Appwrite/Platform/Modules/Databases/Services/Http.php index 26a4aa0942..6c1361b0b1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Http.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Http.php @@ -2,61 +2,9 @@ namespace Appwrite\Platform\Modules\Databases\Services; -use Appwrite\Platform\Modules\Databases\Http\Collections\Create as CreateCollection; -use Appwrite\Platform\Modules\Databases\Http\Collections\Delete as DeleteCollection; -use Appwrite\Platform\Modules\Databases\Http\Collections\Get as GetCollection; -use Appwrite\Platform\Modules\Databases\Http\Collections\Logs\XList as ListCollectionLogs; -use Appwrite\Platform\Modules\Databases\Http\Collections\Update as UpdateCollection; -use Appwrite\Platform\Modules\Databases\Http\Collections\Usage\Get as GetCollectionUsage; -use Appwrite\Platform\Modules\Databases\Http\Collections\XList as ListCollections; -use Appwrite\Platform\Modules\Databases\Http\Columns\Boolean\Create as CreateBoolean; -use Appwrite\Platform\Modules\Databases\Http\Columns\Boolean\Update as UpdateBoolean; -use Appwrite\Platform\Modules\Databases\Http\Columns\Datetime\Create as CreateDatetime; -use Appwrite\Platform\Modules\Databases\Http\Columns\Datetime\Update as UpdateDatetime; -use Appwrite\Platform\Modules\Databases\Http\Columns\Delete as DeleteColumn; -use Appwrite\Platform\Modules\Databases\Http\Columns\Email\Create as CreateEmail; -use Appwrite\Platform\Modules\Databases\Http\Columns\Email\Update as UpdateEmail; -use Appwrite\Platform\Modules\Databases\Http\Columns\Enum\Create as CreateEnum; -use Appwrite\Platform\Modules\Databases\Http\Columns\Enum\Update as UpdateEnum; -use Appwrite\Platform\Modules\Databases\Http\Columns\Float\Create as CreateFloat; -use Appwrite\Platform\Modules\Databases\Http\Columns\Float\Update as UpdateFloat; -use Appwrite\Platform\Modules\Databases\Http\Columns\Get as GetColumn; -use Appwrite\Platform\Modules\Databases\Http\Columns\Integer\Create as CreateInteger; -use Appwrite\Platform\Modules\Databases\Http\Columns\Integer\Update as UpdateInteger; -use Appwrite\Platform\Modules\Databases\Http\Columns\IP\Create as CreateIP; -use Appwrite\Platform\Modules\Databases\Http\Columns\IP\Update as UpdateIP; -use Appwrite\Platform\Modules\Databases\Http\Columns\Relationship\Create as CreateRelationship; -use Appwrite\Platform\Modules\Databases\Http\Columns\Relationship\Update as UpdateRelationship; -use Appwrite\Platform\Modules\Databases\Http\Columns\String\Create as CreateString; -use Appwrite\Platform\Modules\Databases\Http\Columns\String\Update as UpdateString; -use Appwrite\Platform\Modules\Databases\Http\Columns\URL\Create as CreateURL; -use Appwrite\Platform\Modules\Databases\Http\Columns\URL\Update as UpdateURL; -use Appwrite\Platform\Modules\Databases\Http\Columns\XList as ListColumns; -use Appwrite\Platform\Modules\Databases\Http\Databases\Create as CreateDatabase; -use Appwrite\Platform\Modules\Databases\Http\Databases\Delete as DeleteDatabase; -use Appwrite\Platform\Modules\Databases\Http\Databases\Get as GetDatabase; -use Appwrite\Platform\Modules\Databases\Http\Databases\Logs\XList as ListDatabaseLogs; -use Appwrite\Platform\Modules\Databases\Http\Databases\Update as UpdateDatabase; -use Appwrite\Platform\Modules\Databases\Http\Databases\Usage\Get as GetDatabaseUsage; -use Appwrite\Platform\Modules\Databases\Http\Databases\Usage\XList as ListDatabaseUsage; -use Appwrite\Platform\Modules\Databases\Http\Databases\XList as ListDatabases; -use Appwrite\Platform\Modules\Databases\Http\Indexes\Create as CreateIndex; -use Appwrite\Platform\Modules\Databases\Http\Indexes\Delete as DeleteIndex; -use Appwrite\Platform\Modules\Databases\Http\Indexes\Get as GetIndex; -use Appwrite\Platform\Modules\Databases\Http\Indexes\XList as ListIndexes; -use Appwrite\Platform\Modules\Databases\Http\Rows\Create as CreateRow; -use Appwrite\Platform\Modules\Databases\Http\Rows\Delete as DeleteRow; -use Appwrite\Platform\Modules\Databases\Http\Rows\Get as GetRow; -use Appwrite\Platform\Modules\Databases\Http\Rows\Logs\XList as ListRowLogs; -use Appwrite\Platform\Modules\Databases\Http\Rows\Update as UpdateRow; -use Appwrite\Platform\Modules\Databases\Http\Rows\XList as ListRows; -use Appwrite\Platform\Modules\Databases\Http\Tables\Create as CreateTable; -use Appwrite\Platform\Modules\Databases\Http\Tables\Delete as DeleteTable; -use Appwrite\Platform\Modules\Databases\Http\Tables\Get as GetTable; -use Appwrite\Platform\Modules\Databases\Http\Tables\Logs\XList as ListTableLogs; -use Appwrite\Platform\Modules\Databases\Http\Tables\Update as UpdateTable; -use Appwrite\Platform\Modules\Databases\Http\Tables\Usage\Get as GetTableUsage; -use Appwrite\Platform\Modules\Databases\Http\Tables\XList as ListTables; +use Appwrite\Platform\Modules\Databases\Services\Registry\Collections as CollectionsRegistry; +use Appwrite\Platform\Modules\Databases\Services\Registry\Databases as DatabasesRegistry; +use Appwrite\Platform\Modules\Databases\Services\Registry\Tables as TablesRegistry; use Utopia\Platform\Service; class Http extends Service @@ -65,109 +13,12 @@ class Http extends Service { $this->type = Service::TYPE_HTTP; - $this->registerDatabaseActions(); - $this->registerCollectionAndTableActions(); - $this->registerColumnActions(); - $this->registerIndexActions(); - $this->registerRowActions(); - } - - private function registerDatabaseActions(): void - { - $this->addAction(CreateDatabase::getName(), new CreateDatabase()); - $this->addAction(GetDatabase::getName(), new GetDatabase()); - $this->addAction(UpdateDatabase::getName(), new UpdateDatabase()); - $this->addAction(DeleteDatabase::getName(), new DeleteDatabase()); - $this->addAction(ListDatabases::getName(), new ListDatabases()); - $this->addAction(ListDatabaseLogs::getName(), new ListDatabaseLogs()); - $this->addAction(GetDatabaseUsage::getName(), new GetDatabaseUsage()); - $this->addAction(ListDatabaseUsage::getName(), new ListDatabaseUsage()); - } - - private function registerCollectionAndTableActions(): void - { - // Collections - $this->addAction(CreateCollection::getName(), new CreateCollection()); - $this->addAction(GetCollection::getName(), new GetCollection()); - $this->addAction(UpdateCollection::getName(), new UpdateCollection()); - $this->addAction(DeleteCollection::getName(), new DeleteCollection()); - $this->addAction(ListCollections::getName(), new ListCollections()); - $this->addAction(ListCollectionLogs::getName(), new ListCollectionLogs()); - $this->addAction(GetCollectionUsage::getName(), new GetCollectionUsage()); - - // Tables - $this->addAction(CreateTable::getName(), new CreateTable()); - $this->addAction(GetTable::getName(), new GetTable()); - $this->addAction(UpdateTable::getName(), new UpdateTable()); - $this->addAction(DeleteTable::getName(), new DeleteTable()); - $this->addAction(ListTables::getName(), new ListTables()); - $this->addAction(ListTableLogs::getName(), new ListTableLogs()); - $this->addAction(GetTableUsage::getName(), new GetTableUsage()); - } - - private function registerColumnActions(): void - { - // Column top level actions - $this->addAction(GetColumn::getName(), new GetColumn()); - $this->addAction(DeleteColumn::getName(), new DeleteColumn()); - $this->addAction(ListColumns::getName(), new ListColumns()); - - // Column: Boolean - $this->addAction(CreateBoolean::getName(), new CreateBoolean()); - $this->addAction(UpdateBoolean::getName(), new UpdateBoolean()); - - // Column: Datetime - $this->addAction(CreateDatetime::getName(), new CreateDatetime()); - $this->addAction(UpdateDatetime::getName(), new UpdateDatetime()); - - // Column: Email - $this->addAction(CreateEmail::getName(), new CreateEmail()); - $this->addAction(UpdateEmail::getName(), new UpdateEmail()); - - // Column: Enum - $this->addAction(CreateEnum::getName(), new CreateEnum()); - $this->addAction(UpdateEnum::getName(), new UpdateEnum()); - - // Column: Float - $this->addAction(CreateFloat::getName(), new CreateFloat()); - $this->addAction(UpdateFloat::getName(), new UpdateFloat()); - - // Column: Integer - $this->addAction(CreateInteger::getName(), new CreateInteger()); - $this->addAction(UpdateInteger::getName(), new UpdateInteger()); - - // Column: IP - $this->addAction(CreateIP::getName(), new CreateIP()); - $this->addAction(UpdateIP::getName(), new UpdateIP()); - - // Column: Relationship - $this->addAction(CreateRelationship::getName(), new CreateRelationship()); - $this->addAction(UpdateRelationship::getName(), new UpdateRelationship()); - - // Column: String - $this->addAction(CreateString::getName(), new CreateString()); - $this->addAction(UpdateString::getName(), new UpdateString()); - - // Column: URL - $this->addAction(CreateURL::getName(), new CreateURL()); - $this->addAction(UpdateURL::getName(), new UpdateURL()); - } - - private function registerIndexActions(): void - { - $this->addAction(CreateIndex::getName(), new CreateIndex()); - $this->addAction(GetIndex::getName(), new GetIndex()); - $this->addAction(DeleteIndex::getName(), new DeleteIndex()); - $this->addAction(ListIndexes::getName(), new ListIndexes()); - } - - private function registerRowActions(): void - { - $this->addAction(CreateRow::getName(), new CreateRow()); - $this->addAction(GetRow::getName(), new GetRow()); - $this->addAction(UpdateRow::getName(), new UpdateRow()); - $this->addAction(DeleteRow::getName(), new DeleteRow()); - $this->addAction(ListRows::getName(), new ListRows()); - $this->addAction(ListRowLogs::getName(), new ListRowLogs()); + foreach ([ + DatabasesRegistry::class, + CollectionsRegistry::class, + TablesRegistry::class, + ] as $registrar) { + new $registrar($this); + } } } diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Base.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Base.php new file mode 100644 index 0000000000..43bc4b2959 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Base.php @@ -0,0 +1,24 @@ +register($service); + } + + /** + * Register all HTTP actions related to this module. + */ + abstract protected function register(Service $service): void; +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php new file mode 100644 index 0000000000..7b629bca44 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php @@ -0,0 +1,140 @@ +registerCollectionActions($service); + $this->registerDocumentActions($service); + $this->registerAttributeActions($service); + $this->registerIndexActions($service); + } + + private function registerCollectionActions(Service $service): void + { + $service->addAction(CreateCollection::getName(), new CreateCollection()); + $service->addAction(GetCollection::getName(), new GetCollection()); + $service->addAction(UpdateCollection::getName(), new UpdateCollection()); + $service->addAction(DeleteCollection::getName(), new DeleteCollection()); + $service->addAction(ListCollections::getName(), new ListCollections()); + $service->addAction(ListCollectionLogs::getName(), new ListCollectionLogs()); + $service->addAction(GetCollectionUsage::getName(), new GetCollectionUsage()); + } + + private function registerDocumentActions(Service $service): void + { + $service->addAction(CreateDocument::getName(), new CreateDocument()); + $service->addAction(GetDocument::getName(), new GetDocument()); + $service->addAction(UpdateDocument::getName(), new UpdateDocument()); + $service->addAction(DeleteDocument::getName(), new DeleteDocument()); + $service->addAction(ListDocuments::getName(), new ListDocuments()); + } + + private function registerAttributeActions(Service $service): void + { + // Attribute top-level actions + $service->addAction(GetAttribute::getName(), new GetAttribute()); + $service->addAction(DeleteAttribute::getName(), new DeleteAttribute()); + $service->addAction(ListAttributes::getName(), new ListAttributes()); + + // Attribute: Boolean + $service->addAction(CreateBooleanAttribute::getName(), new CreateBooleanAttribute()); + $service->addAction(UpdateBooleanAttribute::getName(), new UpdateBooleanAttribute()); + + // Attribute: Datetime + $service->addAction(CreateDatetimeAttribute::getName(), new CreateDatetimeAttribute()); + $service->addAction(UpdateDatetimeAttribute::getName(), new UpdateDatetimeAttribute()); + + // Attribute: Email + $service->addAction(CreateEmailAttribute::getName(), new CreateEmailAttribute()); + $service->addAction(UpdateEmailAttribute::getName(), new UpdateEmailAttribute()); + + // Attribute: Enum + $service->addAction(CreateEnumAttribute::getName(), new CreateEnumAttribute()); + $service->addAction(UpdateEnumAttribute::getName(), new UpdateEnumAttribute()); + + // Attribute: Float + $service->addAction(CreateFloatAttribute::getName(), new CreateFloatAttribute()); + $service->addAction(UpdateFloatAttribute::getName(), new UpdateFloatAttribute()); + + // Attribute: Integer + $service->addAction(CreateIntegerAttribute::getName(), new CreateIntegerAttribute()); + $service->addAction(UpdateIntegerAttribute::getName(), new UpdateIntegerAttribute()); + + // Attribute: IP + $service->addAction(CreateIPAttribute::getName(), new CreateIPAttribute()); + $service->addAction(UpdateIPAttribute::getName(), new UpdateIPAttribute()); + + // Attribute: Relationship + $service->addAction(CreateRelationshipAttribute::getName(), new CreateRelationshipAttribute()); + $service->addAction(UpdateRelationshipAttribute::getName(), new UpdateRelationshipAttribute()); + + // Attribute: String + $service->addAction(CreateStringAttribute::getName(), new CreateStringAttribute()); + $service->addAction(UpdateStringAttribute::getName(), new UpdateStringAttribute()); + + // Attribute: URL + $service->addAction(CreateURLAttribute::getName(), new CreateURLAttribute()); + $service->addAction(UpdateURLAttribute::getName(), new UpdateURLAttribute()); + } + + private function registerIndexActions(Service $service): void + { + $service->addAction(CreateIndex::getName(), new CreateIndex()); + $service->addAction(GetIndex::getName(), new GetIndex()); + $service->addAction(DeleteIndex::getName(), new DeleteIndex()); + $service->addAction(ListIndexes::getName(), new ListIndexes()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Databases.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Databases.php new file mode 100644 index 0000000000..81c9174253 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Databases.php @@ -0,0 +1,31 @@ +addAction(CreateDatabase::getName(), new CreateDatabase()); + $service->addAction(GetDatabase::getName(), new GetDatabase()); + $service->addAction(UpdateDatabase::getName(), new UpdateDatabase()); + $service->addAction(DeleteDatabase::getName(), new DeleteDatabase()); + $service->addAction(ListDatabases::getName(), new ListDatabases()); + $service->addAction(ListDatabaseLogs::getName(), new ListDatabaseLogs()); + $service->addAction(GetDatabaseUsage::getName(), new GetDatabaseUsage()); + $service->addAction(ListDatabaseUsage::getName(), new ListDatabaseUsage()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php new file mode 100644 index 0000000000..5c544a9d1f --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php @@ -0,0 +1,142 @@ +registerTableActions($service); + $this->registerColumnActions($service); + $this->registerColumnIndexActions($service); + $this->registerRowActions($service); + } + + private function registerTableActions(Service $service): void + { + $service->addAction(CreateTable::getName(), new CreateTable()); + $service->addAction(GetTable::getName(), new GetTable()); + $service->addAction(UpdateTable::getName(), new UpdateTable()); + $service->addAction(DeleteTable::getName(), new DeleteTable()); + $service->addAction(ListTables::getName(), new ListTables()); + $service->addAction(ListTableLogs::getName(), new ListTableLogs()); + $service->addAction(GetTableUsage::getName(), new GetTableUsage()); + } + + private function registerColumnActions(Service $service): void + { + // Column top level actions + $service->addAction(GetColumn::getName(), new GetColumn()); + $service->addAction(DeleteColumn::getName(), new DeleteColumn()); + $service->addAction(ListColumns::getName(), new ListColumns()); + + // Column: Boolean + $service->addAction(CreateBoolean::getName(), new CreateBoolean()); + $service->addAction(UpdateBoolean::getName(), new UpdateBoolean()); + + // Column: Datetime + $service->addAction(CreateDatetime::getName(), new CreateDatetime()); + $service->addAction(UpdateDatetime::getName(), new UpdateDatetime()); + + // Column: Email + $service->addAction(CreateEmail::getName(), new CreateEmail()); + $service->addAction(UpdateEmail::getName(), new UpdateEmail()); + + // Column: Enum + $service->addAction(CreateEnum::getName(), new CreateEnum()); + $service->addAction(UpdateEnum::getName(), new UpdateEnum()); + + // Column: Float + $service->addAction(CreateFloat::getName(), new CreateFloat()); + $service->addAction(UpdateFloat::getName(), new UpdateFloat()); + + // Column: Integer + $service->addAction(CreateInteger::getName(), new CreateInteger()); + $service->addAction(UpdateInteger::getName(), new UpdateInteger()); + + // Column: IP + $service->addAction(CreateIP::getName(), new CreateIP()); + $service->addAction(UpdateIP::getName(), new UpdateIP()); + + // Column: Relationship + $service->addAction(CreateRelationship::getName(), new CreateRelationship()); + $service->addAction(UpdateRelationship::getName(), new UpdateRelationship()); + + // Column: String + $service->addAction(CreateString::getName(), new CreateString()); + $service->addAction(UpdateString::getName(), new UpdateString()); + + // Column: URL + $service->addAction(CreateURL::getName(), new CreateURL()); + $service->addAction(UpdateURL::getName(), new UpdateURL()); + } + + private function registerColumnIndexActions(Service $service): void + { + $service->addAction(CreateColumnIndex::getName(), new CreateColumnIndex()); + $service->addAction(GetColumnIndex::getName(), new GetColumnIndex()); + $service->addAction(DeleteColumnIndex::getName(), new DeleteColumnIndex()); + $service->addAction(ListColumnIndexes::getName(), new ListColumnIndexes()); + } + + private function registerRowActions(Service $service): void + { + $service->addAction(CreateRow::getName(), new CreateRow()); + $service->addAction(GetRow::getName(), new GetRow()); + $service->addAction(UpdateRow::getName(), new UpdateRow()); + $service->addAction(DeleteRow::getName(), new DeleteRow()); + $service->addAction(ListRows::getName(), new ListRows()); + $service->addAction(ListRowLogs::getName(), new ListRowLogs()); + } +} From 44a5fef3455d84f98f2434dbd0a5c94474e0530a Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 19:17:06 +0530 Subject: [PATCH 091/343] misc: name fixes. --- .../Collections/Attributes/Boolean/Create.php | 2 +- .../Collections/Attributes/Boolean/Update.php | 2 +- .../Http/Databases/Collections/Attributes/Get.php | 6 +++--- .../Http/Databases/Collections/Attributes/XList.php | 3 +-- .../Http/Databases/Collections/Documents/Create.php | 8 ++++---- .../Http/Databases/Collections/Documents/Get.php | 2 +- .../Http/Databases/Collections/Documents/Update.php | 6 +++--- .../Http/Databases/Collections/Documents/XList.php | 6 +++--- .../Http/Databases/Collections/Indexes/Create.php | 12 ++++++------ .../Http/Databases/Tables/Indexes/Create.php | 7 ++++++- .../Http/Databases/Tables/Indexes/Delete.php | 7 ++++++- .../Databases/Http/Databases/Tables/Indexes/Get.php | 7 ++++++- .../Http/Databases/Tables/Indexes/XList.php | 7 ++++++- .../Modules/Databases/Services/Registry/Tables.php | 4 ++-- 14 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php index 56c0753f08..7eb6a109c0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php @@ -23,7 +23,7 @@ class Create extends Action public static function getName(): string { - return 'createBooleanColumn'; + return 'createBooleanAttribute'; } protected function getResponseModel(): string|array diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php index c8aa734570..9930ebdd8a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php @@ -23,7 +23,7 @@ class Update extends Action public static function getName(): string { - return 'updateBooleanColumn'; + return 'updateBooleanAttribute'; } protected function getResponseModel(): string|array diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index e04a89295b..3175efdd91 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -20,7 +20,7 @@ class Get extends Action public static function getName(): string { - return 'getColumn'; + return 'getAttribute'; } protected function getResponseModel(): string|array @@ -44,7 +44,7 @@ class Get extends Action $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') - ->desc('Get column') + ->desc('Get attribute') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) @@ -63,7 +63,7 @@ class Get extends Action )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID.') - ->param('key', '', new Key(), 'Column Key.') + ->param('key', '', new Key(), 'Attribute Key.') ->inject('response') ->inject('dbForProject') ->callback([$this, 'action']); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 29e8d1d6b9..fb77626021 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -7,7 +7,6 @@ use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Attributes; -use Appwrite\Utopia\Database\Validator\Queries\Columns; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; @@ -57,7 +56,7 @@ class XList extends Action )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') - ->param('queries', [], new Columns(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') ->callback([$this, 'action']); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index 6db7e802f3..c66f205a8c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -179,7 +179,7 @@ class Create extends Action $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -261,7 +261,7 @@ class Create extends Action $relationships = \array_filter( $table->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -300,10 +300,10 @@ class Create extends Action ->dynamic($document, $this->getResponseModel()); $relationships = \array_map( - fn ($row) => $document->getAttribute('key'), + fn ($document) => $document->getAttribute('key'), \array_filter( $collection->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ) ); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index f56ab40126..aa01eebcdf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -113,7 +113,7 @@ class Get extends Action $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index be009b9cd2..9b373c7e17 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -159,7 +159,7 @@ class Update extends Action $relationships = \array_filter( $collection->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -256,7 +256,7 @@ class Update extends Action $relationships = \array_filter( $table->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ); foreach ($relationships as $relationship) { @@ -290,7 +290,7 @@ class Update extends Action fn ($row) => $document->getAttribute('key'), \array_filter( $collection->getAttribute('attributes', []), - fn ($column) => $column->getAttribute('type') === Database::VAR_RELATIONSHIP + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ) ); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 7b4f5855e2..57af51d908 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -212,12 +212,12 @@ class XList extends Action } if ($select) { - foreach ($documents as $row) { + foreach ($documents as $document) { if (!$hasDatabaseId) { - $row->removeAttribute('$databaseId'); + $document->removeAttribute('$databaseId'); } if (!$hasCollectionId) { - $row->removeAttribute('$collectionId'); + $document->removeAttribute('$collectionId'); } } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index fe21025740..6370a32a4c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -150,23 +150,23 @@ class Create extends Action throw new Exception($this->getParentUnknownException(), "Unknown $contextType: " . $attribute . ". Verify the $contextType name or create the $contextType."); } - $columnStatus = $oldAttributes[$attributeIndex]['status']; - $columnType = $oldAttributes[$attributeIndex]['type']; - $columnArray = $oldAttributes[$attributeIndex]['array'] ?? false; + $attributeStatus = $oldAttributes[$attributeIndex]['status']; + $attributeType = $oldAttributes[$attributeIndex]['type']; + $attributeArray = $oldAttributes[$attributeIndex]['array'] ?? false; - if ($columnType === Database::VAR_RELATIONSHIP) { + if ($attributeType === Database::VAR_RELATIONSHIP) { throw new Exception($this->getParentInvalidTypeException(), "Cannot create an index for a relationship $contextType: " . $oldAttributes[$attributeIndex]['key']); } // ensure attribute is available - if ($columnStatus !== 'available') { + if ($attributeStatus !== 'available') { $contextType = ucfirst($contextType); throw new Exception($this->getParentNotAvailableException(), "$contextType not available: " . $oldAttributes[$attributeIndex]['key']); } $lengths[$i] = null; - if ($columnArray === true) { + if ($attributeArray === true) { $lengths[$i] = Database::ARRAY_INDEX_LENGTH; $orders[$i] = null; } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php index 97ac92d559..77e31f4115 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php @@ -22,6 +22,11 @@ class Create extends IndexCreate { use HTTP; + public static function getName(): string + { + return 'createColumnIndex'; + } + protected function getResponseModel(): string { return UtopiaResponse::MODEL_COLUMN_INDEX; @@ -44,7 +49,7 @@ class Create extends IndexCreate ->label('sdk', new Method( namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), - name: self::getName(), + name: 'createIndex', // getName needs to be different from parent action to avoid conflict in path name description: '/docs/references/databases/create-index.md', auth: [AuthType::KEY], responses: [ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php index 6a86a4767e..7a81942e32 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php @@ -20,6 +20,11 @@ class Delete extends IndexDelete { use HTTP; + public static function getName(): string + { + return 'updateColumnIndex'; + } + /** * 1. `SDKResponse` uses `UtopiaResponse::MODEL_NONE`. * 2. But we later need the actual return type for events queue below! @@ -46,7 +51,7 @@ class Delete extends IndexDelete ->label('sdk', new Method( namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), - name: self::getName(), + name: 'deleteIndex', // getName needs to be different from parent action to avoid conflict in path name description: '/docs/references/databases/delete-index.md', auth: [AuthType::KEY], responses: [ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php index 0cc537d960..a765bfb975 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php @@ -18,6 +18,11 @@ class Get extends IndexGet { use HTTP; + public static function getName(): string + { + return 'getColumnIndex'; + } + protected function getResponseModel(): string { return UtopiaResponse::MODEL_COLUMN_INDEX; @@ -37,7 +42,7 @@ class Get extends IndexGet ->label('sdk', new Method( namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), - name: self::getName(), + name: 'getIndex', // getName needs to be different from parent action to avoid conflict in path name description: '/docs/references/databases/get-index.md', auth: [AuthType::KEY], responses: [ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php index 5a245cf533..afce04fcf9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php @@ -18,6 +18,11 @@ class XList extends IndexXList { use HTTP; + public static function getName(): string + { + return 'listColumnIndexes'; + } + protected function getResponseModel(): string { return UtopiaResponse::MODEL_COLUMN_INDEX_LIST; @@ -37,7 +42,7 @@ class XList extends IndexXList ->label('sdk', new Method( namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), - name: self::getName(), + name: 'listIndexes', // getName needs to be different from parent action to avoid conflict in path name description: '/docs/references/databases/list-indexes.md', auth: [AuthType::KEY], responses: [ diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php index 5c544a9d1f..d881303c1e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php @@ -59,7 +59,7 @@ class Tables extends Base { $this->registerTableActions($service); $this->registerColumnActions($service); - $this->registerColumnIndexActions($service); + $this->registerIndexActions($service); $this->registerRowActions($service); } @@ -122,7 +122,7 @@ class Tables extends Base $service->addAction(UpdateURL::getName(), new UpdateURL()); } - private function registerColumnIndexActions(Service $service): void + private function registerIndexActions(Service $service): void { $service->addAction(CreateColumnIndex::getName(), new CreateColumnIndex()); $service->addAction(GetColumnIndex::getName(), new GetColumnIndex()); From 8006c9d60b62947e226963e37dceb3f491b004a3 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 19:36:59 +0530 Subject: [PATCH 092/343] misc: fixes. --- .../Collections/Attributes/Action.php | 24 +++++++++---------- .../Databases/Collections/Attributes/Get.php | 6 ++--- .../Collections/Attributes/XList.php | 4 ++-- .../Collections/Documents/Create.php | 12 +++++----- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index b683ebd64c..fcb9bcc2df 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -308,8 +308,8 @@ abstract class Action extends UtopiaAction if ($type === Database::VAR_RELATIONSHIP) { $options['side'] = Database::RELATION_SIDE_PARENT; - $relatedTable = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection'] ?? ''); - if ($relatedTable->isEmpty()) { + $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection'] ?? ''); + if ($relatedCollection->isEmpty()) { $parent = $this->isCollectionsAPI() ? 'collection' : 'table'; throw new Exception($this->getParentNotFoundException(), "The related $parent was not found."); } @@ -359,12 +359,12 @@ abstract class Action extends UtopiaAction try { $twoWayAttribute = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $twoWayKey), + '$id' => ID::custom($db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $twoWayKey), 'key' => $twoWayKey, 'databaseInternalId' => $db->getInternalId(), 'databaseId' => $db->getId(), - 'collectionInternalId' => $relatedTable->getInternalId(), - 'collectionId' => $relatedTable->getId(), + 'collectionInternalId' => $relatedCollection->getInternalId(), + 'collectionId' => $relatedCollection->getId(), 'type' => $type, 'status' => 'processing', // processing, available, failed, deleting, stuck 'size' => $size, @@ -378,7 +378,7 @@ abstract class Action extends UtopiaAction 'options' => $options, ]); - $dbForProject->checkAttribute($relatedTable, $twoWayAttribute); + $dbForProject->checkAttribute($relatedCollection, $twoWayAttribute); $dbForProject->createDocument('attributes', $twoWayAttribute); } catch (DuplicateException) { $dbForProject->deleteDocument('attributes', $attribute->getId()); @@ -387,13 +387,13 @@ abstract class Action extends UtopiaAction $dbForProject->deleteDocument('attributes', $attribute->getId()); throw new Exception($this->getLimitException()); } catch (Throwable $e) { - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); throw $e; } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedTable->getId()); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedTable->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); } $queueForDatabase @@ -447,11 +447,11 @@ abstract class Action extends UtopiaAction throw new Exception($this->getNotAvailableException()); } - if ($attribute->getAttribute('type') !== $type) { + if ($attribute->getAttribute(('type') !== $type)) { throw new Exception($this->getTypeInvalidException()); } - if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute('filter') !== $filter) { + if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute(('filter') !== $filter)) { throw new Exception($this->getTypeInvalidException()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index 3175efdd91..96e40c750d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -62,21 +62,21 @@ class Get extends Action ] )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Table ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') ->param('key', '', new Key(), 'Attribute Key.') ->inject('response') ->inject('dbForProject') ->callback([$this, 'action']); } - public function action(string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index fb77626021..7f2f23df62 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -62,14 +62,14 @@ class XList extends Action ->callback([$this, 'action']); } - public function action(string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject): void { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $tableId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index c66f205a8c..297d0f3543 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -197,9 +197,9 @@ class Create extends Action $relations = [$related]; } - $relatedTableId = $relationship->getAttribute('relatedCollection'); - $relatedTable = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedTableId) + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -213,7 +213,7 @@ class Create extends Action } if ($relation instanceof Document) { $current = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(), $relation->getId()) + fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()) ); if ($current->isEmpty()) { @@ -225,11 +225,11 @@ class Create extends Action } else { $relation->removeAttribute('$collectionId'); $relation->removeAttribute('$databaseId'); - $relation->setAttribute('$collection', $relatedTable->getId()); + $relation->setAttribute('$collection', $relatedCollection->getId()); $type = Database::PERMISSION_UPDATE; } - $checkPermissions($relatedTable, $relation, $type); + $checkPermissions($relatedCollection, $relation, $type); } } From 36e66170903e181b19e54c63f7fc93f5d8240650 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 19:47:35 +0530 Subject: [PATCH 093/343] update: the usage modals. --- app/controllers/api/project.php | 1 + .../Databases/Http/Databases/Usage/Get.php | 4 +++ .../Databases/Http/Databases/Usage/XList.php | 4 +++ .../Utopia/Response/Model/UsageDatabase.php | 23 ++++++++++++++-- .../Utopia/Response/Model/UsageDatabases.php | 27 ++++++++++++++++++- .../Utopia/Response/Model/UsageProject.php | 7 ++++- 6 files changed, 62 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 047179b888..079fabb622 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -354,6 +354,7 @@ App::get('/v1/project/usage') 'executionsMbSecondsTotal' => $total[METRIC_EXECUTIONS_MB_SECONDS], 'buildsMbSecondsTotal' => $total[METRIC_BUILDS_MB_SECONDS], 'documentsTotal' => $total[METRIC_DOCUMENTS], + 'rowsTotal' => $total[METRIC_DOCUMENTS], 'databasesTotal' => $total[METRIC_DATABASES], 'databasesStorageTotal' => $total[METRIC_DATABASES_STORAGE], 'usersTotal' => $total[METRIC_USERS], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php index c4105effa0..222201d5ed 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -124,12 +124,16 @@ class Get extends Action $response->dynamic(new Document([ 'range' => $range, 'collectionsTotal' => $usage[$metrics[0]]['total'], + 'tablesTotal' => $usage[$metrics[0]]['total'], 'documentsTotal' => $usage[$metrics[1]]['total'], + 'rowsTotal' => $usage[$metrics[1]]['total'], 'storageTotal' => $usage[$metrics[2]]['total'], 'databaseReadsTotal' => $usage[$metrics[3]]['total'], 'databaseWritesTotal' => $usage[$metrics[4]]['total'], 'collections' => $usage[$metrics[0]]['data'], + 'tables' => $usage[$metrics[0]]['data'], 'documents' => $usage[$metrics[1]]['data'], + 'rows' => $usage[$metrics[1]]['data'], 'storage' => $usage[$metrics[2]]['data'], 'databaseReads' => $usage[$metrics[3]]['data'], 'databaseWrites' => $usage[$metrics[4]]['data'], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php index 0078d54a4b..48533935b3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -117,13 +117,17 @@ class XList extends Action 'range' => $range, 'databasesTotal' => $usage[$metrics[0]]['total'], 'collectionsTotal' => $usage[$metrics[1]]['total'], + 'tablesTotal' => $usage[$metrics[1]]['total'], 'documentsTotal' => $usage[$metrics[2]]['total'], + 'rowsTotal' => $usage[$metrics[2]]['total'], 'storageTotal' => $usage[$metrics[3]]['total'], 'databasesReadsTotal' => $usage[$metrics[4]]['total'], 'databasesWritesTotal' => $usage[$metrics[5]]['total'], 'databases' => $usage[$metrics[0]]['data'], 'collections' => $usage[$metrics[1]]['data'], + 'tables' => $usage[$metrics[1]]['data'], 'documents' => $usage[$metrics[2]]['data'], + 'rows' => $usage[$metrics[2]]['data'], 'storage' => $usage[$metrics[3]]['data'], 'databasesReads' => $usage[$metrics[4]]['data'], 'databasesWrites' => $usage[$metrics[5]]['data'], diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php index 3adabae4c1..c7dc6d15ce 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php @@ -5,7 +5,6 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; -// TODO: check what do we use for - collectionsTotal, documentsTotal, collections, documents class UsageDatabase extends Model { public function __construct() @@ -23,12 +22,18 @@ class UsageDatabase extends Model 'default' => 0, 'example' => 0, ]) - ->addRule('collectionsTotal', [ + ->addRule('documentsTotal', [ 'type' => self::TYPE_INTEGER, 'description' => 'Total aggregated number of documents.', 'default' => 0, 'example' => 0, ]) + ->addRule('rowsTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of rows.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('storageTotal', [ 'type' => self::TYPE_INTEGER, 'description' => 'Total aggregated number of total storage used in bytes.', @@ -54,6 +59,13 @@ class UsageDatabase extends Model 'example' => [], 'array' => true ]) + ->addRule('tables', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of tables per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) ->addRule('documents', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated number of documents per period.', @@ -61,6 +73,13 @@ class UsageDatabase extends Model 'example' => [], 'array' => true ]) + ->addRule('rows', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of rows per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) ->addRule('storage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated storage used in bytes per period.', diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php index ae93182c0f..67568c858c 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php @@ -5,7 +5,6 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; -// TODO: check what do we use for - collectionsTotal, documentsTotal, collections, documents class UsageDatabases extends Model { public function __construct() @@ -29,12 +28,24 @@ class UsageDatabases extends Model 'default' => 0, 'example' => 0, ]) + ->addRule('tablesTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of tables.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('documentsTotal', [ 'type' => self::TYPE_INTEGER, 'description' => 'Total aggregated number of documents.', 'default' => 0, 'example' => 0, ]) + ->addRule('rowsTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of rows.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('storageTotal', [ 'type' => self::TYPE_INTEGER, 'description' => 'Total aggregated number of total databases storage in bytes.', @@ -67,6 +78,13 @@ class UsageDatabases extends Model 'example' => [], 'array' => true ]) + ->addRule('tables', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of tables per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) ->addRule('documents', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated number of documents per period.', @@ -74,6 +92,13 @@ class UsageDatabases extends Model 'example' => [], 'array' => true ]) + ->addRule('rows', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of rows per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) ->addRule('storage', [ 'type' => Response::MODEL_METRIC, 'description' => 'An array of the aggregated number of databases storage in bytes per period.', diff --git a/src/Appwrite/Utopia/Response/Model/UsageProject.php b/src/Appwrite/Utopia/Response/Model/UsageProject.php index 70f8003cfd..ee644aa845 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageProject.php +++ b/src/Appwrite/Utopia/Response/Model/UsageProject.php @@ -5,7 +5,6 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; -// TODO: check what do we use for - documents. class UsageProject extends Model { public function __construct() @@ -23,6 +22,12 @@ class UsageProject extends Model 'default' => 0, 'example' => 0, ]) + ->addRule('rowsTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of rows.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('databasesTotal', [ 'type' => self::TYPE_INTEGER, 'description' => 'Total aggregated number of databases.', From 5c0717458f00e126176787bcf0297074fbfa86b5 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 19:51:16 +0530 Subject: [PATCH 094/343] update: the usage model. --- src/Appwrite/Utopia/Response/Model/UsageDatabase.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php index c7dc6d15ce..990a2b3ee9 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php @@ -22,6 +22,12 @@ class UsageDatabase extends Model 'default' => 0, 'example' => 0, ]) + ->addRule('tablesTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of tables.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('documentsTotal', [ 'type' => self::TYPE_INTEGER, 'description' => 'Total aggregated number of documents.', From c5074fd52fc9d132e706e59f22a5254c54962684 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 19:53:31 +0530 Subject: [PATCH 095/343] update: move around tests. --- .../{ => Collections}/DatabasesBase.php | 518 +++++++++--------- .../DatabasesConsoleClientTest.php | 20 +- .../DatabasesCustomClientTest.php | 70 +-- .../DatabasesCustomServerTest.php | 336 ++++++------ .../DatabasesPermissionsGuestTest.php | 24 +- .../DatabasesPermissionsMemberTest.php | 18 +- .../DatabasesPermissionsScope.php | 2 +- .../DatabasesPermissionsTeamTest.php | 14 +- 8 files changed, 500 insertions(+), 502 deletions(-) rename tests/e2e/Services/Databases/{ => Collections}/DatabasesBase.php (93%) rename tests/e2e/Services/Databases/{ => Collections}/DatabasesConsoleClientTest.php (95%) rename tests/e2e/Services/Databases/{ => Collections}/DatabasesCustomClientTest.php (94%) rename tests/e2e/Services/Databases/{ => Collections}/DatabasesCustomServerTest.php (94%) rename tests/e2e/Services/Databases/{ => Collections}/DatabasesPermissionsGuestTest.php (95%) rename tests/e2e/Services/Databases/{ => Collections}/DatabasesPermissionsMemberTest.php (96%) rename tests/e2e/Services/Databases/{ => Collections}/DatabasesPermissionsScope.php (98%) rename tests/e2e/Services/Databases/{ => Collections}/DatabasesPermissionsTeamTest.php (95%) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/Collections/DatabasesBase.php similarity index 93% rename from tests/e2e/Services/Databases/DatabasesBase.php rename to tests/e2e/Services/Databases/Collections/DatabasesBase.php index 3c2a2c4186..9244e240f7 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/Collections/DatabasesBase.php @@ -1,6 +1,6 @@ $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Movies', 'documentSecurity' => true, 'permissions' => [ @@ -67,7 +66,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Actors', 'documentSecurity' => true, 'permissions' => [ @@ -88,7 +87,7 @@ trait DatabasesBase /** * @depends testCreateCollection */ - public function testConsoleProject(array $data) + public function testConsoleProject(array $data): void { if ($this->getSide() === 'server') { // Server side can't get past the invalid key check anyway @@ -148,7 +147,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Captain America', ], @@ -275,7 +274,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $data['actorsId'], + 'relatedCollectionId' => $data['actorsId'], 'type' => 'oneToMany', 'twoWay' => true, 'key' => 'starringActors', @@ -339,7 +338,7 @@ trait DatabasesBase $this->assertEquals($relationship['headers']['status-code'], 202); $this->assertEquals($relationship['body']['key'], 'starringActors'); $this->assertEquals($relationship['body']['type'], 'relationship'); - $this->assertEquals($relationship['body']['relatedTable'], $data['actorsId']); + $this->assertEquals($relationship['body']['relatedCollection'], $data['actorsId']); $this->assertEquals($relationship['body']['relationType'], 'oneToMany'); $this->assertEquals($relationship['body']['twoWay'], true); $this->assertEquals($relationship['body']['twoWayKey'], 'movie'); @@ -360,17 +359,17 @@ trait DatabasesBase 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertIsArray($movies['body']['columns']); - $this->assertCount(9, $movies['body']['columns']); - $this->assertEquals($movies['body']['columns'][0]['key'], $title['body']['key']); - $this->assertEquals($movies['body']['columns'][1]['key'], $description['body']['key']); - $this->assertEquals($movies['body']['columns'][2]['key'], $tagline['body']['key']); - $this->assertEquals($movies['body']['columns'][3]['key'], $releaseYear['body']['key']); - $this->assertEquals($movies['body']['columns'][4]['key'], $duration['body']['key']); - $this->assertEquals($movies['body']['columns'][5]['key'], $actors['body']['key']); - $this->assertEquals($movies['body']['columns'][6]['key'], $datetime['body']['key']); - $this->assertEquals($movies['body']['columns'][7]['key'], $relationship['body']['key']); - $this->assertEquals($movies['body']['columns'][8]['key'], $integers['body']['key']); + $this->assertIsArray($movies['body']['attributes']); + $this->assertCount(9, $movies['body']['attributes']); + $this->assertEquals($movies['body']['attributes'][0]['key'], $title['body']['key']); + $this->assertEquals($movies['body']['attributes'][1]['key'], $description['body']['key']); + $this->assertEquals($movies['body']['attributes'][2]['key'], $tagline['body']['key']); + $this->assertEquals($movies['body']['attributes'][3]['key'], $releaseYear['body']['key']); + $this->assertEquals($movies['body']['attributes'][4]['key'], $duration['body']['key']); + $this->assertEquals($movies['body']['attributes'][5]['key'], $actors['body']['key']); + $this->assertEquals($movies['body']['attributes'][6]['key'], $datetime['body']['key']); + $this->assertEquals($movies['body']['attributes'][7]['key'], $relationship['body']['key']); + $this->assertEquals($movies['body']['attributes'][8]['key'], $integers['body']['key']); return $data; } @@ -393,7 +392,7 @@ trait DatabasesBase ], ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(2, \count($response['body']['columns'])); + $this->assertEquals(2, \count($response['body']['attributes'])); $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -417,7 +416,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'patch', 'documentSecurity' => true, 'permissions' => [ @@ -449,7 +448,7 @@ trait DatabasesBase ]), [ 'key' => 'titleIndex', 'type' => 'key', - 'columns' => ['title'], + 'attributes' => ['title'], ]); $this->assertEquals(202, $index['headers']['status-code']); @@ -488,7 +487,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Players', 'documentSecurity' => true, 'permissions' => [ @@ -540,7 +539,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Response Models', // 'permissions' missing on purpose to make sure it's optional 'documentSecurity' => true, @@ -654,7 +653,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $data['actorsId'], + 'relatedCollectionId' => $data['actorsId'], 'type' => 'oneToMany', 'twoWay' => true, 'key' => 'relationship', @@ -763,7 +762,7 @@ trait DatabasesBase $this->assertEquals('relationship', $relationship['body']['type']); $this->assertEquals(false, $relationship['body']['required']); $this->assertEquals(false, $relationship['body']['array']); - $this->assertEquals($data['actorsId'], $relationship['body']['relatedTable']); + $this->assertEquals($data['actorsId'], $relationship['body']['relatedCollection']); $this->assertEquals('oneToMany', $relationship['body']['relationType']); $this->assertEquals(true, $relationship['body']['twoWay']); $this->assertEquals('twoWayKey', $relationship['body']['twoWayKey']); @@ -947,7 +946,7 @@ trait DatabasesBase $this->assertEquals('available', $relationshipResponse['body']['status']); $this->assertEquals($relationship['body']['required'], $relationshipResponse['body']['required']); $this->assertEquals($relationship['body']['array'], $relationshipResponse['body']['array']); - $this->assertEquals($relationship['body']['relatedTable'], $relationshipResponse['body']['relatedTable']); + $this->assertEquals($relationship['body']['relatedCollection'], $relationshipResponse['body']['relatedCollection']); $this->assertEquals($relationship['body']['relationType'], $relationshipResponse['body']['relationType']); $this->assertEquals($relationship['body']['twoWay'], $relationshipResponse['body']['twoWay']); $this->assertEquals($relationship['body']['twoWayKey'], $relationshipResponse['body']['twoWayKey']); @@ -961,7 +960,7 @@ trait DatabasesBase $this->assertEquals(200, $attributes['headers']['status-code']); $this->assertEquals(12, $attributes['body']['total']); - $attributes = $attributes['body']['columns']; + $attributes = $attributes['body']['attributes']; $this->assertIsArray($attributes); $this->assertCount(12, $attributes); @@ -1043,7 +1042,7 @@ trait DatabasesBase $this->assertEquals($relationshipResponse['body']['status'], $attributes[9]['status']); $this->assertEquals($relationshipResponse['body']['required'], $attributes[9]['required']); $this->assertEquals($relationshipResponse['body']['array'], $attributes[9]['array']); - $this->assertEquals($relationshipResponse['body']['relatedTable'], $attributes[9]['relatedTable']); + $this->assertEquals($relationshipResponse['body']['relatedCollection'], $attributes[9]['relatedCollection']); $this->assertEquals($relationshipResponse['body']['relationType'], $attributes[9]['relationType']); $this->assertEquals($relationshipResponse['body']['twoWay'], $attributes[9]['twoWay']); $this->assertEquals($relationshipResponse['body']['twoWayKey'], $attributes[9]['twoWayKey']); @@ -1072,7 +1071,7 @@ trait DatabasesBase $this->assertEquals(200, $collection['headers']['status-code']); - $attributes = $collection['body']['columns']; + $attributes = $collection['body']['attributes']; $this->assertIsArray($attributes); $this->assertCount(12, $attributes); @@ -1155,7 +1154,7 @@ trait DatabasesBase $this->assertEquals($relationshipResponse['body']['status'], $attributes[9]['status']); $this->assertEquals($relationshipResponse['body']['required'], $attributes[9]['required']); $this->assertEquals($relationshipResponse['body']['array'], $attributes[9]['array']); - $this->assertEquals($relationshipResponse['body']['relatedTable'], $attributes[9]['relatedTable']); + $this->assertEquals($relationshipResponse['body']['relatedCollection'], $attributes[9]['relatedCollection']); $this->assertEquals($relationshipResponse['body']['relationType'], $attributes[9]['relationType']); $this->assertEquals($relationshipResponse['body']['twoWay'], $attributes[9]['twoWay']); $this->assertEquals($relationshipResponse['body']['twoWayKey'], $attributes[9]['twoWayKey']); @@ -1210,14 +1209,14 @@ trait DatabasesBase ]), [ 'key' => 'titleIndex', 'type' => 'fulltext', - 'columns' => ['title'], + 'attributes' => ['title'], ]); $this->assertEquals(202, $titleIndex['headers']['status-code']); $this->assertEquals('titleIndex', $titleIndex['body']['key']); $this->assertEquals('fulltext', $titleIndex['body']['type']); - $this->assertCount(1, $titleIndex['body']['columns']); - $this->assertEquals('title', $titleIndex['body']['columns'][0]); + $this->assertCount(1, $titleIndex['body']['attributes']); + $this->assertEquals('title', $titleIndex['body']['attributes'][0]); $releaseYearIndex = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', @@ -1226,14 +1225,14 @@ trait DatabasesBase ]), [ 'key' => 'releaseYear', 'type' => 'key', - 'columns' => ['releaseYear'], + 'attributes' => ['releaseYear'], ]); $this->assertEquals(202, $releaseYearIndex['headers']['status-code']); $this->assertEquals('releaseYear', $releaseYearIndex['body']['key']); $this->assertEquals('key', $releaseYearIndex['body']['type']); - $this->assertCount(1, $releaseYearIndex['body']['columns']); - $this->assertEquals('releaseYear', $releaseYearIndex['body']['columns'][0]); + $this->assertCount(1, $releaseYearIndex['body']['attributes']); + $this->assertEquals('releaseYear', $releaseYearIndex['body']['attributes'][0]); $releaseWithDate1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', @@ -1242,16 +1241,16 @@ trait DatabasesBase ]), [ 'key' => 'releaseYearDated', 'type' => 'key', - 'columns' => ['releaseYear', '$createdAt', '$updatedAt'], + 'attributes' => ['releaseYear', '$createdAt', '$updatedAt'], ]); $this->assertEquals(202, $releaseWithDate1['headers']['status-code']); $this->assertEquals('releaseYearDated', $releaseWithDate1['body']['key']); $this->assertEquals('key', $releaseWithDate1['body']['type']); - $this->assertCount(3, $releaseWithDate1['body']['columns']); - $this->assertEquals('releaseYear', $releaseWithDate1['body']['columns'][0]); - $this->assertEquals('$createdAt', $releaseWithDate1['body']['columns'][1]); - $this->assertEquals('$updatedAt', $releaseWithDate1['body']['columns'][2]); + $this->assertCount(3, $releaseWithDate1['body']['attributes']); + $this->assertEquals('releaseYear', $releaseWithDate1['body']['attributes'][0]); + $this->assertEquals('$createdAt', $releaseWithDate1['body']['attributes'][1]); + $this->assertEquals('$updatedAt', $releaseWithDate1['body']['attributes'][2]); $releaseWithDate2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', @@ -1260,14 +1259,14 @@ trait DatabasesBase ]), [ 'key' => 'birthDay', 'type' => 'key', - 'columns' => ['birthDay'], + 'attributes' => ['birthDay'], ]); $this->assertEquals(202, $releaseWithDate2['headers']['status-code']); $this->assertEquals('birthDay', $releaseWithDate2['body']['key']); $this->assertEquals('key', $releaseWithDate2['body']['type']); - $this->assertCount(1, $releaseWithDate2['body']['columns']); - $this->assertEquals('birthDay', $releaseWithDate2['body']['columns'][0]); + $this->assertCount(1, $releaseWithDate2['body']['attributes']); + $this->assertEquals('birthDay', $releaseWithDate2['body']['attributes'][0]); // Test for failure $fulltextReleaseYear = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ @@ -1277,7 +1276,7 @@ trait DatabasesBase ]), [ 'key' => 'releaseYearDated', 'type' => 'fulltext', - 'columns' => ['releaseYear'], + 'attributes' => ['releaseYear'], ]); $this->assertEquals(400, $fulltextReleaseYear['headers']['status-code']); @@ -1290,7 +1289,7 @@ trait DatabasesBase ]), [ 'key' => 'none', 'type' => 'key', - 'columns' => [], + 'attributes' => [], ]); $this->assertEquals(400, $noAttributes['headers']['status-code']); @@ -1303,7 +1302,7 @@ trait DatabasesBase ]), [ 'key' => 'duplicate', 'type' => 'fulltext', - 'columns' => ['releaseYear', 'releaseYear'], + 'attributes' => ['releaseYear', 'releaseYear'], ]); $this->assertEquals(400, $duplicates['headers']['status-code']); @@ -1316,7 +1315,7 @@ trait DatabasesBase ]), [ 'key' => 'tooLong', 'type' => 'key', - 'columns' => ['description', 'tagline'], + 'attributes' => ['description', 'tagline'], ]); $this->assertEquals(400, $tooLong['headers']['status-code']); @@ -1329,7 +1328,7 @@ trait DatabasesBase ]), [ 'key' => 'ft', 'type' => 'fulltext', - 'columns' => ['actors'], + 'attributes' => ['actors'], ]); $this->assertEquals(400, $fulltextArray['headers']['status-code']); @@ -1342,7 +1341,7 @@ trait DatabasesBase ]), [ 'key' => 'index-actors', 'type' => 'key', - 'columns' => ['actors'], + 'attributes' => ['actors'], ]); $this->assertEquals(202, $actorsArray['headers']['status-code']); @@ -1354,7 +1353,7 @@ trait DatabasesBase ]), [ 'key' => 'index-ip-actors', 'type' => 'key', - 'columns' => ['releaseYear', 'actors'], // 2 levels + 'attributes' => ['releaseYear', 'actors'], // 2 levels 'orders' => ['DESC', 'DESC'], ]); @@ -1369,11 +1368,11 @@ trait DatabasesBase ]), [ 'key' => 'index-unknown', 'type' => 'key', - 'columns' => ['Unknown'], + 'attributes' => ['Unknown'], ]); $this->assertEquals(400, $unknown['headers']['status-code']); - $this->assertEquals('Unknown column: Unknown. Verify the column name or create the column.', $unknown['body']['message']); + $this->assertEquals('Unknown attribute: Unknown. Verify the attribute name or create the attribute.', $unknown['body']['message']); $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', @@ -1382,7 +1381,7 @@ trait DatabasesBase ]), [ 'key' => 'integers-order', 'type' => 'key', - 'columns' => ['integers'], // array attribute + 'attributes' => ['integers'], // array attribute 'orders' => ['DESC'], // Check order is removed in API ]); $this->assertEquals(202, $index1['headers']['status-code']); @@ -1394,7 +1393,7 @@ trait DatabasesBase ]), [ 'key' => 'integers-size', 'type' => 'key', - 'columns' => ['integers'], // array attribute + 'attributes' => ['integers'], // array attribute ]); $this->assertEquals(202, $index2['headers']['status-code']); @@ -1463,7 +1462,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Captain America', 'releaseYear' => 1944, @@ -1484,7 +1483,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Spider-Man: Far From Home', 'releaseYear' => 2019, @@ -1507,7 +1506,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Spider-Man: Homecoming', 'releaseYear' => 2017, @@ -1530,7 +1529,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'releaseYear' => 2020, // Missing title, expect an 400 error ], @@ -1542,7 +1541,7 @@ trait DatabasesBase ]); $this->assertEquals(201, $document1['headers']['status-code']); - $this->assertEquals($data['moviesId'], $document1['body']['$tableId']); + $this->assertEquals($data['moviesId'], $document1['body']['$collectionId']); $this->assertArrayNotHasKey('$collection', $document1['body']); $this->assertEquals($databaseId, $document1['body']['$databaseId']); $this->assertEquals($document1['body']['title'], 'Captain America'); @@ -1555,7 +1554,7 @@ trait DatabasesBase $this->assertEquals($document1['body']['birthDay'], '1975-06-12T12:12:55.000+00:00'); $this->assertEquals(201, $document2['headers']['status-code']); - $this->assertEquals($data['moviesId'], $document2['body']['$tableId']); + $this->assertEquals($data['moviesId'], $document2['body']['$collectionId']); $this->assertArrayNotHasKey('$collection', $document2['body']); $this->assertEquals($databaseId, $document2['body']['$databaseId']); $this->assertEquals($document2['body']['title'], 'Spider-Man: Far From Home'); @@ -1572,7 +1571,7 @@ trait DatabasesBase $this->assertEquals($document2['body']['integers'][1], 60); $this->assertEquals(201, $document3['headers']['status-code']); - $this->assertEquals($data['moviesId'], $document3['body']['$tableId']); + $this->assertEquals($data['moviesId'], $document3['body']['$collectionId']); $this->assertArrayNotHasKey('$collection', $document3['body']); $this->assertEquals($databaseId, $document3['body']['$databaseId']); $this->assertEquals($document3['body']['title'], 'Spider-Man: Homecoming'); @@ -1612,17 +1611,16 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(1944, $documents['body']['rows'][0]['releaseYear']); - $this->assertEquals(2017, $documents['body']['rows'][1]['releaseYear']); - $this->assertEquals(2019, $documents['body']['rows'][2]['releaseYear']); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['rows'][0])); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['rows'][1])); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['rows'][2])); - $this->assertCount(3, $documents['body']['rows']); + $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); + $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); + $this->assertEquals(2019, $documents['body']['documents'][2]['releaseYear']); + $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][0])); + $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][1])); + $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][2])); + $this->assertCount(3, $documents['body']['documents']); - foreach ($documents['body']['rows'] as $document) { - print_r($document); - $this->assertEquals($data['moviesId'], $document['$tableId']); + foreach ($documents['body']['documents'] as $document) { + $this->assertEquals($data['moviesId'], $document['$collectionId']); $this->assertArrayNotHasKey('$collection', $document); $this->assertEquals($databaseId, $document['$databaseId']); } @@ -1637,10 +1635,10 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(1944, $documents['body']['rows'][2]['releaseYear']); - $this->assertEquals(2017, $documents['body']['rows'][1]['releaseYear']); - $this->assertEquals(2019, $documents['body']['rows'][0]['releaseYear']); - $this->assertCount(3, $documents['body']['rows']); + $this->assertEquals(1944, $documents['body']['documents'][2]['releaseYear']); + $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); + $this->assertEquals(2019, $documents['body']['documents'][0]['releaseYear']); + $this->assertCount(3, $documents['body']['documents']); // changing description attribute to be null by default instead of empty string $patchNull = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string/description', array_merge([ @@ -1656,7 +1654,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Dummy', 'releaseYear' => 1944, @@ -1686,7 +1684,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - return ['rows' => $documents['body']['rows'], 'databaseId' => $databaseId]; + return ['documents' => $documents['body']['documents'], 'databaseId' => $databaseId]; } @@ -1696,15 +1694,15 @@ trait DatabasesBase public function testGetDocument(array $data): void { $databaseId = $data['databaseId']; - foreach ($data['rows'] as $document) { - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$tableId'] . '/documents/' . $document['$id'], array_merge([ + foreach ($data['documents'] as $document) { + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals($response['body']['$id'], $document['$id']); - $this->assertEquals($document['$tableId'], $response['body']['$tableId']); + $this->assertEquals($document['$collectionId'], $response['body']['$collectionId']); $this->assertArrayNotHasKey('$collection', $response['body']); $this->assertEquals($document['$databaseId'], $response['body']['$databaseId']); $this->assertEquals($response['body']['title'], $document['title']); @@ -1722,9 +1720,9 @@ trait DatabasesBase public function testGetDocumentWithQueries(array $data): void { $databaseId = $data['databaseId']; - $document = $data['rows'][0]; + $document = $data['documents'][0]; - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$tableId'] . '/documents/' . $document['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1754,36 +1752,36 @@ trait DatabasesBase ], $this->getHeaders())); $this->assertEquals(200, $base['headers']['status-code']); - $this->assertEquals('Captain America', $base['body']['rows'][0]['title']); - $this->assertEquals('Spider-Man: Far From Home', $base['body']['rows'][1]['title']); - $this->assertEquals('Spider-Man: Homecoming', $base['body']['rows'][2]['title']); - $this->assertCount(3, $base['body']['rows']); + $this->assertEquals('Captain America', $base['body']['documents'][0]['title']); + $this->assertEquals('Spider-Man: Far From Home', $base['body']['documents'][1]['title']); + $this->assertEquals('Spider-Man: Homecoming', $base['body']['documents'][2]['title']); + $this->assertCount(3, $base['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorAfter(new Document(['$id' => $base['body']['rows'][0]['$id']]))->toString() + Query::cursorAfter(new Document(['$id' => $base['body']['documents'][0]['$id']]))->toString() ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals($base['body']['rows'][1]['$id'], $documents['body']['rows'][0]['$id']); - $this->assertEquals($base['body']['rows'][2]['$id'], $documents['body']['rows'][1]['$id']); - $this->assertCount(2, $documents['body']['rows']); + $this->assertEquals($base['body']['documents'][1]['$id'], $documents['body']['documents'][0]['$id']); + $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][1]['$id']); + $this->assertCount(2, $documents['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorAfter(new Document(['$id' => $base['body']['rows'][2]['$id']]))->toString() + Query::cursorAfter(new Document(['$id' => $base['body']['documents'][2]['$id']]))->toString() ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEmpty($documents['body']['rows']); + $this->assertEmpty($documents['body']['documents']); /** * Test with ASC order and after. @@ -1798,24 +1796,24 @@ trait DatabasesBase ]); $this->assertEquals(200, $base['headers']['status-code']); - $this->assertEquals(1944, $base['body']['rows'][0]['releaseYear']); - $this->assertEquals(2017, $base['body']['rows'][1]['releaseYear']); - $this->assertEquals(2019, $base['body']['rows'][2]['releaseYear']); - $this->assertCount(3, $base['body']['rows']); + $this->assertEquals(1944, $base['body']['documents'][0]['releaseYear']); + $this->assertEquals(2017, $base['body']['documents'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['documents'][2]['releaseYear']); + $this->assertCount(3, $base['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorAfter(new Document(['$id' => $base['body']['rows'][1]['$id']]))->toString(), + Query::cursorAfter(new Document(['$id' => $base['body']['documents'][1]['$id']]))->toString(), Query::orderAsc('releaseYear')->toString() ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals($base['body']['rows'][2]['$id'], $documents['body']['rows'][0]['$id']); - $this->assertCount(1, $documents['body']['rows']); + $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][0]['$id']); + $this->assertCount(1, $documents['body']['documents']); /** * Test with DESC order and after. @@ -1830,24 +1828,24 @@ trait DatabasesBase ]); $this->assertEquals(200, $base['headers']['status-code']); - $this->assertEquals(1944, $base['body']['rows'][2]['releaseYear']); - $this->assertEquals(2017, $base['body']['rows'][1]['releaseYear']); - $this->assertEquals(2019, $base['body']['rows'][0]['releaseYear']); - $this->assertCount(3, $base['body']['rows']); + $this->assertEquals(1944, $base['body']['documents'][2]['releaseYear']); + $this->assertEquals(2017, $base['body']['documents'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['documents'][0]['releaseYear']); + $this->assertCount(3, $base['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorAfter(new Document(['$id' => $base['body']['rows'][1]['$id']]))->toString(), + Query::cursorAfter(new Document(['$id' => $base['body']['documents'][1]['$id']]))->toString(), Query::orderDesc('releaseYear')->toString() ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals($base['body']['rows'][2]['$id'], $documents['body']['rows'][0]['$id']); - $this->assertCount(1, $documents['body']['rows']); + $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][0]['$id']); + $this->assertCount(1, $documents['body']['documents']); /** * Test after with unknown document. @@ -1896,36 +1894,36 @@ trait DatabasesBase ], $this->getHeaders())); $this->assertEquals(200, $base['headers']['status-code']); - $this->assertEquals('Captain America', $base['body']['rows'][0]['title']); - $this->assertEquals('Spider-Man: Far From Home', $base['body']['rows'][1]['title']); - $this->assertEquals('Spider-Man: Homecoming', $base['body']['rows'][2]['title']); - $this->assertCount(3, $base['body']['rows']); + $this->assertEquals('Captain America', $base['body']['documents'][0]['title']); + $this->assertEquals('Spider-Man: Far From Home', $base['body']['documents'][1]['title']); + $this->assertEquals('Spider-Man: Homecoming', $base['body']['documents'][2]['title']); + $this->assertCount(3, $base['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorBefore(new Document(['$id' => $base['body']['rows'][2]['$id']]))->toString(), + Query::cursorBefore(new Document(['$id' => $base['body']['documents'][2]['$id']]))->toString(), ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals($base['body']['rows'][0]['$id'], $documents['body']['rows'][0]['$id']); - $this->assertEquals($base['body']['rows'][1]['$id'], $documents['body']['rows'][1]['$id']); - $this->assertCount(2, $documents['body']['rows']); + $this->assertEquals($base['body']['documents'][0]['$id'], $documents['body']['documents'][0]['$id']); + $this->assertEquals($base['body']['documents'][1]['$id'], $documents['body']['documents'][1]['$id']); + $this->assertCount(2, $documents['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorBefore(new Document(['$id' => $base['body']['rows'][0]['$id']]))->toString(), + Query::cursorBefore(new Document(['$id' => $base['body']['documents'][0]['$id']]))->toString(), ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEmpty($documents['body']['rows']); + $this->assertEmpty($documents['body']['documents']); /** * Test with ASC order and after. @@ -1940,24 +1938,24 @@ trait DatabasesBase ]); $this->assertEquals(200, $base['headers']['status-code']); - $this->assertEquals(1944, $base['body']['rows'][0]['releaseYear']); - $this->assertEquals(2017, $base['body']['rows'][1]['releaseYear']); - $this->assertEquals(2019, $base['body']['rows'][2]['releaseYear']); - $this->assertCount(3, $base['body']['rows']); + $this->assertEquals(1944, $base['body']['documents'][0]['releaseYear']); + $this->assertEquals(2017, $base['body']['documents'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['documents'][2]['releaseYear']); + $this->assertCount(3, $base['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorBefore(new Document(['$id' => $base['body']['rows'][1]['$id']]))->toString(), + Query::cursorBefore(new Document(['$id' => $base['body']['documents'][1]['$id']]))->toString(), Query::orderAsc('releaseYear')->toString(), ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals($base['body']['rows'][0]['$id'], $documents['body']['rows'][0]['$id']); - $this->assertCount(1, $documents['body']['rows']); + $this->assertEquals($base['body']['documents'][0]['$id'], $documents['body']['documents'][0]['$id']); + $this->assertCount(1, $documents['body']['documents']); /** * Test with DESC order and after. @@ -1972,24 +1970,24 @@ trait DatabasesBase ]); $this->assertEquals(200, $base['headers']['status-code']); - $this->assertEquals(1944, $base['body']['rows'][2]['releaseYear']); - $this->assertEquals(2017, $base['body']['rows'][1]['releaseYear']); - $this->assertEquals(2019, $base['body']['rows'][0]['releaseYear']); - $this->assertCount(3, $base['body']['rows']); + $this->assertEquals(1944, $base['body']['documents'][2]['releaseYear']); + $this->assertEquals(2017, $base['body']['documents'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['documents'][0]['releaseYear']); + $this->assertCount(3, $base['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorBefore(new Document(['$id' => $base['body']['rows'][1]['$id']]))->toString(), + Query::cursorBefore(new Document(['$id' => $base['body']['documents'][1]['$id']]))->toString(), Query::orderDesc('releaseYear')->toString(), ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals($base['body']['rows'][0]['$id'], $documents['body']['rows'][0]['$id']); - $this->assertCount(1, $documents['body']['rows']); + $this->assertEquals($base['body']['documents'][0]['$id'], $documents['body']['documents'][0]['$id']); + $this->assertCount(1, $documents['body']['documents']); return []; } @@ -2011,8 +2009,8 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(1944, $documents['body']['rows'][0]['releaseYear']); - $this->assertCount(1, $documents['body']['rows']); + $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); + $this->assertCount(1, $documents['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2026,9 +2024,9 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(2017, $documents['body']['rows'][0]['releaseYear']); - $this->assertEquals(2019, $documents['body']['rows'][1]['releaseYear']); - $this->assertCount(2, $documents['body']['rows']); + $this->assertEquals(2017, $documents['body']['documents'][0]['releaseYear']); + $this->assertEquals(2019, $documents['body']['documents'][1]['releaseYear']); + $this->assertCount(2, $documents['body']['documents']); return []; } @@ -2049,21 +2047,21 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(1944, $documents['body']['rows'][0]['releaseYear']); - $this->assertCount(1, $documents['body']['rows']); + $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); + $this->assertCount(1, $documents['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::equal('$id', [$documents['body']['rows'][0]['$id']])->toString(), + Query::equal('$id', [$documents['body']['documents'][0]['$id']])->toString(), ], ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(1944, $documents['body']['rows'][0]['releaseYear']); - $this->assertCount(1, $documents['body']['rows']); + $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); + $this->assertCount(1, $documents['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2075,8 +2073,8 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(2017, $documents['body']['rows'][0]['releaseYear']); - $this->assertCount(1, $documents['body']['rows']); + $this->assertEquals(2017, $documents['body']['documents'][0]['releaseYear']); + $this->assertCount(1, $documents['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2088,9 +2086,9 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(2019, $documents['body']['rows'][0]['releaseYear']); - $this->assertEquals(2017, $documents['body']['rows'][1]['releaseYear']); - $this->assertCount(2, $documents['body']['rows']); + $this->assertEquals(2019, $documents['body']['documents'][0]['releaseYear']); + $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); + $this->assertCount(2, $documents['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2125,8 +2123,8 @@ trait DatabasesBase ], ]); - $this->assertCount(1, $documents['body']['rows']); - $this->assertEquals('Captain America', $documents['body']['rows'][0]['title']); + $this->assertCount(1, $documents['body']['documents']); + $this->assertEquals('Captain America', $documents['body']['documents'][0]['title']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2137,9 +2135,9 @@ trait DatabasesBase ], ]); - $this->assertCount(2, $documents['body']['rows']); - $this->assertEquals('Spider-Man: Far From Home', $documents['body']['rows'][0]['title']); - $this->assertEquals('Spider-Man: Homecoming', $documents['body']['rows'][1]['title']); + $this->assertCount(2, $documents['body']['documents']); + $this->assertEquals('Spider-Man: Far From Home', $documents['body']['documents'][0]['title']); + $this->assertEquals('Spider-Man: Homecoming', $documents['body']['documents'][1]['title']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2150,7 +2148,7 @@ trait DatabasesBase ], ]); - $this->assertCount(3, $documents['body']['rows']); + $this->assertCount(3, $documents['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2161,7 +2159,7 @@ trait DatabasesBase ], ]); - $this->assertCount(0, $documents['body']['rows']); + $this->assertCount(0, $documents['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2209,9 +2207,9 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals('1975-06-12T12:12:55.000+00:00', $documents['body']['rows'][0]['birthDay']); - $this->assertEquals('1975-06-12T18:12:55.000+00:00', $documents['body']['rows'][1]['birthDay']); - $this->assertCount(2, $documents['body']['rows']); + $this->assertEquals('1975-06-12T12:12:55.000+00:00', $documents['body']['documents'][0]['birthDay']); + $this->assertEquals('1975-06-12T18:12:55.000+00:00', $documents['body']['documents'][1]['birthDay']); + $this->assertCount(2, $documents['body']['documents']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -2288,7 +2286,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Thor: Ragnaroc', 'releaseYear' => 2017, @@ -2306,7 +2304,7 @@ trait DatabasesBase $id = $document['body']['$id']; $this->assertEquals(201, $document['headers']['status-code']); - $this->assertEquals($data['moviesId'], $document['body']['$tableId']); + $this->assertEquals($data['moviesId'], $document['body']['$collectionId']); $this->assertArrayNotHasKey('$collection', $document['body']); $this->assertEquals($databaseId, $document['body']['$databaseId']); $this->assertEquals($document['body']['title'], 'Thor: Ragnaroc'); @@ -2334,7 +2332,7 @@ trait DatabasesBase $this->assertEquals(200, $document['headers']['status-code']); $this->assertEquals($document['body']['$id'], $id); - $this->assertEquals($data['moviesId'], $document['body']['$tableId']); + $this->assertEquals($data['moviesId'], $document['body']['$collectionId']); $this->assertArrayNotHasKey('$collection', $document['body']); $this->assertEquals($databaseId, $document['body']['$databaseId']); $this->assertEquals($document['body']['title'], 'Thor: Ragnarok'); @@ -2351,7 +2349,7 @@ trait DatabasesBase $id = $document['body']['$id']; $this->assertEquals(200, $document['headers']['status-code']); - $this->assertEquals($data['moviesId'], $document['body']['$tableId']); + $this->assertEquals($data['moviesId'], $document['body']['$collectionId']); $this->assertArrayNotHasKey('$collection', $document['body']); $this->assertEquals($databaseId, $document['body']['$databaseId']); $this->assertEquals($document['body']['title'], 'Thor: Ragnarok'); @@ -2399,7 +2397,7 @@ trait DatabasesBase $this->assertEquals(409, $response['headers']['status-code']); $this->assertEquals('Remote document is newer than local.', $response['body']['message']); - $this->assertEquals(Exception::ROW_UPDATE_CONFLICT, $response['body']['type']); + $this->assertEquals(Exception::DOCUMENT_UPDATE_CONFLICT, $response['body']['type']); return []; } @@ -2414,7 +2412,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Thor: Ragnarok', 'releaseYear' => 2017, @@ -2475,7 +2473,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'invalidDocumentStructure', 'permissions' => [ Permission::create(Role::any()), @@ -2672,7 +2670,7 @@ trait DatabasesBase $this->assertEquals(400, $enumDefault['headers']['status-code']); $this->assertEquals(400, $enumDefaultStrict['headers']['status-code']); $this->assertEquals('Minimum value must be lesser than maximum value', $invalidRange['body']['message']); - $this->assertEquals('Cannot set default value for array columns', $defaultArray['body']['message']); + $this->assertEquals('Cannot set default value for array attributes', $defaultArray['body']['message']); $this->assertEquals(400, $datetimeDefault['headers']['status-code']); // wait for worker to add attributes sleep(3); @@ -2683,7 +2681,7 @@ trait DatabasesBase 'x-appwrite-key' => $this->getProject()['apiKey'], ]), []); - $this->assertCount(10, $collection['body']['columns']); + $this->assertCount(10, $collection['body']['attributes']); /** * Test for successful validation @@ -2693,7 +2691,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'email' => 'user@example.com', ], @@ -2708,7 +2706,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'enum' => 'yes', ], @@ -2723,7 +2721,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'ip' => '1.1.1.1', ], @@ -2738,7 +2736,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'url' => 'http://www.example.com', ], @@ -2753,7 +2751,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'range' => 3, ], @@ -2768,7 +2766,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'floatRange' => 1.4, ], @@ -2783,7 +2781,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'probability' => 0.99999, ], @@ -2798,7 +2796,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'upperBound' => 8, ], @@ -2813,7 +2811,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'lowerBound' => 8, ], @@ -2842,7 +2840,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'email' => 'user@@example.com', ], @@ -2857,7 +2855,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'enum' => 'badEnum', ], @@ -2872,7 +2870,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'ip' => '1.1.1.1.1', ], @@ -2887,7 +2885,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'url' => 'example...com', ], @@ -2902,7 +2900,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'range' => 11, ], @@ -2917,7 +2915,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'floatRange' => 2.5, ], @@ -2932,7 +2930,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'probability' => 1.1, ], @@ -2947,7 +2945,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'upperBound' => 11, ], @@ -2962,7 +2960,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'lowerBound' => 3, ], @@ -2977,7 +2975,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => 'unique()', + 'documentId' => 'unique()', 'data' => [ 'birthDay' => '2020-10-10 27:30:10+01:00', ], @@ -3016,7 +3014,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Captain America', 'releaseYear' => 1944, @@ -3146,7 +3144,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'enforceCollectionAndDocumentPermissions', 'documentSecurity' => true, 'permissions' => [ @@ -3188,7 +3186,7 @@ trait DatabasesBase ]), [ 'key' => 'key_attribute', 'type' => 'key', - 'columns' => [$attribute['body']['key']], + 'attributes' => [$attribute['body']['key']], ]); $this->assertEquals(202, $index['headers']['status-code']); @@ -3201,7 +3199,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'attribute' => 'one', ], @@ -3218,7 +3216,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'attribute' => 'one', ], @@ -3235,7 +3233,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'attribute' => 'one', ], @@ -3254,7 +3252,7 @@ trait DatabasesBase // Current user has read permission on the collection so can get any document $this->assertEquals(3, $documentsUser1['body']['total']); - $this->assertCount(3, $documentsUser1['body']['rows']); + $this->assertCount(3, $documentsUser1['body']['documents']); $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], array_merge([ 'content-type' => 'application/json', @@ -3316,7 +3314,7 @@ trait DatabasesBase // Current user has no collection permissions but has read permission for one document $this->assertEquals(1, $documentsUser2['body']['total']); - $this->assertCount(1, $documentsUser2['body']['rows']); + $this->assertCount(1, $documentsUser2['body']['documents']); } public function testEnforceCollectionPermissions() @@ -3339,7 +3337,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'enforceCollectionPermissions', 'permissions' => [ Permission::read(Role::user($user)), @@ -3377,7 +3375,7 @@ trait DatabasesBase ]), [ 'key' => 'key_attribute', 'type' => 'key', - 'columns' => [$attribute['body']['key']], + 'attributes' => [$attribute['body']['key']], ]); $this->assertEquals(202, $index['headers']['status-code']); @@ -3389,7 +3387,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'attribute' => 'one', ], @@ -3406,7 +3404,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'attribute' => 'one', ], @@ -3423,7 +3421,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'attribute' => 'one', ], @@ -3442,7 +3440,7 @@ trait DatabasesBase // Current user has read permission on the collection so can get any document $this->assertEquals(3, $documentsUser1['body']['total']); - $this->assertCount(3, $documentsUser1['body']['rows']); + $this->assertCount(3, $documentsUser1['body']['documents']); $document3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document3['body']['$id'], array_merge([ 'content-type' => 'application/json', @@ -3514,7 +3512,7 @@ trait DatabasesBase // Current user has no collection permissions read access to one document $this->assertEquals(1, $documentsUser2['body']['total']); - $this->assertCount(1, $documentsUser2['body']['rows']); + $this->assertCount(1, $documentsUser2['body']['documents']); } /** @@ -3530,7 +3528,7 @@ trait DatabasesBase ]), [ 'key' => 'unique_title', 'type' => 'unique', - 'columns' => ['title'], + 'attributes' => ['title'], ]); $this->assertEquals(202, $uniqueIndex['headers']['status-code']); @@ -3542,7 +3540,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Captain America', 'releaseYear' => 1944, @@ -3565,7 +3563,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Captain America 5', 'releaseYear' => 1944, @@ -3588,7 +3586,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Captain America', 'releaseYear' => 1944, @@ -3624,7 +3622,7 @@ trait DatabasesBase ]; $document = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/collections/' . $data['moviesId'] . '/documents', $headers, [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Creation Date Test', 'releaseYear' => 2000 @@ -3692,7 +3690,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::create(Role::user(ID::custom($this->getUser()['$id']))), @@ -3729,7 +3727,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Captain America', ], @@ -3803,7 +3801,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Boolean' ]); @@ -3848,7 +3846,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => 'person', + 'collectionId' => 'person', 'name' => 'person', 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), @@ -3866,7 +3864,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => 'library', + 'collectionId' => 'library', 'name' => 'library', 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), @@ -3895,7 +3893,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => 'library', + 'relatedCollectionId' => 'library', 'type' => Database::RELATION_ONE_TO_ONE, 'key' => 'library', 'twoWay' => true, @@ -3930,8 +3928,8 @@ trait DatabasesBase $this->assertEquals(200, $attributes['headers']['status-code']); $this->assertEquals(2, $attributes['body']['total']); - $attributes = $attributes['body']['columns']; - $this->assertEquals('library', $attributes[1]['relatedTable']); + $attributes = $attributes['body']['attributes']; + $this->assertEquals('library', $attributes[1]['relatedCollection']); $this->assertEquals('oneToOne', $attributes[1]['relationType']); $this->assertEquals(true, $attributes[1]['twoWay']); $this->assertEquals('person', $attributes[1]['twoWayKey']); @@ -3958,7 +3956,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'library' => [ '$id' => 'library1', @@ -3982,7 +3980,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'library' => [ 'libraryName' => 'Library 2', @@ -4001,8 +3999,8 @@ trait DatabasesBase $this->assertEquals($databaseId, $person1['body']['$databaseId']); $this->assertEquals($databaseId, $person1['body']['library']['$databaseId']); - $this->assertEquals($person['body']['$id'], $person1['body']['$tableId']); - $this->assertEquals($library['body']['$id'], $person1['body']['library']['$tableId']); + $this->assertEquals($person['body']['$id'], $person1['body']['$collectionId']); + $this->assertEquals($library['body']['$id'], $person1['body']['library']['$collectionId']); $this->assertArrayNotHasKey('$collection', $person1['body']); $this->assertArrayNotHasKey('$collection', $person1['body']['library']); @@ -4020,8 +4018,8 @@ trait DatabasesBase ]); $this->assertEquals(1, $documents['body']['total']); - $this->assertEquals('Library 1', $documents['body']['rows'][0]['library']['libraryName']); - $this->assertArrayHasKey('fullName', $documents['body']['rows'][0]); + $this->assertEquals('Library 1', $documents['body']['documents'][0]['library']['libraryName']); + $this->assertArrayHasKey('fullName', $documents['body']['documents'][0]); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -4069,7 +4067,7 @@ trait DatabasesBase $this->assertEquals(200, $attributes['headers']['status-code']); $this->assertEquals(1, $attributes['body']['total']); - $this->assertEquals('libraryName', $attributes['body']['columns'][0]['key']); + $this->assertEquals('libraryName', $attributes['body']['attributes'][0]['key']); return [ 'databaseId' => $databaseId, @@ -4093,7 +4091,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => 'library', + 'relatedCollectionId' => 'library', 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => true, 'key' => 'libraries', @@ -4108,9 +4106,9 @@ trait DatabasesBase 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertIsArray($libraryAttributesResponse['body']['columns']); + $this->assertIsArray($libraryAttributesResponse['body']['attributes']); $this->assertEquals(2, $libraryAttributesResponse['body']['total']); - $this->assertEquals('person_one_to_many', $libraryAttributesResponse['body']['columns'][1]['key']); + $this->assertEquals('person_one_to_many', $libraryAttributesResponse['body']['attributes'][1]['key']); $libraryCollectionResponse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $libraryCollection, array_merge([ 'content-type' => 'application/json', @@ -4118,8 +4116,8 @@ trait DatabasesBase 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertIsArray($libraryCollectionResponse['body']['columns']); - $this->assertCount(2, $libraryCollectionResponse['body']['columns']); + $this->assertIsArray($libraryCollectionResponse['body']['attributes']); + $this->assertCount(2, $libraryCollectionResponse['body']['attributes']); $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$personCollection}/attributes/libraries", array_merge([ 'content-type' => 'application/json', @@ -4142,7 +4140,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => 'person10', + 'documentId' => 'person10', 'data' => [ 'fullName' => 'Stevie Wonder', 'libraries' => [ @@ -4238,7 +4236,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Albums', 'documentSecurity' => true, 'permissions' => [ @@ -4264,7 +4262,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Artists', 'documentSecurity' => true, 'permissions' => [ @@ -4290,7 +4288,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $artists['body']['$id'], + 'relatedCollectionId' => $artists['body']['$id'], 'type' => Database::RELATION_MANY_TO_ONE, 'twoWay' => true, 'key' => 'artist', @@ -4319,7 +4317,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => 'album1', + 'documentId' => 'album1', 'permissions' => $permissions, 'data' => [ 'name' => 'Album 1', @@ -4382,7 +4380,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Sports', 'documentSecurity' => true, 'permissions' => [ @@ -4408,7 +4406,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Players', 'documentSecurity' => true, 'permissions' => [ @@ -4434,7 +4432,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $players['body']['$id'], + 'relatedCollectionId' => $players['body']['$id'], 'type' => Database::RELATION_MANY_TO_MANY, 'twoWay' => true, 'key' => 'players', @@ -4464,7 +4462,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => 'sport1', + 'documentId' => 'sport1', 'permissions' => $permissions, 'data' => [ 'name' => 'Sport 1', @@ -4542,10 +4540,10 @@ trait DatabasesBase ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(1, count($response['body']['rows'])); - $this->assertEquals('person10', $response['body']['rows'][0]['$id']); - $this->assertEquals('Stevie Wonder', $response['body']['rows'][0]['fullName']); - $this->assertEquals(2, count($response['body']['rows'][0]['libraries'])); + $this->assertEquals(1, count($response['body']['documents'])); + $this->assertEquals('person10', $response['body']['documents'][0]['$id']); + $this->assertEquals('Stevie Wonder', $response['body']['documents'][0]['fullName']); + $this->assertEquals(2, count($response['body']['documents'][0]['libraries'])); $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -4559,11 +4557,11 @@ trait DatabasesBase ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(2, count($response['body']['rows'])); - $this->assertEquals(null, $response['body']['rows'][0]['fullName']); - $this->assertArrayNotHasKey("libraries", $response['body']['rows'][0]); - $this->assertArrayNotHasKey('$databaseId', $response['body']['rows'][0]); - $this->assertArrayNotHasKey('$tableId', $response['body']['rows'][0]); + $this->assertEquals(2, count($response['body']['documents'])); + $this->assertEquals(null, $response['body']['documents'][0]['fullName']); + $this->assertArrayNotHasKey("libraries", $response['body']['documents'][0]); + $this->assertArrayNotHasKey('$databaseId', $response['body']['documents'][0]); + $this->assertArrayNotHasKey('$collectionId', $response['body']['documents'][0]); } /** @@ -4582,9 +4580,9 @@ trait DatabasesBase ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertArrayNotHasKey('libraries', $response['body']['rows'][0]); - $this->assertArrayNotHasKey('$databaseId', $response['body']['rows'][0]); - $this->assertArrayNotHasKey('$tableId', $response['body']['rows'][0]); + $this->assertArrayNotHasKey('libraries', $response['body']['documents'][0]); + $this->assertArrayNotHasKey('$databaseId', $response['body']['documents'][0]); + $this->assertArrayNotHasKey('$collectionId', $response['body']['documents'][0]); $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -4594,11 +4592,11 @@ trait DatabasesBase Query::select(['libraries.*', '$id'])->toString(), ], ]); - $document = $response['body']['rows'][0]; + $document = $response['body']['documents'][0]; $this->assertEquals(200, $response['headers']['status-code']); $this->assertArrayHasKey('libraries', $document); $this->assertArrayNotHasKey('$databaseId', $document); - $this->assertArrayNotHasKey('$tableId', $document); + $this->assertArrayNotHasKey('$collectionId', $document); $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['personCollection'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', @@ -4642,7 +4640,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'USA Presidents', 'documentSecurity' => true, 'permissions' => [ @@ -4684,7 +4682,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'first_name' => 'Donald', 'last_name' => 'Trump', @@ -4699,7 +4697,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'first_name' => 'George', 'last_name' => 'Bush', @@ -4714,7 +4712,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'first_name' => 'Joe', 'last_name' => 'Biden', @@ -4747,7 +4745,7 @@ trait DatabasesBase ); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertCount(2, $documents['body']['rows']); + $this->assertCount(2, $documents['body']['documents']); } /** @@ -4765,7 +4763,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Collection1', 'documentSecurity' => true, 'permissions' => [ @@ -4779,7 +4777,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Collection2', 'documentSecurity' => true, 'permissions' => [ @@ -4816,7 +4814,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection2, + 'relatedCollectionId' => $collection2, 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => true, 'key' => 'collection2' @@ -4828,7 +4826,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'name' => 'Document 1', 'collection2' => [ @@ -4861,7 +4859,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Slow Queries', 'documentSecurity' => true, 'permissions' => [ @@ -4894,9 +4892,9 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ - 'longtext' => file_get_contents(__DIR__ . '/../../../resources/longtext.txt'), + 'longtext' => file_get_contents(__DIR__ . '../../../../../resources/longtext.txt'), ], 'permissions' => [ Permission::read(Role::user($this->getUser()['$id'])), diff --git a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php b/tests/e2e/Services/Databases/Collections/DatabasesConsoleClientTest.php similarity index 95% rename from tests/e2e/Services/Databases/DatabasesConsoleClientTest.php rename to tests/e2e/Services/Databases/Collections/DatabasesConsoleClientTest.php index e9dca1d674..64cade4f9d 100644 --- a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php +++ b/tests/e2e/Services/Databases/Collections/DatabasesConsoleClientTest.php @@ -1,6 +1,6 @@ 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::read(Role::any()), @@ -69,7 +69,7 @@ class DatabasesConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'TvShows', 'permissions' => [ Permission::read(Role::any()), @@ -224,12 +224,12 @@ class DatabasesConsoleClientTest extends Scope ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(11, count($response['body'])); + $this->assertEquals(15, count($response['body'])); $this->assertEquals('24h', $response['body']['range']); - $this->assertIsNumeric($response['body']['rowsTotal']); - $this->assertIsNumeric($response['body']['tablesTotal']); - $this->assertIsArray($response['body']['tables']); - $this->assertIsArray($response['body']['rows']); + $this->assertIsNumeric($response['body']['documentsTotal']); + $this->assertIsNumeric($response['body']['collectionsTotal']); + $this->assertIsArray($response['body']['collections']); + $this->assertIsArray($response['body']['documents']); } @@ -273,8 +273,8 @@ class DatabasesConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(3, count($response['body'])); $this->assertEquals('24h', $response['body']['range']); - $this->assertIsNumeric($response['body']['rowsTotal']); - $this->assertIsArray($response['body']['rows']); + $this->assertIsNumeric($response['body']['documentsTotal']); + $this->assertIsArray($response['body']['documents']); } /** diff --git a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php b/tests/e2e/Services/Databases/Collections/DatabasesCustomClientTest.php similarity index 94% rename from tests/e2e/Services/Databases/DatabasesCustomClientTest.php rename to tests/e2e/Services/Databases/Collections/DatabasesCustomClientTest.php index b192cd04a1..49839f83e1 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php +++ b/tests/e2e/Services/Databases/Collections/DatabasesCustomClientTest.php @@ -1,6 +1,6 @@ $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Movies', 'documentSecurity' => true, 'permissions' => [ @@ -73,7 +73,7 @@ class DatabasesCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Captain America', ], @@ -95,7 +95,7 @@ class DatabasesCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Captain America', ], @@ -138,7 +138,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('permissionCheck'), + 'collectionId' => ID::custom('permissionCheck'), 'name' => 'permissionCheck', 'permissions' => [], 'documentSecurity' => true, @@ -166,7 +166,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => ID::custom('permissionCheckDocument'), + 'documentId' => ID::custom('permissionCheckDocument'), 'data' => [ 'name' => 'AppwriteBeginner', ], @@ -247,7 +247,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'level1', 'documentSecurity' => false, 'permissions' => [ @@ -264,7 +264,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'level2', 'documentSecurity' => false, 'permissions' => [ @@ -283,7 +283,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection2['body']['$id'], + 'relatedCollectionId' => $collection2['body']['$id'], 'type' => 'oneToMany', 'twoWay' => true, 'onDelete' => 'cascade', @@ -309,11 +309,11 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $collection1RelationAttribute = $collection1Attributes['body']['columns'][0]; + $collection1RelationAttribute = $collection1Attributes['body']['attributes'][0]; $this->assertEquals($relation['body']['side'], $collection1RelationAttribute['side']); $this->assertEquals($relation['body']['twoWayKey'], $collection1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedTable'], $collection1RelationAttribute['relatedTable']); + $this->assertEquals($relation['body']['relatedCollection'], $collection1RelationAttribute['relatedCollection']); $this->assertEquals('restrict', $collection1RelationAttribute['onDelete']); } @@ -335,7 +335,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'c1', 'documentSecurity' => false, 'permissions' => [ @@ -351,7 +351,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'c2', 'documentSecurity' => false, 'permissions' => [ @@ -369,7 +369,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection2['body']['$id'], + 'relatedCollectionId' => $collection2['body']['$id'], 'type' => Database::RELATION_ONE_TO_ONE, 'twoWay' => false, 'onDelete' => 'cascade', @@ -387,7 +387,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection2['body']['$id'], + 'relatedCollectionId' => $collection2['body']['$id'], 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => false, 'onDelete' => 'cascade', @@ -406,7 +406,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection2['body']['$id'], + 'relatedCollectionId' => $collection2['body']['$id'], 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => false, 'onDelete' => 'cascade', @@ -424,7 +424,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection2['body']['$id'], + 'relatedCollectionId' => $collection2['body']['$id'], 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => false, 'onDelete' => 'cascade', @@ -442,7 +442,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection2['body']['$id'], + 'relatedCollectionId' => $collection2['body']['$id'], 'type' => Database::RELATION_MANY_TO_MANY, 'twoWay' => true, 'onDelete' => 'setNull', @@ -461,7 +461,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection2['body']['$id'], + 'relatedCollectionId' => $collection2['body']['$id'], 'type' => Database::RELATION_MANY_TO_MANY, 'twoWay' => true, 'onDelete' => 'setNull', @@ -472,7 +472,7 @@ class DatabasesCustomClientTest extends Scope \sleep(2); $this->assertEquals(409, $relation['body']['code']); - $this->assertEquals('Creating more than one "manyToMany" relationship on the same table is currently not permitted.', $relation['body']['message']); + $this->assertEquals('Creating more than one "manyToMany" relationship on the same collection is currently not permitted.', $relation['body']['message']); } public function testUpdateWithoutRelationPermission(): void @@ -495,7 +495,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('collection1'), + 'collectionId' => ID::custom('collection1'), 'name' => ID::custom('collection1'), 'documentSecurity' => false, 'permissions' => [ @@ -511,7 +511,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('collection2'), + 'collectionId' => ID::custom('collection2'), 'name' => ID::custom('collection2'), 'documentSecurity' => false, 'permissions' => [ @@ -524,7 +524,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('collection3'), + 'collectionId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), 'documentSecurity' => false, 'permissions' => [ @@ -539,7 +539,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('collection4'), + 'collectionId' => ID::custom('collection4'), 'name' => ID::custom('collection4'), 'documentSecurity' => false, 'permissions' => [ @@ -552,7 +552,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('collection5'), + 'collectionId' => ID::custom('collection5'), 'name' => ID::custom('collection5'), 'documentSecurity' => false, 'permissions' => [ @@ -568,7 +568,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection2['body']['$id'], + 'relatedCollectionId' => $collection2['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', @@ -581,7 +581,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection3['body']['$id'], + 'relatedCollectionId' => $collection3['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', @@ -594,7 +594,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection4['body']['$id'], + 'relatedCollectionId' => $collection4['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', @@ -607,7 +607,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection5['body']['$id'], + 'relatedCollectionId' => $collection5['body']['$id'], 'type' => 'oneToOne', 'twoWay' => false, 'onDelete' => 'setNull', @@ -681,7 +681,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => ID::custom($collection1['body']['$id']), + 'documentId' => ID::custom($collection1['body']['$id']), 'data' => [ 'Title' => 'Captain America', $collection2['body']['$id'] => [ @@ -709,7 +709,7 @@ class DatabasesCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::custom($collection1['body']['$id']), + 'documentId' => ID::custom($collection1['body']['$id']), 'data' => [ 'Title' => 'Captain America', $collection2['body']['$id'] => [ @@ -739,7 +739,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('collection3'), + 'collectionId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), 'documentSecurity' => false, 'permissions' => [ @@ -814,7 +814,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('collection3'), + 'collectionId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), 'documentSecurity' => false, 'permissions' => [ @@ -830,7 +830,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('collection2'), + 'collectionId' => ID::custom('collection2'), 'name' => ID::custom('collection2'), 'documentSecurity' => false, 'permissions' => [ @@ -847,7 +847,7 @@ class DatabasesCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => ID::custom('collection3Doc1'), + 'documentId' => ID::custom('collection3Doc1'), 'data' => [ 'Rating' => '20' ] diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/Collections/DatabasesCustomServerTest.php similarity index 94% rename from tests/e2e/Services/Databases/DatabasesCustomServerTest.php rename to tests/e2e/Services/Databases/Collections/DatabasesCustomServerTest.php index 874aa5623e..e420681a2e 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/Collections/DatabasesCustomServerTest.php @@ -1,6 +1,6 @@ $this->getProject()['apiKey'] ]), [ 'name' => 'Test 1', - 'tableId' => ID::custom('first'), + 'collectionId' => ID::custom('first'), 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), @@ -374,7 +374,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test 2', - 'tableId' => ID::custom('second'), + 'collectionId' => ID::custom('second'), 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), @@ -390,12 +390,12 @@ class DatabasesCustomServerTest extends Scope ], $this->getHeaders())); $this->assertEquals(2, $collections['body']['total']); - $this->assertEquals($test1['body']['$id'], $collections['body']['tables'][0]['$id']); - $this->assertEquals($test1['body']['enabled'], $collections['body']['tables'][0]['enabled']); - $this->assertEquals($test2['body']['$id'], $collections['body']['tables'][1]['$id']); - $this->assertEquals($test1['body']['enabled'], $collections['body']['tables'][0]['enabled']); + $this->assertEquals($test1['body']['$id'], $collections['body']['collections'][0]['$id']); + $this->assertEquals($test1['body']['enabled'], $collections['body']['collections'][0]['enabled']); + $this->assertEquals($test2['body']['$id'], $collections['body']['collections'][1]['$id']); + $this->assertEquals($test1['body']['enabled'], $collections['body']['collections'][0]['enabled']); - $base = array_reverse($collections['body']['tables']); + $base = array_reverse($collections['body']['collections']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', @@ -407,7 +407,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collections['headers']['status-code']); - $this->assertCount(1, $collections['body']['tables']); + $this->assertCount(1, $collections['body']['collections']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', @@ -419,7 +419,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collections['headers']['status-code']); - $this->assertCount(1, $collections['body']['tables']); + $this->assertCount(1, $collections['body']['collections']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', @@ -431,7 +431,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collections['headers']['status-code']); - $this->assertCount(2, $collections['body']['tables']); + $this->assertCount(2, $collections['body']['collections']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', @@ -443,7 +443,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collections['headers']['status-code']); - $this->assertCount(0, $collections['body']['tables']); + $this->assertCount(0, $collections['body']['collections']); /** * Test for Order @@ -458,8 +458,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(2, $collections['body']['total']); - $this->assertEquals($base[0]['$id'], $collections['body']['tables'][0]['$id']); - $this->assertEquals($base[1]['$id'], $collections['body']['tables'][1]['$id']); + $this->assertEquals($base[0]['$id'], $collections['body']['collections'][0]['$id']); + $this->assertEquals($base[1]['$id'], $collections['body']['collections'][1]['$id']); /** * Test for After @@ -474,24 +474,24 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorAfter(new Document(['$id' => $base['body']['tables'][0]['$id']]))->toString(), + Query::cursorAfter(new Document(['$id' => $base['body']['collections'][0]['$id']]))->toString(), ], ]); - $this->assertCount(1, $collections['body']['tables']); - $this->assertEquals($base['body']['tables'][1]['$id'], $collections['body']['tables'][0]['$id']); + $this->assertCount(1, $collections['body']['collections']); + $this->assertEquals($base['body']['collections'][1]['$id'], $collections['body']['collections'][0]['$id']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorAfter(new Document(['$id' => $base['body']['tables'][1]['$id']]))->toString(), + Query::cursorAfter(new Document(['$id' => $base['body']['collections'][1]['$id']]))->toString(), ], ]); - $this->assertCount(0, $collections['body']['tables']); - $this->assertEmpty($collections['body']['tables']); + $this->assertCount(0, $collections['body']['collections']); + $this->assertEmpty($collections['body']['collections']); /** * Test for Before @@ -506,24 +506,24 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorBefore(new Document(['$id' => $base['body']['tables'][1]['$id']]))->toString(), + Query::cursorBefore(new Document(['$id' => $base['body']['collections'][1]['$id']]))->toString(), ], ]); - $this->assertCount(1, $collections['body']['tables']); - $this->assertEquals($base['body']['tables'][0]['$id'], $collections['body']['tables'][0]['$id']); + $this->assertCount(1, $collections['body']['collections']); + $this->assertEquals($base['body']['collections'][0]['$id'], $collections['body']['collections'][0]['$id']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::cursorBefore(new Document(['$id' => $base['body']['tables'][0]['$id']]))->toString(), + Query::cursorBefore(new Document(['$id' => $base['body']['collections'][0]['$id']]))->toString(), ], ]); - $this->assertCount(0, $collections['body']['tables']); - $this->assertEmpty($collections['body']['tables']); + $this->assertCount(0, $collections['body']['collections']); + $this->assertEmpty($collections['body']['collections']); /** * Test for Search @@ -536,7 +536,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(1, $collections['body']['total']); - $this->assertEquals('first', $collections['body']['tables'][0]['$id']); + $this->assertEquals('first', $collections['body']['collections'][0]['$id']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', @@ -546,8 +546,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(2, $collections['body']['total']); - $this->assertEquals('Test 1', $collections['body']['tables'][0]['name']); - $this->assertEquals('Test 2', $collections['body']['tables'][1]['name']); + $this->assertEquals('Test 1', $collections['body']['collections'][0]['name']); + $this->assertEquals('Test 2', $collections['body']['collections'][1]['name']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', @@ -579,7 +579,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test 1', - 'tableId' => ID::custom('first'), + 'collectionId' => ID::custom('first'), 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), @@ -592,7 +592,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(409, $response['headers']['status-code']); return [ 'databaseId' => $databaseId, - 'tableId' => $test1['body']['$id'], + 'collectionId' => $test1['body']['$id'], ]; } @@ -602,7 +602,7 @@ class DatabasesCustomServerTest extends Scope public function testGetCollection(array $data): void { $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', @@ -622,7 +622,7 @@ class DatabasesCustomServerTest extends Scope public function testUpdateCollection(array $data) { $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $collection = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', @@ -657,7 +657,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Encrypted Actors Data', 'permissions' => [ Permission::read(Role::any()), @@ -719,7 +719,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'firstName' => 'Jonah', 'lastName' => 'Jameson', @@ -767,7 +767,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Actors', 'permissions' => [ Permission::read(Role::any()), @@ -820,7 +820,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'firstName' => 'lorem', 'lastName' => 'ipsum', @@ -840,7 +840,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'key_lastName', 'type' => 'key', - 'columns' => [ + 'attributes' => [ 'lastName', ], ]); @@ -857,11 +857,11 @@ class DatabasesCustomServerTest extends Scope $unneededId = $unneeded['body']['key']; $this->assertEquals(200, $collection['headers']['status-code']); - $this->assertIsArray($collection['body']['columns']); - $this->assertCount(3, $collection['body']['columns']); - $this->assertEquals($collection['body']['columns'][0]['key'], $firstName['body']['key']); - $this->assertEquals($collection['body']['columns'][1]['key'], $lastName['body']['key']); - $this->assertEquals($collection['body']['columns'][2]['key'], $unneeded['body']['key']); + $this->assertIsArray($collection['body']['attributes']); + $this->assertCount(3, $collection['body']['attributes']); + $this->assertEquals($collection['body']['attributes'][0]['key'], $firstName['body']['key']); + $this->assertEquals($collection['body']['attributes'][1]['key'], $lastName['body']['key']); + $this->assertEquals($collection['body']['attributes'][2]['key'], $unneeded['body']['key']); $this->assertCount(1, $collection['body']['indexes']); $this->assertEquals($collection['body']['indexes'][0]['key'], $index['body']['key']); @@ -892,13 +892,13 @@ class DatabasesCustomServerTest extends Scope ]), []); $this->assertEquals(200, $collection['headers']['status-code']); - $this->assertIsArray($collection['body']['columns']); - $this->assertCount(2, $collection['body']['columns']); - $this->assertEquals($collection['body']['columns'][0]['key'], $firstName['body']['key']); - $this->assertEquals($collection['body']['columns'][1]['key'], $lastName['body']['key']); + $this->assertIsArray($collection['body']['attributes']); + $this->assertCount(2, $collection['body']['attributes']); + $this->assertEquals($collection['body']['attributes'][0]['key'], $firstName['body']['key']); + $this->assertEquals($collection['body']['attributes'][1]['key'], $lastName['body']['key']); return [ - 'tableId' => $actors['body']['$id'], + 'collectionId' => $actors['body']['$id'], 'key' => $index['body']['key'], 'databaseId' => $databaseId ]; @@ -910,7 +910,7 @@ class DatabasesCustomServerTest extends Scope public function testDeleteIndex($data): array { $databaseId = $data['databaseId']; - $index = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/indexes/' . $data['key'], array_merge([ + $index = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/indexes/' . $data['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -921,7 +921,7 @@ class DatabasesCustomServerTest extends Scope // Wait for database worker to finish deleting index sleep(2); - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['tableId'], array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['collectionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -938,7 +938,7 @@ class DatabasesCustomServerTest extends Scope public function testDeleteIndexOnDeleteAttribute($data) { $databaseId = $data['databaseId']; - $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/attributes/string', array_merge([ + $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -948,7 +948,7 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/attributes/string', array_merge([ + $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -965,25 +965,25 @@ class DatabasesCustomServerTest extends Scope sleep(2); - $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/indexes', array_merge([ + $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'index1', 'type' => 'key', - 'columns' => ['attribute1', 'attribute2'], + 'attributes' => ['attribute1', 'attribute2'], 'orders' => ['ASC', 'ASC'], ]); - $index2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/indexes', array_merge([ + $index2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'key' => 'index2', 'type' => 'key', - 'columns' => ['attribute2'], + 'attributes' => ['attribute2'], ]); $this->assertEquals(202, $index1['headers']['status-code']); @@ -994,7 +994,7 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Expected behavior: deleting attribute2 will cause index2 to be dropped, and index1 rebuilt with a single key - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/attributes/' . $attribute2['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/' . $attribute2['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1005,7 +1005,7 @@ class DatabasesCustomServerTest extends Scope // wait for database worker to complete sleep(2); - $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['tableId'], array_merge([ + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['collectionId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1015,12 +1015,12 @@ class DatabasesCustomServerTest extends Scope $this->assertIsArray($collection['body']['indexes']); $this->assertCount(1, $collection['body']['indexes']); $this->assertEquals($index1['body']['key'], $collection['body']['indexes'][0]['key']); - $this->assertIsArray($collection['body']['indexes'][0]['columns']); - $this->assertCount(1, $collection['body']['indexes'][0]['columns']); - $this->assertEquals($attribute1['body']['key'], $collection['body']['indexes'][0]['columns'][0]); + $this->assertIsArray($collection['body']['indexes'][0]['attributes']); + $this->assertCount(1, $collection['body']['indexes'][0]['attributes']); + $this->assertEquals($attribute1['body']['key'], $collection['body']['indexes'][0]['attributes'][0]); // Delete attribute - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['tableId'] . '/attributes/' . $attribute1['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/' . $attribute1['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1050,7 +1050,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'TestCleanupDuplicateIndexOnDeleteAttribute', 'permissions' => [ Permission::read(Role::any()), @@ -1100,7 +1100,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'index1', 'type' => 'key', - 'columns' => ['attribute1', 'attribute2'], + 'attributes' => ['attribute1', 'attribute2'], 'orders' => ['ASC', 'ASC'], ]); @@ -1111,7 +1111,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'index2', 'type' => 'key', - 'columns' => ['attribute2'], + 'attributes' => ['attribute2'], ]); $this->assertEquals(202, $index1['headers']['status-code']); @@ -1143,9 +1143,9 @@ class DatabasesCustomServerTest extends Scope $this->assertIsArray($collection['body']['indexes']); $this->assertCount(1, $collection['body']['indexes']); $this->assertEquals($index2['body']['key'], $collection['body']['indexes'][0]['key']); - $this->assertIsArray($collection['body']['indexes'][0]['columns']); - $this->assertCount(1, $collection['body']['indexes'][0]['columns']); - $this->assertEquals($attribute2['body']['key'], $collection['body']['indexes'][0]['columns'][0]); + $this->assertIsArray($collection['body']['indexes'][0]['attributes']); + $this->assertCount(1, $collection['body']['indexes'][0]['attributes']); + $this->assertEquals($attribute2['body']['key'], $collection['body']['indexes'][0]['attributes'][0]); // Delete attribute $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $attribute2['body']['key'], array_merge([ @@ -1163,14 +1163,14 @@ class DatabasesCustomServerTest extends Scope public function testDeleteCollection($data) { $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; // Add Documents to the collection $document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'firstName' => 'Tom', 'lastName' => 'Holland', @@ -1186,7 +1186,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'firstName' => 'Samuel', 'lastName' => 'Jackson', @@ -1249,7 +1249,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Collection1', 'documentSecurity' => false, 'permissions' => [], @@ -1260,7 +1260,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Collection2', 'documentSecurity' => false, 'permissions' => [], @@ -1274,7 +1274,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'relatedTableId' => $collection2, + 'relatedCollectionId' => $collection2, 'type' => Database::RELATION_MANY_TO_ONE, 'twoWay' => false, 'key' => 'collection2' @@ -1318,7 +1318,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('attributeRowWidthLimit'), + 'collectionId' => ID::custom('attributeRowWidthLimit'), 'name' => 'attributeRowWidthLimit', 'permissions' => [ Permission::read(Role::any()), @@ -1384,7 +1384,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('testLimitException'), + 'collectionId' => ID::custom('testLimitException'), 'name' => 'testLimitException', 'permissions' => [ Permission::read(Role::any()), @@ -1426,12 +1426,12 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $collection['headers']['status-code']); $this->assertEquals($collection['body']['name'], 'testLimitException'); - $this->assertIsArray($collection['body']['columns']); + $this->assertIsArray($collection['body']['attributes']); $this->assertIsArray($collection['body']['indexes']); - $this->assertCount(64, $collection['body']['columns']); + $this->assertCount(64, $collection['body']['attributes']); $this->assertCount(0, $collection['body']['indexes']); - foreach ($collection['body']['columns'] as $attribute) { + foreach ($collection['body']['attributes'] as $attribute) { $this->assertEquals('available', $attribute['status'], 'attribute: ' . $attribute['key']); } @@ -1446,7 +1446,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => "key_attribute{$i}", 'type' => 'key', - 'columns' => ["attribute{$i}"], + 'attributes' => ["attribute{$i}"], ]); $this->assertEquals(202, $index['headers']['status-code']); @@ -1463,9 +1463,9 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $collection['headers']['status-code']); $this->assertEquals($collection['body']['name'], 'testLimitException'); - $this->assertIsArray($collection['body']['columns']); + $this->assertIsArray($collection['body']['attributes']); $this->assertIsArray($collection['body']['indexes']); - $this->assertCount(64, $collection['body']['columns']); + $this->assertCount(64, $collection['body']['attributes']); $this->assertCount(58, $collection['body']['indexes']); $tooMany = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ @@ -1475,7 +1475,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'tooMany', 'type' => 'key', - 'columns' => ['attribute61'], + 'attributes' => ['attribute61'], ]); $this->assertEquals(400, $tooMany['headers']['status-code']); @@ -1508,7 +1508,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('updateAttributes'), + 'collectionId' => ID::custom('updateAttributes'), 'name' => 'updateAttributes' ]); @@ -1642,7 +1642,7 @@ class DatabasesCustomServerTest extends Scope return [ 'databaseId' => $databaseId, - 'tableId' => $collectionId + 'collectionId' => $collectionId ]; } @@ -1653,7 +1653,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'string'; $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string/' . $key, array_merge([ 'content-type' => 'application/json', @@ -1681,7 +1681,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('lorem', $attribute['default']); @@ -1785,7 +1785,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -1795,7 +1795,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'email'; $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/email/' . $key, array_merge([ 'content-type' => 'application/json', @@ -1823,7 +1823,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('torsten@appwrite.io', $attribute['default']); @@ -1928,7 +1928,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -1938,7 +1938,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'ip'; $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/ip/' . $key, array_merge([ 'content-type' => 'application/json', @@ -1966,7 +1966,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('127.0.0.1', $attribute['default']); @@ -2070,7 +2070,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -2080,7 +2080,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'url'; $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/url/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2108,7 +2108,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('http://appwrite.io', $attribute['default']); @@ -2212,7 +2212,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -2222,7 +2222,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'integer'; $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2254,7 +2254,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals(123, $attribute['default']); @@ -2430,7 +2430,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2444,7 +2444,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2458,7 +2458,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ @@ -2473,7 +2473,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); } /** @@ -2483,7 +2483,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'float'; $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2515,7 +2515,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals(123.456, $attribute['default']); @@ -2691,7 +2691,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2705,7 +2705,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2719,7 +2719,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ @@ -2734,7 +2734,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); } /** @@ -2744,7 +2744,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'boolean'; $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2772,7 +2772,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals(true, $attribute['default']); @@ -2876,7 +2876,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -2886,7 +2886,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'datetime'; $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2914,7 +2914,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('1975-06-12 14:12:55+02:00', $attribute['default']); @@ -3018,7 +3018,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -3028,7 +3028,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'enum'; $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', @@ -3061,7 +3061,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $attribute = array_values(array_filter($new['body']['attributes'], fn (array $a) => $a['key'] === $key))[0] ?? null; $this->assertNotNull($attribute); $this->assertFalse($attribute['required']); $this->assertEquals('lorem', $attribute['default']); @@ -3133,7 +3133,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', @@ -3146,7 +3146,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_VALUE_INVALID, $update['body']['type']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/enum/' . $key, array_merge([ 'content-type' => 'application/json', @@ -3234,7 +3234,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_DEFAULT_UNSUPPORTED, $update['body']['type']); } /** @@ -3244,7 +3244,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'string'; $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $document = $this->client->call( Client::METHOD_POST, @@ -3255,7 +3255,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => 'unique()', + 'documentId' => 'unique()', 'data' => [ 'string' => 'string' ], @@ -3287,7 +3287,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => 'unique()', + 'documentId' => 'unique()', 'data' => [ 'string' => str_repeat('a', 2048) ], @@ -3324,7 +3324,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $attribute['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_INVALID_RESIZE, $attribute['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_INVALID_RESIZE, $attribute['body']['type']); // original documents to original size, remove new document $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document['body']['$id'], array_merge([ @@ -3373,7 +3373,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => 'unique()', + 'documentId' => 'unique()', 'data' => [ 'string' => str_repeat('a', 10) ], @@ -3408,7 +3408,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => 'unique()', + 'documentId' => 'unique()', 'data' => [ 'string' => str_repeat('a', 11) ], @@ -3417,7 +3417,7 @@ class DatabasesCustomServerTest extends Scope ); $this->assertEquals(400, $newDoc['headers']['status-code']); - $this->assertEquals(AppwriteException::ROW_INVALID_STRUCTURE, $newDoc['body']['type']); + $this->assertEquals(AppwriteException::DOCUMENT_INVALID_STRUCTURE, $newDoc['body']['type']); } /** @@ -3426,7 +3426,7 @@ class DatabasesCustomServerTest extends Scope public function testAttributeUpdateNotFound(array $data) { $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $attributes = [ 'string' => [ @@ -3491,7 +3491,7 @@ class DatabasesCustomServerTest extends Scope ]), $payload); $this->assertEquals(404, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::TABLE_NOT_FOUND, $update['body']['type']); + $this->assertEquals(AppwriteException::COLLECTION_NOT_FOUND, $update['body']['type']); /** * Check if Attribute exists @@ -3503,7 +3503,7 @@ class DatabasesCustomServerTest extends Scope ]), $payload); $this->assertEquals(404, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_NOT_FOUND, $update['body']['type']); + $this->assertEquals(AppwriteException::ATTRIBUTE_NOT_FOUND, $update['body']['type']); } } @@ -3514,7 +3514,7 @@ class DatabasesCustomServerTest extends Scope { $key = 'string'; $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; // Create document to test against $document = $this->client->call( @@ -3526,7 +3526,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => 'unique()', + 'documentId' => 'unique()', 'data' => [ 'string' => 'string' ], @@ -3578,7 +3578,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => 'unique()', + 'documentId' => 'unique()', 'data' => [ 'new_string' => 'string' ], @@ -3600,7 +3600,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => 'unique()', + 'documentId' => 'unique()', 'data' => [ 'string' => 'string' ], @@ -3630,7 +3630,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => 'collection1', + 'collectionId' => 'collection1', 'name' => 'level1', 'documentSecurity' => false, 'permissions' => [ @@ -3646,7 +3646,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => 'collection2', + 'collectionId' => 'collection2', 'name' => 'level2', 'documentSecurity' => false, 'permissions' => [ @@ -3684,7 +3684,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection2Id, + 'relatedCollectionId' => $collection2Id, 'type' => 'oneToMany', 'twoWay' => true, 'onDelete' => 'cascade', @@ -3700,11 +3700,11 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $collection1RelationAttribute = $collection1Attributes['body']['columns'][0]; + $collection1RelationAttribute = $collection1Attributes['body']['attributes'][0]; $this->assertEquals($relation['body']['side'], $collection1RelationAttribute['side']); $this->assertEquals($relation['body']['twoWayKey'], $collection1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedTable'], $collection1RelationAttribute['relatedTable']); + $this->assertEquals($relation['body']['relatedCollection'], $collection1RelationAttribute['relatedCollection']); // Create a document for checking later $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1Id . '/documents', array_merge([ @@ -3712,7 +3712,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => 'unique()', + 'documentId' => 'unique()', 'data' => [ 'level2' => [[ '$id' => 'unique()', @@ -3764,8 +3764,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection1Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection1Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $collection1Attributes['body']['columns'][0]['key']); + $this->assertEquals(1, count($collection1Attributes['body']['attributes'])); + $this->assertEquals('new_level_2', $collection1Attributes['body']['attributes'][0]['key']); // Check if attribute was renamed on the child's side $collection2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection2Id, [ @@ -3775,8 +3775,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection2Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection2Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $collection2Attributes['body']['columns'][0]['twoWayKey']); + $this->assertEquals(1, count($collection2Attributes['body']['attributes'])); + $this->assertEquals('new_level_2', $collection2Attributes['body']['attributes'][0]['twoWayKey']); $this->cleanupRelationshipCollection(); } @@ -3794,7 +3794,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection2Id, + 'relatedCollectionId' => $collection2Id, 'type' => 'oneToOne', 'twoWay' => true, 'onDelete' => 'cascade', @@ -3810,11 +3810,11 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $collection1RelationAttribute = $collection1Attributes['body']['columns'][0]; + $collection1RelationAttribute = $collection1Attributes['body']['attributes'][0]; $this->assertEquals($relation['body']['side'], $collection1RelationAttribute['side']); $this->assertEquals($relation['body']['twoWayKey'], $collection1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedTable'], $collection1RelationAttribute['relatedTable']); + $this->assertEquals($relation['body']['relatedCollection'], $collection1RelationAttribute['relatedCollection']); // Create a document for checking later $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1Id . '/documents', array_merge([ @@ -3822,7 +3822,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => 'unique()', + 'documentId' => 'unique()', 'data' => [ 'level2' => [ '$id' => 'unique()', @@ -3874,8 +3874,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection1Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection1Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $collection1Attributes['body']['columns'][0]['key']); + $this->assertEquals(1, count($collection1Attributes['body']['attributes'])); + $this->assertEquals('new_level_2', $collection1Attributes['body']['attributes'][0]['key']); // Check if attribute was renamed on the child's side $collection2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection2Id, [ @@ -3885,8 +3885,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection2Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection2Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $collection2Attributes['body']['columns'][0]['twoWayKey']); + $this->assertEquals(1, count($collection2Attributes['body']['attributes'])); + $this->assertEquals('new_level_2', $collection2Attributes['body']['attributes'][0]['twoWayKey']); $this->cleanupRelationshipCollection(); } @@ -3904,7 +3904,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection2Id, + 'relatedCollectionId' => $collection2Id, 'type' => 'manyToOne', 'twoWay' => true, 'onDelete' => 'cascade', @@ -3920,11 +3920,11 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $collection1RelationAttribute = $collection1Attributes['body']['columns'][0]; + $collection1RelationAttribute = $collection1Attributes['body']['attributes'][0]; $this->assertEquals($relation['body']['side'], $collection1RelationAttribute['side']); $this->assertEquals($relation['body']['twoWayKey'], $collection1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedTable'], $collection1RelationAttribute['relatedTable']); + $this->assertEquals($relation['body']['relatedCollection'], $collection1RelationAttribute['relatedCollection']); // Create a document for checking later $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1Id . '/documents', array_merge([ @@ -3932,7 +3932,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => 'unique()', + 'documentId' => 'unique()', 'data' => [ 'level2' => [ '$id' => 'unique()', @@ -3984,8 +3984,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection1Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection1Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $collection1Attributes['body']['columns'][0]['key']); + $this->assertEquals(1, count($collection1Attributes['body']['attributes'])); + $this->assertEquals('new_level_2', $collection1Attributes['body']['attributes'][0]['key']); // Check if attribute was renamed on the child's side $collection2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection2Id, [ @@ -3995,8 +3995,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection2Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection2Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $collection2Attributes['body']['columns'][0]['twoWayKey']); + $this->assertEquals(1, count($collection2Attributes['body']['attributes'])); + $this->assertEquals('new_level_2', $collection2Attributes['body']['attributes'][0]['twoWayKey']); $this->cleanupRelationshipCollection(); } @@ -4014,7 +4014,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedTableId' => $collection2Id, + 'relatedCollectionId' => $collection2Id, 'type' => 'manyToOne', 'twoWay' => true, 'onDelete' => 'cascade', @@ -4030,11 +4030,11 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $collection1RelationAttribute = $collection1Attributes['body']['columns'][0]; + $collection1RelationAttribute = $collection1Attributes['body']['attributes'][0]; $this->assertEquals($relation['body']['side'], $collection1RelationAttribute['side']); $this->assertEquals($relation['body']['twoWayKey'], $collection1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedTable'], $collection1RelationAttribute['relatedTable']); + $this->assertEquals($relation['body']['relatedCollection'], $collection1RelationAttribute['relatedCollection']); // Create a document for checking later $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1Id . '/documents', array_merge([ @@ -4042,7 +4042,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'rowId' => 'unique()', + 'documentId' => 'unique()', 'data' => [ 'level2' => [ '$id' => 'unique()', @@ -4094,8 +4094,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection1Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection1Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $collection1Attributes['body']['columns'][0]['key']); + $this->assertEquals(1, count($collection1Attributes['body']['attributes'])); + $this->assertEquals('new_level_2', $collection1Attributes['body']['attributes'][0]['key']); // Check if attribute was renamed on the child's side $collection2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection2Id, [ @@ -4105,8 +4105,8 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(200, $collection2Attributes['headers']['status-code']); - $this->assertEquals(1, count($collection2Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $collection2Attributes['body']['columns'][0]['twoWayKey']); + $this->assertEquals(1, count($collection2Attributes['body']['attributes'])); + $this->assertEquals('new_level_2', $collection2Attributes['body']['attributes'][0]['twoWayKey']); $this->cleanupRelationshipCollection(); } diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/Collections/DatabasesPermissionsGuestTest.php similarity index 95% rename from tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php rename to tests/e2e/Services/Databases/Collections/DatabasesPermissionsGuestTest.php index 64413c2fab..d05c944391 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/Collections/DatabasesPermissionsGuestTest.php @@ -1,6 +1,6 @@ client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::read(Role::any()), @@ -42,7 +42,7 @@ class DatabasesPermissionsGuestTest extends Scope ], ]); $privateMovies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [], 'documentSecurity' => true, @@ -94,14 +94,14 @@ class DatabasesPermissionsGuestTest extends Scope $databaseId = $data['databaseId']; $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $publicCollectionId . '/documents', $this->getServerHeader(), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], 'permissions' => $permissions, ]); $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents', $this->getServerHeader(), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], @@ -124,11 +124,11 @@ class DatabasesPermissionsGuestTest extends Scope ]); $this->assertEquals(1, $publicDocuments['body']['total']); - $this->assertEquals($permissions, $publicDocuments['body']['rows'][0]['$permissions']); + $this->assertEquals($permissions, $publicDocuments['body']['documents'][0]['$permissions']); if (\in_array(Permission::read(Role::any()), $permissions)) { $this->assertEquals(1, $privateDocuments['body']['total']); - $this->assertEquals($permissions, $privateDocuments['body']['rows'][0]['$permissions']); + $this->assertEquals($permissions, $privateDocuments['body']['documents'][0]['$permissions']); } else { $this->assertEquals(0, $privateDocuments['body']['total']); } @@ -152,7 +152,7 @@ class DatabasesPermissionsGuestTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ] @@ -165,7 +165,7 @@ class DatabasesPermissionsGuestTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], @@ -175,7 +175,7 @@ class DatabasesPermissionsGuestTest extends Scope // Create a document in private collection with API key so we can test that update and delete are also not allowed $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $privateCollectionId . '/documents', $this->getServerHeader(), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], @@ -241,7 +241,7 @@ class DatabasesPermissionsGuestTest extends Scope $databaseId = $database['body']['$id']; $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::create(Role::any()), @@ -263,7 +263,7 @@ class DatabasesPermissionsGuestTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Thor: Ragnarok', ], diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php b/tests/e2e/Services/Databases/Collections/DatabasesPermissionsMemberTest.php similarity index 96% rename from tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php rename to tests/e2e/Services/Databases/Collections/DatabasesPermissionsMemberTest.php index 2b959344fe..e8065501fe 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php +++ b/tests/e2e/Services/Databases/Collections/DatabasesPermissionsMemberTest.php @@ -1,6 +1,6 @@ client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::read(Role::any()), @@ -146,7 +146,7 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(202, $response['headers']['status-code']); $private = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Private Movies', 'permissions' => [ Permission::read(Role::users()), @@ -167,7 +167,7 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(202, $response['headers']['status-code']); $doconly = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', $this->getServerHeader(), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Document Only Movies', 'permissions' => [], 'documentSecurity' => true, @@ -186,7 +186,7 @@ class DatabasesPermissionsMemberTest extends Scope return [ 'users' => $this->users, - 'tables' => $this->collections, + 'collections' => $this->collections, 'databaseId' => $databaseId ]; } @@ -199,11 +199,11 @@ class DatabasesPermissionsMemberTest extends Scope public function testReadDocuments($permissions, $anyCount, $usersCount, $docOnlyCount, $data) { $users = $data['users']; - $collections = $data['tables']; + $collections = $data['collections']; $databaseId = $data['databaseId']; $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['public'] . '/documents', $this->getServerHeader(), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], @@ -212,7 +212,7 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['private'] . '/documents', $this->getServerHeader(), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], @@ -221,7 +221,7 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collections['doconly'] . '/documents', $this->getServerHeader(), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsScope.php b/tests/e2e/Services/Databases/Collections/DatabasesPermissionsScope.php similarity index 98% rename from tests/e2e/Services/Databases/DatabasesPermissionsScope.php rename to tests/e2e/Services/Databases/Collections/DatabasesPermissionsScope.php index 0042d253ac..9d46dda5c6 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsScope.php +++ b/tests/e2e/Services/Databases/Collections/DatabasesPermissionsScope.php @@ -1,6 +1,6 @@ assertEquals(201, $db['headers']['status-code']); $collection1 = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections', $this->getServerHeader(), [ - 'tableId' => ID::custom('collection1'), + 'collectionId' => ID::custom('collection1'), 'name' => 'Collection 1', 'permissions' => [ Permission::read(Role::team($teams['team1']['$id'])), @@ -64,7 +64,7 @@ class DatabasesPermissionsTeamTest extends Scope ]); $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections', $this->getServerHeader(), [ - 'tableId' => ID::custom('collection2'), + 'collectionId' => ID::custom('collection2'), 'name' => 'Collection 2', 'permissions' => [ Permission::read(Role::team($teams['team2']['$id'])), @@ -141,7 +141,7 @@ class DatabasesPermissionsTeamTest extends Scope $this->createCollections($this->teams); $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $this->collections['collection1'] . '/documents', $this->getServerHeader(), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], @@ -149,7 +149,7 @@ class DatabasesPermissionsTeamTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/collections/' . $this->collections['collection2'] . '/documents', $this->getServerHeader(), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Ipsum', ], @@ -174,7 +174,7 @@ class DatabasesPermissionsTeamTest extends Scope ]); if ($success) { - $this->assertCount(1, $documents['body']['rows']); + $this->assertCount(1, $documents['body']['documents']); } else { $this->assertEquals(401, $documents['headers']['status-code']); } @@ -192,7 +192,7 @@ class DatabasesPermissionsTeamTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users[$user]['session'], ], [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'title' => 'Ipsum', ], From 2d74765ba0fd68026c73e38ac1505bd728480a15 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 8 May 2025 20:00:01 +0530 Subject: [PATCH 096/343] update: fix exception. --- .github/workflows/tests.yml | 4 ++-- .../Http/Databases/Collections/Attributes/Action.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a7fc1cf0c6..4775272185 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -145,7 +145,7 @@ jobs: Account, Avatars, Console, - Databases, + Databases/Collections, Functions, FunctionsSchedule, GraphQL, @@ -213,7 +213,7 @@ jobs: Account, Avatars, Console, - Databases, + Databases/Collections, Functions, FunctionsSchedule, GraphQL, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index fcb9bcc2df..be6e3d1ff7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -494,7 +494,7 @@ abstract class Action extends UtopiaAction } if (!is_null($default) && !$validator->isValid($default)) { - throw new Exception($this->getTypeInvalidException(), $validator->getDescription()); + throw new Exception($this->getInvalidValueException(), $validator->getDescription()); } $options = [ From 0ecd97d027cb03bb8cb0bd059abecc54df182cf4 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 09:33:52 +0530 Subject: [PATCH 097/343] fix: wrong param. --- .../Http/Databases/Tables/Columns/Relationship/Create.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php index 2e338ae037..be5da989af 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php @@ -80,7 +80,7 @@ class Create extends RelationshipCreate ->inject('queueForDatabase') ->inject('queueForEvents') ->callback(function (string $databaseId, string $tableId, string $relatedTableId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $relatedTableId, $type, $twoWayKey, $key, $twoWayKey, $onDelete, $response, $dbForProject, $queueForDatabase, $queueForEvents); + parent::action($databaseId, $tableId, $relatedTableId, $type, $twoWay, $key, $twoWayKey, $onDelete, $response, $dbForProject, $queueForDatabase, $queueForEvents); }); } } From ef30e827c75a4c1885a4dbc08af04005e5294ca1 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 09:52:04 +0530 Subject: [PATCH 098/343] misc: changes to the databases worker. --- .../Modules/Databases/Workers/Databases.php | 293 +++++++++--------- 1 file changed, 146 insertions(+), 147 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php index 2a6d1f1f28..8711d28d2c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php +++ b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php @@ -60,8 +60,8 @@ class Databases extends Action } $type = $payload['type']; - $row = new Document($payload['row'] ?? $payload['document'] ?? []); - $table = new Document($payload['table'] ?? $payload['collection'] ?? []); + $document = new Document($payload['row'] ?? $payload['document'] ?? []); + $collection = new Document($payload['table'] ?? $payload['collection'] ?? []); $database = new Document($payload['database'] ?? []); $log->addTag('projectId', $project->getId()); @@ -74,20 +74,20 @@ class Databases extends Action $log->addTag('databaseId', $database->getId()); match (\strval($type)) { - DATABASE_TYPE_DELETE_DATABASE => $this->deleteDatabase($database, $project, $dbForProject), - DATABASE_TYPE_DELETE_COLLECTION => $this->deleteTable($database, $table, $project, $dbForProject), - DATABASE_TYPE_CREATE_ATTRIBUTE => $this->createColumn($database, $table, $row, $project, $dbForPlatform, $dbForProject, $queueForRealtime), - DATABASE_TYPE_DELETE_ATTRIBUTE => $this->deleteColumn($database, $table, $row, $project, $dbForPlatform, $dbForProject, $queueForRealtime), - DATABASE_TYPE_CREATE_INDEX => $this->createIndex($database, $table, $row, $project, $dbForPlatform, $dbForProject, $queueForRealtime), - DATABASE_TYPE_DELETE_INDEX => $this->deleteIndex($database, $table, $row, $project, $dbForPlatform, $dbForProject, $queueForRealtime), + DATABASE_TYPE_DELETE_DATABASE => $this->deleteDatabase($database, $dbForProject), + DATABASE_TYPE_DELETE_COLLECTION => $this->deleteCollection($database, $collection, $dbForProject), + DATABASE_TYPE_CREATE_ATTRIBUTE => $this->createAttribute($database, $collection, $document, $project, $dbForPlatform, $dbForProject, $queueForRealtime), + DATABASE_TYPE_DELETE_ATTRIBUTE => $this->deleteAttribute($database, $collection, $document, $project, $dbForPlatform, $dbForProject, $queueForRealtime), + DATABASE_TYPE_CREATE_INDEX => $this->createIndex($database, $collection, $document, $project, $dbForPlatform, $dbForProject, $queueForRealtime), + DATABASE_TYPE_DELETE_INDEX => $this->deleteIndex($database, $collection, $document, $project, $dbForPlatform, $dbForProject, $queueForRealtime), default => throw new Exception('No database operation for type: ' . \strval($type)), }; } /** * @param Document $database - * @param Document $table - * @param Document $column + * @param Document $collection + * @param Document $attribute * @param Document $project * @param Database $dbForPlatform * @param Database $dbForProject @@ -98,20 +98,20 @@ class Databases extends Action * @throws \Exception * @throws \Throwable */ - private function createColumn( + private function createAttribute( Document $database, - Document $table, - Document $column, + Document $collection, + Document $attribute, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime ): void { - if ($table->isEmpty()) { - throw new Exception('Missing table'); + if ($collection->isEmpty()) { + throw new Exception('Missing collection/table'); } - if ($column->isEmpty()) { - throw new Exception('Missing column'); + if ($attribute->isEmpty()) { + throw new Exception('Missing attribute/column'); } $projectId = $project->getId(); @@ -123,42 +123,42 @@ class Databases extends Action * TODO @christyjacob4 verify if this is still the case * Fetch attribute from the database, since with Resque float values are loosing information. */ - $column = $dbForProject->getDocument('attributes', $column->getId()); + $attribute = $dbForProject->getDocument('attributes', $attribute->getId()); - if ($column->isEmpty()) { + if ($attribute->isEmpty()) { // Attribute was deleted before job was processed return; } - $tableId = $table->getId(); - $key = $column->getAttribute('key', ''); - $type = $column->getAttribute('type', ''); - $size = $column->getAttribute('size', 0); - $required = $column->getAttribute('required', false); - $default = $column->getAttribute('default', null); - $signed = $column->getAttribute('signed', true); - $array = $column->getAttribute('array', false); - $format = $column->getAttribute('format', ''); - $formatOptions = $column->getAttribute('formatOptions', []); - $filters = $column->getAttribute('filters', []); - $options = $column->getAttribute('options', []); + $collectionId = $collection->getId(); + $key = $attribute->getAttribute('key', ''); + $type = $attribute->getAttribute('type', ''); + $size = $attribute->getAttribute('size', 0); + $required = $attribute->getAttribute('required', false); + $default = $attribute->getAttribute('default', null); + $signed = $attribute->getAttribute('signed', true); + $array = $attribute->getAttribute('array', false); + $format = $attribute->getAttribute('format', ''); + $formatOptions = $attribute->getAttribute('formatOptions', []); + $filters = $attribute->getAttribute('filters', []); + $options = $attribute->getAttribute('options', []); $project = $dbForPlatform->getDocument('projects', $projectId); - $relatedColumn = new Document(); - $relatedTable = new Document(); + $relatedAttribute = new Document(); + $relatedCollection = new Document(); try { switch ($type) { case Database::VAR_RELATIONSHIP: - $relatedTable = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); - if ($relatedTable->isEmpty()) { - throw new DatabaseException('Table not found'); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + if ($relatedCollection->isEmpty()) { + throw new DatabaseException('Collection/Table not found'); } if ( !$dbForProject->createRelationship( - collection: 'database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), - relatedCollection: 'database_' . $database->getInternalId() . '_collection_' . $relatedTable->getInternalId(), + collection: 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + relatedCollection: 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), type: $options['relationType'], twoWay: $options['twoWay'], id: $key, @@ -166,61 +166,61 @@ class Databases extends Action onDelete: $options['onDelete'], ) ) { - throw new DatabaseException('Failed to create Column'); + throw new DatabaseException('Failed to create attribute/column'); } if ($options['twoWay']) { - $relatedColumn = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $options['twoWayKey']); - $dbForProject->updateDocument('attributes', $relatedColumn->getId(), $relatedColumn->setAttribute('status', 'available')); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'available')); } break; default: - if (!$dbForProject->createAttribute('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { - throw new Exception('Failed to create Column'); + if (!$dbForProject->createAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { + throw new Exception('Failed to create attribute/column'); } } - $dbForProject->updateDocument('attributes', $column->getId(), $column->setAttribute('status', 'available')); + $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'available')); } catch (\Throwable $e) { Console::error($e->getMessage()); if ($e instanceof DatabaseException) { - $column->setAttribute('error', $e->getMessage()); - if (! $relatedColumn->isEmpty()) { - $relatedColumn->setAttribute('error', $e->getMessage()); + $attribute->setAttribute('error', $e->getMessage()); + if (! $relatedAttribute->isEmpty()) { + $relatedAttribute->setAttribute('error', $e->getMessage()); } } $dbForProject->updateDocument( 'attributes', - $column->getId(), - $column->setAttribute('status', 'failed') + $attribute->getId(), + $attribute->setAttribute('status', 'failed') ); - if (! $relatedColumn->isEmpty()) { + if (! $relatedAttribute->isEmpty()) { $dbForProject->updateDocument( 'attributes', - $relatedColumn->getId(), - $relatedColumn->setAttribute('status', 'failed') + $relatedAttribute->getId(), + $relatedAttribute->setAttribute('status', 'failed') ); } throw $e; } finally { - $this->trigger($database, $table, $project, $events, $queueForRealtime, $column); + $this->trigger($database, $collection, $project, $events, $queueForRealtime, $attribute); - if (! $relatedTable->isEmpty()) { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedTable->getId()); + if (! $relatedCollection->isEmpty()) { + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $tableId); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } } /** * @param Document $database - * @param Document $table - * @param Document $column + * @param Document $collection + * @param Document $attribute * @param Document $project * @param Database $dbForPlatform * @param Database $dbForProject @@ -231,13 +231,13 @@ class Databases extends Action * @throws \Exception * @throws \Throwable **/ - private function deleteColumn(Document $database, Document $table, Document $column, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void + private function deleteAttribute(Document $database, Document $collection, Document $attribute, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void { - if ($table->isEmpty()) { - throw new Exception('Missing collection'); + if ($collection->isEmpty()) { + throw new Exception('Missing collection/table'); } - if ($column->isEmpty()) { - throw new Exception('Missing attribute'); + if ($attribute->isEmpty()) { + throw new Exception('Missing attribute/column'); } $projectId = $project->getId(); @@ -245,13 +245,13 @@ class Databases extends Action 'databases.[databaseId].tables.[tableId].columns.[columnId].delete', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].delete', ]; - $tableId = $table->getId(); - $key = $column->getAttribute('key', ''); - $type = $column->getAttribute('type', ''); + $collectionId = $collection->getId(); + $key = $attribute->getAttribute('key', ''); + $type = $attribute->getAttribute('type', ''); $project = $dbForPlatform->getDocument('projects', $projectId); - $options = $column->getAttribute('options', []); - $relatedColumn = new Document(); - $relatedTable = new Document(); + $options = $attribute->getAttribute('options', []); + $relatedAttribute = new Document(); + $relatedCollection = new Document(); // possible states at this point: // - available: should not land in queue; controller flips these to 'deleting' // - processing: hasn't finished creating @@ -263,89 +263,89 @@ class Databases extends Action try { if ($type === Database::VAR_RELATIONSHIP) { if ($options['twoWay']) { - $relatedTable = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); - if ($relatedTable->isEmpty()) { - throw new DatabaseException('Table not found'); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + if ($relatedCollection->isEmpty()) { + throw new DatabaseException('Collection/Table not found'); } - $relatedColumn = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedTable->getInternalId() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); } - if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $key)) { - $dbForProject->updateDocument('attributes', $relatedColumn->getId(), $relatedColumn->setAttribute('status', 'stuck')); + if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck')); throw new DatabaseException('Failed to delete Relationship'); } - } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $key)) { - throw new DatabaseException('Failed to delete Column'); + } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + throw new DatabaseException('Failed to delete attribute/column'); } - $dbForProject->deleteDocument('attributes', $column->getId()); + $dbForProject->deleteDocument('attributes', $attribute->getId()); - if (!$relatedColumn->isEmpty()) { - $dbForProject->deleteDocument('attributes', $relatedColumn->getId()); + if (!$relatedAttribute->isEmpty()) { + $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); } } catch (NotFound $e) { Console::error($e->getMessage()); - $dbForProject->deleteDocument('attributes', $column->getId()); + $dbForProject->deleteDocument('attributes', $attribute->getId()); - if (!$relatedColumn->isEmpty()) { - $dbForProject->deleteDocument('attributes', $relatedColumn->getId()); + if (!$relatedAttribute->isEmpty()) { + $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); } } catch (\Throwable $e) { Console::error($e->getMessage()); if ($e instanceof DatabaseException) { - $column->setAttribute('error', $e->getMessage()); - if (!$relatedColumn->isEmpty()) { - $relatedColumn->setAttribute('error', $e->getMessage()); + $attribute->setAttribute('error', $e->getMessage()); + if (!$relatedAttribute->isEmpty()) { + $relatedAttribute->setAttribute('error', $e->getMessage()); } } $dbForProject->updateDocument( 'attributes', - $column->getId(), - $column->setAttribute('status', 'stuck') + $attribute->getId(), + $attribute->setAttribute('status', 'stuck') ); - if (!$relatedColumn->isEmpty()) { + if (!$relatedAttribute->isEmpty()) { $dbForProject->updateDocument( 'attributes', - $relatedColumn->getId(), - $relatedColumn->setAttribute('status', 'stuck') + $relatedAttribute->getId(), + $relatedAttribute->setAttribute('status', 'stuck') ); } throw $e; } finally { - $this->trigger($database, $table, $project, $events, $queueForRealtime, $column); + $this->trigger($database, $collection, $project, $events, $queueForRealtime, $attribute); } // The underlying database removes/rebuilds indexes when attribute is removed - // Update indexes table with changes + // Update indexes collection with changes /** @var Document[] $indexes */ - $indexes = $table->getAttribute('indexes', []); + $indexes = $collection->getAttribute('indexes', []); foreach ($indexes as $index) { - /** @var string[] $columns */ - $columns = $index->getAttribute('attributes'); + /** @var string[] $attributes */ + $attributes = $index->getAttribute('attributes'); $lengths = $index->getAttribute('lengths'); $orders = $index->getAttribute('orders'); - $found = \array_search($key, $columns); + $found = \array_search($key, $attributes); if ($found !== false) { // If found, remove entry from attributes, lengths, and orders // array_values wraps array_diff to reindex array keys // when found attribute is removed from array - $columns = \array_values(\array_diff($columns, [$columns[$found]])); + $attributes = \array_values(\array_diff($attributes, [$attributes[$found]])); $lengths = \array_values(\array_diff($lengths, isset($lengths[$found]) ? [$lengths[$found]] : [])); $orders = \array_values(\array_diff($orders, isset($orders[$found]) ? [$orders[$found]] : [])); - if (empty($columns)) { + if (empty($attributes)) { $dbForProject->deleteDocument('indexes', $index->getId()); } else { $index - ->setAttribute('attributes', $columns, Document::SET_TYPE_ASSIGN) + ->setAttribute('attributes', $attributes, Document::SET_TYPE_ASSIGN) ->setAttribute('lengths', $lengths, Document::SET_TYPE_ASSIGN) ->setAttribute('orders', $orders, Document::SET_TYPE_ASSIGN); @@ -363,7 +363,7 @@ class Databases extends Action } if ($exists) { // Delete the duplicate if created, else update in db - $this->deleteIndex($database, $table, $index, $project, $dbForPlatform, $dbForProject, $queueForRealtime); + $this->deleteIndex($database, $collection, $index, $project, $dbForPlatform, $dbForProject, $queueForRealtime); } else { $dbForProject->updateDocument('indexes', $index->getId(), $index); } @@ -371,17 +371,17 @@ class Databases extends Action } } } finally { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $tableId); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); - if (! $relatedTable->isEmpty()) { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedTable->getId()); + if (! $relatedCollection->isEmpty()) { + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); } } } /** * @param Document $database - * @param Document $table + * @param Document $collection * @param Document $index * @param Document $project * @param Database $dbForPlatform @@ -394,10 +394,10 @@ class Databases extends Action * @throws DatabaseException * @throws \Throwable */ - private function createIndex(Document $database, Document $table, Document $index, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void + private function createIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void { - if ($table->isEmpty()) { - throw new Exception('Missing collection'); + if ($collection->isEmpty()) { + throw new Exception('Missing collection/table'); } if ($index->isEmpty()) { throw new Exception('Missing index'); @@ -408,7 +408,7 @@ class Databases extends Action 'databases.[databaseId].tables.[tableId].indexes.[indexId].update', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].update', ]; - $collectionId = $table->getId(); + $collectionId = $collection->getId(); $key = $index->getAttribute('key', ''); $type = $index->getAttribute('type', ''); $attributes = $index->getAttribute('attributes', []); @@ -417,7 +417,7 @@ class Databases extends Action $project = $dbForPlatform->getDocument('projects', $projectId); try { - if (!$dbForProject->createIndex('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { + if (!$dbForProject->createIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { throw new DatabaseException('Failed to create Index'); } $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); @@ -434,14 +434,14 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $table, $project, $events, $queueForRealtime, null, $index); + $this->trigger($database, $collection, $project, $events, $queueForRealtime, null, $index); $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } } /** * @param Document $database - * @param Document $table + * @param Document $collection * @param Document $index * @param Document $project * @param Database $dbForPlatform @@ -454,10 +454,10 @@ class Databases extends Action * @throws DatabaseException * @throws \Throwable */ - private function deleteIndex(Document $database, Document $table, Document $index, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void + private function deleteIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void { - if ($table->isEmpty()) { - throw new Exception('Missing collection'); + if ($collection->isEmpty()) { + throw new Exception('Missing collection/table'); } if ($index->isEmpty()) { throw new Exception('Missing index'); @@ -473,7 +473,7 @@ class Databases extends Action $project = $dbForPlatform->getDocument('projects', $projectId); try { - if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getInternalId() . '_collection_' . $table->getInternalId(), $key)) { + if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { throw new DatabaseException('Failed to delete index'); } $dbForProject->deleteDocument('indexes', $index->getId()); @@ -493,22 +493,21 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $table, $project, $events, $queueForRealtime, null, $index); - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $table->getId()); + $this->trigger($database, $collection, $project, $events, $queueForRealtime, null, $index); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); } } /** * @param Document $database - * @param Document $project * @param $dbForProject * @return void * @throws Exception */ - protected function deleteDatabase(Document $database, Document $project, $dbForProject): void + protected function deleteDatabase(Document $database, $dbForProject): void { - $this->deleteByGroup('database_' . $database->getInternalId(), [], $dbForProject, function ($collection) use ($database, $project, $dbForProject) { - $this->deleteTable($database, $collection, $project, $dbForProject); + $this->deleteByGroup('database_' . $database->getInternalId(), [], $dbForProject, function ($collection) use ($database, $dbForProject) { + $this->deleteCollection($database, $collection, $dbForProject); }); $dbForProject->deleteCollection('database_' . $database->getInternalId()); @@ -516,7 +515,7 @@ class Databases extends Action /** * @param Document $database - * @param Document $table + * @param Document $collection * @param Document $project * @param Database $dbForProject * @return void @@ -527,17 +526,17 @@ class Databases extends Action * @throws Structure * @throws Exception */ - protected function deleteTable(Document $database, Document $table, Document $project, Database $dbForProject): void + protected function deleteCollection(Document $database, Document $collection, Database $dbForProject): void { - if ($table->isEmpty()) { - throw new Exception('Missing table'); + if ($collection->isEmpty()) { + throw new Exception('Missing collection/table'); } - $collectionId = $table->getId(); - $collectionInternalId = $table->getInternalId(); + $collectionId = $collection->getId(); + $collectionInternalId = $collection->getInternalId(); $databaseInternalId = $database->getInternalId(); - $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $table->getInternalId()); + $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $collection->getInternalId()); /** * Related collections relating to current collection @@ -551,9 +550,9 @@ class Databases extends Action Query::contains('options', ['"relatedCollection":"'. $collectionId .'"']), ], $dbForProject, - function ($column) use ($dbForProject, $databaseInternalId) { - $dbForProject->purgeCachedDocument('database_' . $databaseInternalId, $column->getAttribute('collectionId')); - $dbForProject->purgeCachedCollection('database_' . $databaseInternalId . '_collection_' . $column->getAttribute('collectionInternalId')); + function ($attribute) use ($dbForProject, $databaseInternalId) { + $dbForProject->purgeCachedDocument('database_' . $databaseInternalId, $attribute->getAttribute('collectionId')); + $dbForProject->purgeCachedCollection('database_' . $databaseInternalId . '_collection_' . $attribute->getAttribute('collectionInternalId')); } ); @@ -570,52 +569,52 @@ class Databases extends Action /** - * @param string $tableId + * @param string $collectionId * @param array $queries * @param Database $database * @param callable|null $callback * @return void * @throws Exception */ - protected function deleteByGroup(string $tableId, array $queries, Database $database, callable $callback = null): void + protected function deleteByGroup(string $collectionId, array $queries, Database $database, callable $callback = null): void { $start = \microtime(true); try { $count = $database->deleteDocuments( - $tableId, + $collectionId, $queries, Database::DELETE_BATCH_SIZE, $callback ); } catch (\Throwable $th) { $tenant = $database->getSharedTables() ? 'Tenant:'.$database->getTenant() : ''; - Console::error("Failed to delete rows for table:{$database->getNamespace()}_{$tableId} {$tenant} :{$th->getMessage()}"); + Console::error("Failed to delete documents/rows for collection/table: {$database->getNamespace()}_{$collectionId} {$tenant} :{$th->getMessage()}"); return; } $end = \microtime(true); - Console::info("Deleted {$count} rows by group in " . ($end - $start) . " seconds"); + Console::info("Deleted {$count} documents/rows by group in " . ($end - $start) . " seconds"); } /** * @param Document $database - * @param Document $table + * @param Document $collection * @param Document $project * @param string[] $events * @param Realtime $queueForRealtime - * @param Document|null $column + * @param Document|null $attribute * @param Document|null $index * @return void * @throws DatabaseException */ protected function trigger( Document $database, - Document $table, + Document $collection, Document $project, array $events, Realtime $queueForRealtime, - Document|null $column = null, + Document|null $attribute = null, Document|null $index = null, ): void { // table and collection @@ -624,15 +623,15 @@ class Databases extends Action ->setProject($project) ->setSubscribers(['console']) ->setEvent($event) - ->setParam('tableId', $table->getId()) - ->setParam('collectionId', $table->getId()) + ->setParam('tableId', $collection->getId()) + ->setParam('collectionId', $collection->getId()) ->setParam('databaseId', $database->getId()); - if (! empty($column)) { + if (! empty($attribute)) { $queueForRealtime - ->setParam('columnId', $column->getId()) - ->setParam('attributeId', $column->getId()) - ->setPayload($column->getArrayCopy()); + ->setParam('columnId', $attribute->getId()) + ->setParam('attributeId', $attribute->getId()) + ->setPayload($attribute->getArrayCopy()); } if (! empty($index)) { From 938b376f3c811591b5f405123a0838e19908d3fd Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 10:02:14 +0530 Subject: [PATCH 099/343] fix: var ref. --- .../Databases/Http/Databases/Collections/Documents/Update.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index 9b373c7e17..eaaa2bb63f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -287,7 +287,7 @@ class Update extends Action $response->dynamic($document, $this->getResponseModel()); $relationships = \array_map( - fn ($row) => $document->getAttribute('key'), + fn ($document) => $document->getAttribute('key'), \array_filter( $collection->getAttribute('attributes', []), fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP From 65dbebd103467027f7118dc84cb5896d639f43fd Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 11:09:58 +0530 Subject: [PATCH 100/343] misc: fix error types. --- .../Collections/Attributes/Action.php | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index be6e3d1ff7..d1047e671d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -150,6 +150,16 @@ abstract class Action extends UtopiaAction : Exception::COLUMN_LIMIT_EXCEEDED; } + /** + * Get the appropriate index invalid exception. + */ + final protected function getInvalidIndexException(): string + { + return $this->isCollectionsAPI() + ? Exception::INDEX_INVALID + : Exception::COLUMN_INDEX_INVALID; + } + /** * Get the correct default unsupported message. */ @@ -480,7 +490,7 @@ abstract class Action extends UtopiaAction $max ??= $attribute->getAttribute('formatOptions')['max']; if ($min > $max) { - throw new Exception($this->getTypeInvalidException(), 'Minimum value must be lesser than maximum value'); + throw new Exception($this->getInvalidValueException(), 'Minimum value must be lesser than maximum value'); } if ($attribute->getAttribute('format') === APP_DATABASE_ATTRIBUTE_INT_RANGE) { @@ -506,17 +516,17 @@ abstract class Action extends UtopiaAction break; case APP_DATABASE_ATTRIBUTE_ENUM: if (empty($elements)) { - throw new Exception($this->getTypeInvalidException(), 'Enum elements must not be empty'); + throw new Exception($this->getInvalidValueException(), 'Enum elements must not be empty'); } foreach ($elements as $element) { if (\strlen($element) === 0) { - throw new Exception($this->getTypeInvalidException(), 'Each enum element must not be empty'); + throw new Exception($this->getInvalidValueException(), 'Each enum element must not be empty'); } } if (!is_null($default) && !in_array($default, $elements)) { - throw new Exception($this->getTypeInvalidException(), 'Default value not found in elements'); + throw new Exception($this->getInvalidValueException(), 'Default value not found in elements'); } $options = [ @@ -575,7 +585,7 @@ abstract class Action extends UtopiaAction } catch (LimitException) { throw new Exception($this->getLimitException()); } catch (IndexException $e) { - throw new Exception(Exception::INDEX_INVALID, $e->getMessage()); + throw new Exception($this->getInvalidIndexException(), $e->getMessage()); } } From a8dc5c3797532e8a50412574a3e0cd0f103a2eec Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 11:10:53 +0530 Subject: [PATCH 101/343] add: table tests to usage. --- tests/e2e/General/UsageTest.php | 296 +++++++++++++++++++++++++++++--- 1 file changed, 273 insertions(+), 23 deletions(-) diff --git a/tests/e2e/General/UsageTest.php b/tests/e2e/General/UsageTest.php index 54b8597204..1cdd2070d0 100644 --- a/tests/e2e/General/UsageTest.php +++ b/tests/e2e/General/UsageTest.php @@ -411,13 +411,13 @@ class UsageTest extends Scope } /** @depends testStorageStats */ - public function testPrepareDatabaseStats(array $data): array + public function testPrepareDatabaseStatsCollectionsAPI(array $data): array { $requestsTotal = $data['requestsTotal']; $databasesTotal = 0; - $tablesTotal = 0; - $rowsTotal = 0; + $collectionsTotal = 0; + $documentsTotal = 0; for ($i = 0; $i < self::CREATE; $i++) { $name = uniqid() . ' database'; @@ -470,7 +470,7 @@ class UsageTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'tableId' => 'unique()', + 'collectionId' => 'unique()', 'name' => $name, 'documentSecurity' => false, 'permissions' => [ @@ -486,7 +486,7 @@ class UsageTest extends Scope $this->assertNotEmpty($response['body']['$id']); $requestsTotal += 1; - $tablesTotal += 1; + $collectionsTotal += 1; $collectionId = $response['body']['$id']; @@ -501,7 +501,7 @@ class UsageTest extends Scope $this->assertEmpty($response['body']); - $tablesTotal -= 1; + $collectionsTotal -= 1; $requestsTotal += 1; } } @@ -537,7 +537,7 @@ class UsageTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), [ - 'rowId' => 'unique()', + 'documentId' => 'unique()', 'data' => ['name' => $name] ] ); @@ -546,7 +546,7 @@ class UsageTest extends Scope $this->assertNotEmpty($response['body']['$id']); $requestsTotal += 1; - $rowsTotal += 1; + $documentsTotal += 1; $documentId = $response['body']['$id']; @@ -561,31 +561,31 @@ class UsageTest extends Scope $this->assertEmpty($response['body']); - $rowsTotal -= 1; + $documentsTotal -= 1; $requestsTotal += 1; } } return array_merge($data, [ 'databaseId' => $databaseId, - 'tableId' => $collectionId, + 'collectionId' => $collectionId, 'requestsTotal' => $requestsTotal, 'databasesTotal' => $databasesTotal, - 'tablesTotal' => $tablesTotal, - 'rowsTotal' => $rowsTotal, + 'collectionsTotal' => $collectionsTotal, + 'documentsTotal' => $documentsTotal, ]); } - /** @depends testPrepareDatabaseStats */ + /** @depends testPrepareDatabaseStatsCollectionsAPI */ #[Retry(count: 1)] - public function testDatabaseStats(array $data): array + public function testDatabaseStatsCollectionsAPI(array $data): array { $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $requestsTotal = $data['requestsTotal']; $databasesTotal = $data['databasesTotal']; - $tablesTotal = $data['tablesTotal']; - $rowsTotal = $data['rowsTotal']; + $collectionsTotal = $data['collectionsTotal']; + $documentsTotal = $data['documentsTotal']; sleep(self::WAIT); @@ -606,7 +606,7 @@ class UsageTest extends Scope $this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']); $this->validateDates($response['body']['requests']); $this->assertEquals($databasesTotal, $response['body']['databasesTotal']); - $this->assertEquals($rowsTotal, $response['body']['rowsTotal']); + $this->assertEquals($documentsTotal, $response['body']['documentsTotal']); $response = $this->client->call( Client::METHOD_GET, @@ -616,9 +616,260 @@ class UsageTest extends Scope $this->assertEquals($databasesTotal, $response['body']['databases'][array_key_last($response['body']['databases'])]['value']); $this->validateDates($response['body']['databases']); - $this->assertEquals($tablesTotal, $response['body']['tables'][array_key_last($response['body']['tables'])]['value']); + $this->assertEquals($collectionsTotal, $response['body']['collections'][array_key_last($response['body']['collections'])]['value']); + $this->validateDates($response['body']['collections']); + $this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']); + $this->validateDates($response['body']['documents']); + + $response = $this->client->call( + Client::METHOD_GET, + '/databases/' . $databaseId . '/usage?range=30d', + $this->getConsoleHeaders() + ); + + $this->assertEquals($collectionsTotal, $response['body']['collections'][array_key_last($response['body']['collections'])]['value']); + $this->validateDates($response['body']['collections']); + + $this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']); + $this->validateDates($response['body']['documents']); + + $response = $this->client->call( + Client::METHOD_GET, + '/databases/' . $databaseId . '/collections/' . $collectionId . '/usage?range=30d', + $this->getConsoleHeaders() + ); + + $this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']); + $this->validateDates($response['body']['documents']); + + return $data; + } + + /** @depends testDatabaseStatsCollectionsAPI */ + public function testPrepareDatabaseStatsTablesAPI(array $data): array + { + $rowsTotal = 0; + $tablesTotal = 0; + $databasesTotal = $data['databasesTotal']; + $documentsTotal = $data['documentsTotal']; + $collectionsTotal = $data['collectionsTotal']; + + $requestsTotal = $data['requestsTotal']; + + for ($i = 0; $i < self::CREATE; $i++) { + $name = uniqid() . ' database'; + + $response = $this->client->call( + Client::METHOD_POST, + '/databases', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), + [ + 'databaseId' => 'unique()', + 'name' => $name, + ] + ); + + $this->assertEquals($name, $response['body']['name']); + $this->assertNotEmpty($response['body']['$id']); + + $requestsTotal += 1; + $databasesTotal += 1; + + $databaseId = $response['body']['$id']; + + if ($i < (self::CREATE / 2)) { + $response = $this->client->call( + Client::METHOD_DELETE, + '/databases/' . $databaseId, + array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), + ); + + $this->assertEmpty($response['body']); + + $databasesTotal -= 1; + $requestsTotal += 1; + } + } + + for ($i = 0; $i < self::CREATE; $i++) { + $name = uniqid() . ' table'; + + $response = $this->client->call( + Client::METHOD_POST, + '/databases/' . $databaseId . '/tables', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), + [ + 'tableId' => 'unique()', + 'name' => $name, + 'documentSecurity' => false, + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ] + ); + + $this->assertEquals($name, $response['body']['name']); + $this->assertNotEmpty($response['body']['$id']); + + $requestsTotal += 1; + $tablesTotal += 1; + + $tableId = $response['body']['$id']; + + if ($i < (self::CREATE / 2)) { + $response = $this->client->call( + Client::METHOD_DELETE, + '/databases/' . $databaseId . '/tables/' . $tableId, + array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), + ); + + $this->assertEmpty($response['body']); + + $tablesTotal -= 1; + $requestsTotal += 1; + } + } + + $response = $this->client->call( + Client::METHOD_POST, + '/databases/' . $databaseId . '/tables/' . $tableId . '/columns' . '/string', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), + [ + 'key' => 'name', + 'size' => 255, + 'required' => true, + ] + ); + + $this->assertEquals('name', $response['body']['key']); + + sleep(self::WAIT); + + $requestsTotal += 1; + + for ($i = 0; $i < self::CREATE; $i++) { + $name = uniqid() . ' table'; + + $response = $this->client->call( + Client::METHOD_POST, + '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), + [ + 'rowId' => 'unique()', + 'data' => ['name' => $name] + ] + ); + + $this->assertEquals($name, $response['body']['name']); + $this->assertNotEmpty($response['body']['$id']); + + $requestsTotal += 1; + $rowsTotal += 1; + + $rowId = $response['body']['$id']; + + if ($i < (self::CREATE / 2)) { + $response = $this->client->call( + Client::METHOD_DELETE, + '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $rowId, + array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), + ); + + $this->assertEmpty($response['body']); + + $rowsTotal -= 1; + $requestsTotal += 1; + } + } + + return array_merge($data, [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'requestsTotal' => $requestsTotal, + 'databasesTotal' => $databasesTotal, + 'tablesTotal' => $tablesTotal, + 'rowsTotal' => $rowsTotal, + + // For clarity + 'absoluteRowsTotal' => $rowsTotal + $data['documentsTotal'], + 'absoluteTablesTotal' => $tablesTotal + $data['collectionsTotal'], + ]); + } + + /** @depends testPrepareDatabaseStatsTablesAPI */ + #[Retry(count: 1)] + public function testDatabaseStatsTablesAPI(array $data): array + { + $tableId = $data['tableId']; + $databaseId = $data['databaseId']; + $requestsTotal = $data['requestsTotal']; + + $absoluteRowsTotal = $data['absoluteRowsTotal']; + $absoluteTablesTotal = $data['absoluteTablesTotal']; + + $rowsTotal = $data['rowsTotal']; + $tablesTotal = $data['tablesTotal']; + $databasesTotal = $data['databasesTotal']; + + sleep(self::WAIT); + + $response = $this->client->call( + Client::METHOD_GET, + '/project/usage', + $this->getConsoleHeaders(), + [ + 'period' => '1d', + 'startDate' => self::getToday(), + 'endDate' => self::getTomorrow(), + ] + ); + + $this->assertGreaterThanOrEqual(31, count($response['body'])); + $this->assertCount(1, $response['body']['requests']); + $this->assertCount(1, $response['body']['network']); + $this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']); + $this->validateDates($response['body']['requests']); + $this->assertEquals($databasesTotal, $response['body']['databasesTotal']); + + // project level includes all i.e. documents + rows total. + $this->assertEquals($absoluteRowsTotal, $response['body']['rowsTotal']); + + $response = $this->client->call( + Client::METHOD_GET, + '/databases/usage?range=30d', + $this->getConsoleHeaders() + ); + + $this->assertEquals($databasesTotal, $response['body']['databases'][array_key_last($response['body']['databases'])]['value']); + $this->validateDates($response['body']['databases']); + + // database level includes all i.e. collections + tables total. + $this->assertEquals($absoluteTablesTotal, $response['body']['tables'][array_key_last($response['body']['tables'])]['value']); // database level $this->validateDates($response['body']['tables']); - $this->assertEquals($rowsTotal, $response['body']['rows'][array_key_last($response['body']['rows'])]['value']); + + // database level includes all i.e. documents + rows total. + $this->assertEquals($absoluteRowsTotal, $response['body']['rows'][array_key_last($response['body']['rows'])]['value']); $this->validateDates($response['body']['rows']); $response = $this->client->call( @@ -635,7 +886,7 @@ class UsageTest extends Scope $response = $this->client->call( Client::METHOD_GET, - '/databases/' . $databaseId . '/collections/' . $collectionId . '/usage?range=30d', + '/databases/' . $databaseId . '/tables/' . $tableId . '/usage?range=30d', $this->getConsoleHeaders() ); @@ -645,7 +896,7 @@ class UsageTest extends Scope return $data; } - /** @depends testDatabaseStats */ + /** @depends testDatabaseStatsTablesAPI */ public function testPrepareFunctionsStats(array $data): array { $executionTime = 0; @@ -859,7 +1110,6 @@ class UsageTest extends Scope return $data; } - public function testPrepareSitesStats(): array { $siteId = $this->setupSite([ From a807dd97d9e5e7c47618dfb70a89b08911a25b0d Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 14:47:01 +0530 Subject: [PATCH 102/343] fix: realtime events. --- src/Appwrite/Event/Realtime.php | 33 +++++++- src/Appwrite/Messaging/Adapter/Realtime.php | 12 +-- .../Collections/Attributes/Action.php | 30 ++------ .../Collections/Attributes/Delete.php | 7 +- .../Collections/Documents/Action.php | 16 ---- .../Collections/Documents/Create.php | 6 +- .../Collections/Documents/Delete.php | 6 +- .../Collections/Documents/Update.php | 6 +- .../Databases/Collections/Indexes/Action.php | 16 ---- .../Databases/Collections/Indexes/Create.php | 5 +- .../Databases/Collections/Indexes/Delete.php | 5 +- .../Modules/Databases/Workers/Databases.php | 76 ++++++++----------- 12 files changed, 95 insertions(+), 123 deletions(-) diff --git a/src/Appwrite/Event/Realtime.php b/src/Appwrite/Event/Realtime.php index 67d51e5c52..f45b6548d8 100644 --- a/src/Appwrite/Event/Realtime.php +++ b/src/Appwrite/Event/Realtime.php @@ -73,21 +73,46 @@ class Realtime extends Event } $allEvents = Event::generateEvents($this->getEvent(), $this->getParams()); + $firstEvent = $allEvents[0]; // most verbose event pattern + + // generate and merge all collection and tables api events. + if (str_contains($this->getEvent(), 'databases.') && str_contains($firstEvent, 'collections')) { + $tableEventMap = [ + 'collections' => 'tables', 'attributes' => 'columns', + 'attributeId' => 'columnId', 'documents' => 'rows', 'documentId' => 'rowId', + ]; + + // replace params! + $tableEvent = str_replace( + array_keys($tableEventMap), + array_values($tableEventMap), + $this->getEvent() + ); + + // generate new events + $tableEvents = Event::generateEvents($tableEvent, $this->getParams()); + + // merge all of the api events + $allEvents = array_merge($allEvents, $tableEvents); + + // remove duplicates + $allEvents = array_values(array_unique($allEvents)); + } + $payload = new Document($this->getPayload()); $db = $this->getContext('database'); $bucket = $this->getContext('bucket'); - // can be Tables API or Collections API, generated channels include both! + // Can be Tables API or Collections API; generated channels include both! $tableOrCollection = $this->getContext('table') ?? $this->getContext('collection'); $target = RealtimeAdapter::fromPayload( - // Pass first, most verbose event pattern - event: $allEvents[0], + event: $firstEvent, payload: $payload, project: $this->getProject(), database: $db, - table: $tableOrCollection, + collection: $tableOrCollection, bucket: $bucket, ); diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index 4980618ab1..bfe87c49db 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -252,12 +252,12 @@ class Realtime extends Adapter * @param Document $payload * @param Document|null $project * @param Document|null $database - * @param Document|null $table + * @param Document|null $collection * @param Document|null $bucket * @return array * @throws \Exception */ - public static function fromPayload(string $event, Document $payload, Document $project = null, Document $database = null, Document $table = null, Document $bucket = null): array + public static function fromPayload(string $event, Document $payload, Document $project = null, Document $database = null, Document $collection = null, Document $bucket = null): array { $channels = []; $roles = []; @@ -308,7 +308,7 @@ class Realtime extends Adapter if ($database->isEmpty()) { throw new \Exception('Database needs to be passed to Realtime for Document/Row events in the Database.'); } - if ($table->isEmpty()) { + if ($collection->isEmpty()) { throw new \Exception('Collection or the Table needs to be passed to Realtime for Document/Row events in the Database.'); } @@ -322,9 +322,9 @@ class Realtime extends Adapter $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents'; $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents.' . $payload->getId(); - $roles = $table->getAttribute('documentSecurity', false) - ? \array_merge($table->getRead(), $payload->getRead()) - : $table->getRead(); + $roles = $collection->getAttribute('documentSecurity', false) + ? \array_merge($collection->getRead(), $payload->getRead()) + : $collection->getRead(); } break; case 'buckets': diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index d1047e671d..954e997872 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -84,22 +84,6 @@ abstract class Action extends UtopiaAction return $this->isCollectionsAPI() ? 'collections' : 'tables'; } - /** - * Get the correct parent param key (e.g. `tableId` or `collectionId`) - */ - final protected function getParentEventsParamKey(): string - { - return $this->isCollectionsAPI() ? 'collectionId' : 'tableId'; - } - - /** - * Get the correct param key (e.g. `attributeId` or `columnId`) - */ - final protected function getEventsParamKey(): string - { - return $this->getContext() . 'Id'; - } - /** * Get the appropriate parent level not found exception. */ @@ -423,9 +407,10 @@ abstract class Action extends UtopiaAction $queueForEvents ->setContext('database', $db) ->setParam('databaseId', $databaseId) - ->setParam($this->getEventsParamKey(), $attribute->getId()) - // tableId or columnId - ->setParam($this->getParentEventsParamKey(), $collection->getId()) + ->setParam('attributeId', $attribute->getId()) + ->setParam('columnId', $attribute->getId()) + ->setParam('tableId', $collection->getId()) + ->setParam('collectionId', $collection->getId()) ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); $response->setStatusCode(SwooleResponse::STATUS_CODE_CREATED); @@ -623,9 +608,10 @@ abstract class Action extends UtopiaAction $queueForEvents ->setContext('database', $db) ->setParam('databaseId', $databaseId) - ->setParam($this->getEventsParamKey(), $attribute->getId()) - // tableId or columnId - ->setParam($this->getParentEventsParamKey(), $collection->getId()) + ->setParam('attributeId', $attribute->getId()) + ->setParam('columnId', $attribute->getId()) + ->setParam('tableId', $collection->getId()) + ->setParam('collectionId', $collection->getId()) ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); return $attribute; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 2432ac5fd0..81bc77a9ba 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -146,9 +146,10 @@ class Delete extends Action ->setContext('database', $db) ->setParam('databaseId', $databaseId) ->setPayload($response->output($attribute, $model)) - ->setParam($this->getEventsParamKey(), $attribute->getId()) - // tableId or columnId - ->setParam($this->getParentEventsParamKey(), $collection->getId()) + ->setParam('attributeId', $attribute->getId()) + ->setParam('columnId', $attribute->getId()) + ->setParam('collectionId', $collection->getId()) + ->setParam('tableId', $collection->getId()) // set proper context ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index b9a3247f96..a5b8fc5805 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -67,22 +67,6 @@ abstract class Action extends UtopiaAction return $this->isCollectionsAPI() ? 'collections' : 'tables'; } - /** - * Get the correct parent param key (e.g. `tableId` or `collectionId`) - */ - final protected function getParentEventsParamKey(): string - { - return $this->isCollectionsAPI() ? 'collectionId' : 'tableId'; - } - - /** - * Get the correct param key (e.g. `documentId` or `rowId`) - */ - final protected function getEventsParamKey(): string - { - return $this->getContext() . 'Id'; - } - /** * Get the appropriate parent level not found exception. */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index 297d0f3543..4c63837d57 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -310,9 +310,11 @@ class Create extends Action $queueForEvents ->setParam('databaseId', $databaseId) ->setContext('database', $database) - ->setParam($this->getEventsParamKey(), $document->getId()) + ->setParam('rowId', $document->getId()) + ->setParam('documentId', $document->getId()) + ->setParam('tableId', $collection->getId()) + ->setParam('collectionId', $collection->getId()) ->setPayload($response->getPayload(), sensitive: $relationships) - ->setParam($this->getParentEventsParamKey(), $collection->getId()) ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index 2f0c4e76db..66e1b37320 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -164,8 +164,10 @@ class Delete extends Action $queueForEvents ->setParam('databaseId', $databaseId) ->setContext('database', $database) - ->setParam($this->getParentEventsParamKey(), $collection->getId()) - ->setParam($this->getEventsParamKey(), $document->getId()) + ->setParam('rowId', $document->getId()) + ->setParam('documentId', $document->getId()) + ->setParam('tableId', $collection->getId()) + ->setParam('collectionId', $collection->getId()) ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection) ->setPayload($response->output($document, $this->getResponseModel()), sensitive: $relationships); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index eaaa2bb63f..5bee2ee761 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -297,8 +297,10 @@ class Update extends Action $queueForEvents ->setParam('databaseId', $databaseId) ->setContext('database', $database) - ->setParam($this->getEventsParamKey(), $document->getId()) - ->setParam($this->getParentEventsParamKey(), $collection->getId()) + ->setParam('rowId', $document->getId()) + ->setParam('documentId', $document->getId()) + ->setParam('tableId', $collection->getId()) + ->setParam('collectionId', $collection->getId()) ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection) ->setPayload($response->getPayload(), sensitive: $relationships); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php index 6186139bfb..93459440f0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php @@ -49,22 +49,6 @@ abstract class Action extends UtopiaAction return $this->context; } - /** - * Get the correct grand parent param key (e.g. `tableId` or `collectionId`) - */ - final protected function getGrandParentEventsParamKey(): string - { - return $this->isCollectionsAPI() ? 'collectionId' : 'tableId'; - } - - /** - * Get the key used in event parameters. - */ - final protected function getEventsParamKey(): string - { - return 'indexId'; - } - /** * Determine if the current action is for the Collections API. */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index 6370a32a4c..014627e0a8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -220,8 +220,9 @@ class Create extends Action $queueForEvents ->setContext('database', $db) ->setParam('databaseId', $databaseId) - ->setParam($this->getEventsParamKey(), $index->getId()) - ->setParam($this->getGrandParentEventsParamKey(), $collection->getId()) + ->setParam('indexId', $index->getId()) + ->setParam('tableId', $collection->getId()) + ->setParam('collectionId', $collection->getId()) ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); $response diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index 2d57a8a5f0..f86cf7b11f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -115,9 +115,10 @@ class Delete extends Action $queueForEvents ->setContext('database', $db) ->setParam('databaseId', $databaseId) - ->setParam($this->getEventsParamKey(), $index->getId()) + ->setParam('indexId', $index->getId()) + ->setParam('tableId', $collection->getId()) + ->setParam('collectionId', $collection->getId()) ->setPayload($response->output($index, $this->getResponseModel())) - ->setParam($this->getGrandParentEventsParamKey(), $collection->getId()) ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); $response->noContent(); diff --git a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php index 8711d28d2c..35334de266 100644 --- a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php +++ b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php @@ -115,10 +115,8 @@ class Databases extends Action } $projectId = $project->getId(); - $events = [ - "databases.[databaseId].tables.[tableId].columns.[columnId].update", - "databases.[databaseId].collections.[collectionId].attributes.[attributeId].update", - ]; + $event = "databases.[databaseId].collections.[collectionId].attributes.[attributeId].update"; + /** * TODO @christyjacob4 verify if this is still the case * Fetch attribute from the database, since with Resque float values are loosing information. @@ -207,7 +205,7 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $collection, $project, $events, $queueForRealtime, $attribute); + $this->trigger($database, $collection, $project, $event, $queueForRealtime, $attribute); if (! $relatedCollection->isEmpty()) { $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); @@ -241,10 +239,7 @@ class Databases extends Action } $projectId = $project->getId(); - $events = [ - 'databases.[databaseId].tables.[tableId].columns.[columnId].delete', - 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].delete', - ]; + $event = 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].delete'; $collectionId = $collection->getId(); $key = $attribute->getAttribute('key', ''); $type = $attribute->getAttribute('type', ''); @@ -317,7 +312,7 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $collection, $project, $events, $queueForRealtime, $attribute); + $this->trigger($database, $collection, $project, $event, $queueForRealtime, $attribute); } // The underlying database removes/rebuilds indexes when attribute is removed @@ -404,10 +399,7 @@ class Databases extends Action } $projectId = $project->getId(); - $events = [ - 'databases.[databaseId].tables.[tableId].indexes.[indexId].update', - 'databases.[databaseId].collections.[collectionId].indexes.[indexId].update', - ]; + $event = 'databases.[databaseId].collections.[collectionId].indexes.[indexId].update'; $collectionId = $collection->getId(); $key = $index->getAttribute('key', ''); $type = $index->getAttribute('type', ''); @@ -434,7 +426,7 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $collection, $project, $events, $queueForRealtime, null, $index); + $this->trigger($database, $collection, $project, $event, $queueForRealtime, null, $index); $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } } @@ -464,10 +456,7 @@ class Databases extends Action } $projectId = $project->getId(); - $events = [ - 'databases.[databaseId].tables.[tableId].indexes.[indexId].delete', - 'databases.[databaseId].collections.[collectionId].indexes.[indexId].delete', - ]; + $event = 'databases.[databaseId].collections.[collectionId].indexes.[indexId].delete'; $key = $index->getAttribute('key'); $status = $index->getAttribute('status', ''); $project = $dbForPlatform->getDocument('projects', $projectId); @@ -493,7 +482,7 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $collection, $project, $events, $queueForRealtime, null, $index); + $this->trigger($database, $collection, $project, $event, $queueForRealtime, null, $index); $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); } } @@ -516,7 +505,6 @@ class Databases extends Action /** * @param Document $database * @param Document $collection - * @param Document $project * @param Database $dbForProject * @return void * @throws Authorization @@ -601,7 +589,7 @@ class Databases extends Action * @param Document $database * @param Document $collection * @param Document $project - * @param string[] $events + * @param string $event * @param Realtime $queueForRealtime * @param Document|null $attribute * @param Document|null $index @@ -612,35 +600,31 @@ class Databases extends Action Document $database, Document $collection, Document $project, - array $events, + string $event, Realtime $queueForRealtime, Document|null $attribute = null, Document|null $index = null, ): void { - // table and collection - foreach ($events as $event) { + $queueForRealtime + ->setProject($project) + ->setSubscribers(['console']) + ->setEvent($event) + ->setParam('databaseId', $database->getId()) + ->setParam('tableId', $collection->getId()) + ->setParam('collectionId', $collection->getId()); + + if (! empty($attribute)) { $queueForRealtime - ->setProject($project) - ->setSubscribers(['console']) - ->setEvent($event) - ->setParam('tableId', $collection->getId()) - ->setParam('collectionId', $collection->getId()) - ->setParam('databaseId', $database->getId()); - - if (! empty($attribute)) { - $queueForRealtime - ->setParam('columnId', $attribute->getId()) - ->setParam('attributeId', $attribute->getId()) - ->setPayload($attribute->getArrayCopy()); - } - - if (! empty($index)) { - $queueForRealtime - ->setParam('indexId', $index->getId()) - ->setPayload($index->getArrayCopy()); - } - - $queueForRealtime->trigger(); + ->setParam('columnId', $attribute->getId()) + ->setParam('attributeId', $attribute->getId()) + ->setPayload($attribute->getArrayCopy()); } + if (! empty($index)) { + $queueForRealtime + ->setParam('indexId', $index->getId()) + ->setPayload($index->getArrayCopy()); + } + + $queueForRealtime->trigger(); } } From f10be55f92c1615ec8e73a4a0aa1f1cedeffb8de Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 14:49:44 +0530 Subject: [PATCH 103/343] update: short the callbacks. --- .../Http/Databases/Tables/Columns/Boolean/Create.php | 7 +------ .../Http/Databases/Tables/Columns/Boolean/Update.php | 6 +----- .../Http/Databases/Tables/Columns/Datetime/Create.php | 6 +----- .../Http/Databases/Tables/Columns/Datetime/Update.php | 5 +---- .../Databases/Http/Databases/Tables/Columns/Delete.php | 7 +------ .../Http/Databases/Tables/Columns/Email/Create.php | 7 +------ .../Http/Databases/Tables/Columns/Email/Update.php | 6 +----- .../Http/Databases/Tables/Columns/Enum/Create.php | 6 +----- .../Http/Databases/Tables/Columns/Enum/Update.php | 5 +---- .../Http/Databases/Tables/Columns/Float/Create.php | 7 +------ .../Http/Databases/Tables/Columns/Float/Update.php | 6 +----- .../Databases/Http/Databases/Tables/Columns/Get.php | 5 +---- .../Http/Databases/Tables/Columns/IP/Create.php | 7 +------ .../Http/Databases/Tables/Columns/IP/Update.php | 6 +----- .../Http/Databases/Tables/Columns/Integer/Create.php | 7 +------ .../Http/Databases/Tables/Columns/Integer/Update.php | 6 +----- .../Databases/Tables/Columns/Relationship/Create.php | 6 +----- .../Databases/Tables/Columns/Relationship/Update.php | 5 +---- .../Http/Databases/Tables/Columns/String/Create.php | 7 +------ .../Http/Databases/Tables/Columns/String/Update.php | 6 +----- .../Http/Databases/Tables/Columns/URL/Create.php | 7 +------ .../Http/Databases/Tables/Columns/URL/Update.php | 6 +----- .../Databases/Http/Databases/Tables/Columns/XList.php | 5 +---- .../Modules/Databases/Http/Databases/Tables/Create.php | 6 +----- .../Modules/Databases/Http/Databases/Tables/Delete.php | 7 +------ .../Modules/Databases/Http/Databases/Tables/Get.php | 5 +---- .../Databases/Http/Databases/Tables/Indexes/Create.php | 10 +++------- .../Databases/Http/Databases/Tables/Indexes/Delete.php | 7 +------ .../Databases/Http/Databases/Tables/Indexes/Get.php | 5 +---- .../Databases/Http/Databases/Tables/Indexes/XList.php | 5 +---- .../Databases/Http/Databases/Tables/Logs/XList.php | 8 +------- .../Databases/Http/Databases/Tables/Rows/Create.php | 7 +------ .../Databases/Http/Databases/Tables/Rows/Delete.php | 7 +------ .../Databases/Http/Databases/Tables/Rows/Get.php | 6 +----- .../Http/Databases/Tables/Rows/Logs/XList.php | 8 +------- .../Databases/Http/Databases/Tables/Rows/Update.php | 6 +----- .../Databases/Http/Databases/Tables/Rows/XList.php | 6 +----- .../Modules/Databases/Http/Databases/Tables/Update.php | 6 +----- .../Databases/Http/Databases/Tables/Usage/Get.php | 5 +---- .../Modules/Databases/Http/Databases/Tables/XList.php | 5 +---- 40 files changed, 42 insertions(+), 208 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php index 6f48afe57f..ada1d83424 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php @@ -2,14 +2,11 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Boolean; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Boolean\Create as BooleanCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -67,8 +64,6 @@ class Create extends BooleanCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php index 485a9587e3..5316677adc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php @@ -2,14 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Boolean; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Boolean\Update as BooleanUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -68,8 +66,6 @@ class Update extends BooleanUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $default, $newKey, $response, $dbForProject, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php index 1a5f6f65e1..a0731f0767 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php @@ -2,8 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Datetime; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Datetime\Create as DatetimeCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -68,8 +66,6 @@ class Create extends DatetimeCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php index 1eb13852e7..495e96f025 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Datetime; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Datetime\Update as DatetimeUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -69,8 +68,6 @@ class Update extends DatetimeUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $default, $newKey, $response, $dbForProject, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php index 10604029dd..68cb00e18b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php @@ -2,15 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Delete as AttributesDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -66,8 +63,6 @@ class Delete extends AttributesDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php index 2d7b65931f..569d641118 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php @@ -2,15 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Email; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Network\Validator\Email; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Email\Create as EmailCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -68,8 +65,6 @@ class Create extends EmailCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php index a067334a9d..bb3abb10d3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Email; -use Appwrite\Event\Event; use Appwrite\Network\Validator\Email; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Email\Update as EmailUpdate; use Appwrite\SDK\AuthType; @@ -10,7 +9,6 @@ use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -69,8 +67,6 @@ class Update extends EmailUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $default, $newKey, $response, $dbForProject, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php index 8fdb689b46..47d06d4a53 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php @@ -2,8 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Enum; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Enum\Create as EnumCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -70,8 +68,6 @@ class Create extends EnumCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $elements, $required, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php index 85e1c4e5cc..18c1db0683 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Enum; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Enum\Update as EnumUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -71,8 +70,6 @@ class Update extends EnumUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $elements, $required, $default, $newKey, $response, $dbForProject, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php index 2ad2c11572..217378e274 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php @@ -2,14 +2,11 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Float; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Float\Create as FloatCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -70,8 +67,6 @@ class Create extends FloatCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $min, $max, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php index ef6080b86c..be9e2f6b09 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php @@ -2,14 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Float; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Float\Update as FloatUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -71,8 +69,6 @@ class Update extends FloatUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $min, $max, $default, $newKey, $response, $dbForProject, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php index 42ba23ad3a..630ac01e0f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php @@ -7,7 +7,6 @@ use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -67,8 +66,6 @@ class Get extends AttributesGet ->param('key', '', new Key(), 'Column Key.') ->inject('response') ->inject('dbForProject') - ->callback(function (string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject) { - parent::action($databaseId, $tableId, $key, $response, $dbForProject); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php index 34d5ecdfca..4da949dd74 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php @@ -2,14 +2,11 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\IP; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\IP\Create as IPCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -68,8 +65,6 @@ class Create extends IPCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php index 34cfe97343..7adda8a4d5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php @@ -2,14 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\IP; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\IP\Update as IPUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -69,8 +67,6 @@ class Update extends IPUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $default, $newKey, $response, $dbForProject, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php index 13aa90b6e3..2172b5067b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php @@ -2,14 +2,11 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Integer; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Integer\Create as IntegerCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -70,8 +67,6 @@ class Create extends IntegerCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $min, $max, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php index 6cf3383795..26f7e8625c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php @@ -2,14 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Integer; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Integer\Update as IntegerUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -71,8 +69,6 @@ class Update extends IntegerUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $min, $max, $default, $newKey, $response, $dbForProject, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php index be5da989af..76dd80cec9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php @@ -2,8 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Relationship; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Relationship\Create as RelationshipCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -79,8 +77,6 @@ class Create extends RelationshipCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $relatedTableId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $relatedTableId, $type, $twoWay, $key, $twoWayKey, $onDelete, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php index 1afdd0c56a..b2229bb32d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Relationship; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Relationship\Update as RelationshipUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -70,8 +69,6 @@ class Update extends RelationshipUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?string $onDelete, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $onDelete, $newKey, $response, $dbForProject, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php index e17ac07ccf..cf12e6582d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php @@ -2,14 +2,11 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\String; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\String\Create as StringCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -72,8 +69,6 @@ class Create extends StringCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $size, $required, $default, $array, $encrypt, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php index f64d5408eb..968b15bbef 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php @@ -2,14 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\String; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\String\Update as StringUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -72,8 +70,6 @@ class Update extends StringUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?int $size, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $default, $size, $newKey, $response, $dbForProject, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php index a0f4e2ae8f..8c9865cde0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php @@ -2,14 +2,11 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\URL; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\URL\Create as URLCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -68,8 +65,6 @@ class Create extends URLCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $default, $array, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php index 623328e249..e461befe0b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php @@ -2,14 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\URL; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\URL\Update as URLUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -69,8 +67,6 @@ class Update extends URLUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $required, $default, $newKey, $response, $dbForProject, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php index a6b43518b9..3dde78441d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php @@ -8,7 +8,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Columns; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; @@ -56,8 +55,6 @@ class XList extends AttributesXList ->param('queries', [], new Columns(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Columns::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->callback(function (string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject) { - parent::action($databaseId, $tableId, $queries, $response, $dbForProject); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php index 1f349b95ed..0ca46f66e0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Create as CollectionCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -10,7 +9,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -69,8 +67,6 @@ class Create extends CollectionCreate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { - parent::action($databaseId, $tableId, $name, $permissions, $documentSecurity, $enabled, $response, $dbForProject, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php index 338d344660..c24fad28ef 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php @@ -2,15 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Delete as CollectionDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; @@ -63,8 +60,6 @@ class Delete extends CollectionDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php index ffa1da443e..e277db6d3d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php @@ -8,7 +8,6 @@ use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; @@ -56,8 +55,6 @@ class Get extends CollectionGet ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') - ->callback(function (string $databaseId, string $tableId, UtopiaResponse $response, Database $dbForProject) { - parent::action($databaseId, $tableId, $response, $dbForProject); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php index 77e31f4115..b8e22cec71 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php @@ -2,8 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Create as IndexCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -38,10 +36,10 @@ class Create extends IndexCreate $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) - ->setHttpPath('/v1/databases/:databaseId/tables/:tables/indexes') + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes') ->desc('Create index') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].tables.[tables].indexes.[indexId].create') + ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].create') ->label('scope', 'collections.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'index.create') @@ -70,8 +68,6 @@ class Create extends IndexCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, string $type, array $columns, array $orders, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $type, $columns, $orders, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php index 7a81942e32..ed8c355075 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php @@ -2,15 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Delete as IndexDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -69,8 +66,6 @@ class Delete extends IndexDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { - parent::action($databaseId, $tableId, $key, $response, $dbForProject, $queueForDatabase, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php index a765bfb975..cd689316e6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php @@ -8,7 +8,6 @@ use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -58,8 +57,6 @@ class Get extends IndexGet ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') - ->callback(function (string $databaseId, string $tableId, string $key, UtopiaResponse $response, Database $dbForProject) { - parent::action($databaseId, $tableId, $key, $response, $dbForProject); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php index afce04fcf9..3d0e7d5139 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php @@ -9,7 +9,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Indexes; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; @@ -58,8 +57,6 @@ class XList extends IndexXList ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->callback(function (string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject) { - parent::action($databaseId, $tableId, $queries, $response, $dbForProject); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php index 9a6d4c4e8e..967e53539c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php @@ -7,14 +7,10 @@ use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; -use Appwrite\Utopia\Response as UtopiaResponse; -use MaxMind\Db\Reader; -use Utopia\Database\Database; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; -use Utopia\Locale\Locale; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; @@ -59,8 +55,6 @@ class XList extends CollectionLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->callback(function (string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb) { - parent::action($databaseId, $tableId, $queries, $response, $dbForProject, $locale, $geodb); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php index 1773a4c2ff..d041630894 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php @@ -2,8 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; -use Appwrite\Event\Event; -use Appwrite\Event\StatsUsage; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Create as DocumentCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -12,7 +10,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -76,8 +73,6 @@ class Create extends DocumentCreate ->inject('user') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->callback(function (string $databaseId, string $rowId, string $tableId, string|array $data, ?array $permissions, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage) { - parent::action($databaseId, $rowId, $tableId, $databaseId, $permissions, $response, $dbForProject, $user, $queueForEvents, $queueForStatsUsage); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php index 05a98d6096..e40046bdf9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php @@ -2,15 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; -use Appwrite\Event\Event; -use Appwrite\Event\StatsUsage; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Delete as DocumentDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; @@ -74,8 +71,6 @@ class Delete extends DocumentDelete ->inject('dbForProject') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->callback(function (string $databaseId, string $tableId, string $rowId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { - parent::action($databaseId, $tableId, $rowId, $requestTimestamp, $response, $dbForProject, $queueForEvents, $queueForStatsUsage); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php index 717cec3721..5ff02e96e8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php @@ -2,14 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; -use Appwrite\Event\StatsUsage; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Get as DocumentGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; @@ -62,8 +60,6 @@ class Get extends DocumentGet ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') - ->callback(function (string $databaseId, string $tableId, string $rowId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage) { - parent::action($databaseId, $tableId, $rowId, $queries, $response, $dbForProject, $queueForStatsUsage); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php index 23b70ac19e..29a92413f9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php @@ -7,14 +7,10 @@ use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; -use Appwrite\Utopia\Response as UtopiaResponse; -use MaxMind\Db\Reader; -use Utopia\Database\Database; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; -use Utopia\Locale\Locale; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; @@ -60,8 +56,6 @@ class XList extends DocumentLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->callback(function (string $databaseId, string $tableId, string $rowId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb) { - parent::action($databaseId, $tableId, $rowId, $queries, $response, $dbForProject, $locale, $geodb); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php index 0a83feee38..3c98d3c499 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php @@ -2,8 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; -use Appwrite\Event\Event; -use Appwrite\Event\StatsUsage; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Update as DocumentUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -72,8 +70,6 @@ class Update extends DocumentUpdate ->inject('dbForProject') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->callback(function (string $databaseId, string $tableId, string $rowId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { - parent::action($databaseId, $tableId, $rowId, $data, $permissions, $requestTimestamp, $response, $dbForProject, $queueForEvents, $queueForStatsUsage); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php index f4bdbaa483..c74a87c842 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php @@ -2,14 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; -use Appwrite\Event\StatsUsage; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\XList as DocumentXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; @@ -61,8 +59,6 @@ class XList extends DocumentXList ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') - ->callback(function (string $databaseId, string $tableId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage) { - parent::action($databaseId, $tableId, $queries, $response, $dbForProject, $queueForStatsUsage); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php index e60fbb4ac8..85024e4008 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php @@ -2,14 +2,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Update as CollectionUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -68,8 +66,6 @@ class Update extends CollectionUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback(function (string $databaseId, string $tableId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents) { - parent::action($databaseId, $tableId, $name, $permissions, $documentSecurity, $enabled, $response, $dbForProject, $queueForEvents); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php index 304884cece..e67850e361 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php @@ -8,7 +8,6 @@ use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; @@ -58,8 +57,6 @@ class Get extends CollectionUsageGet ->param('tableId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') - ->callback(function (string $databaseId, string $range, string $tableId, UtopiaResponse $response, Database $dbForProject) { - parent::action($databaseId, $range, $tableId, $response, $dbForProject); - }); + ->callback([$this, 'action']); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php index 10913cd491..b2f102cc55 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php @@ -9,7 +9,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Tables; use Appwrite\Utopia\Response as UtopiaResponse; -use Utopia\Database\Database; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; @@ -59,8 +58,6 @@ class XList extends CollectionXList ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->callback(function (string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject) { - parent::action($databaseId, $queries, $search, $response, $dbForProject); - }); + ->callback([$this, 'action']); } } From d3f1c4f8526914bcd63afb26a8ebff010e7457c0 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 15:10:44 +0530 Subject: [PATCH 104/343] revert: tests to `collections` API. --- .../Services/Migrations/MigrationsBase.php | 16 +-- tests/e2e/Services/Webhooks/WebhooksBase.php | 104 +++++++++--------- .../Webhooks/WebhooksCustomServerTest.php | 44 ++++---- tests/unit/Messaging/MessagingTest.php | 38 +++---- 4 files changed, 101 insertions(+), 101 deletions(-) diff --git a/tests/e2e/Services/Migrations/MigrationsBase.php b/tests/e2e/Services/Migrations/MigrationsBase.php index a40a2156ea..c241b38e3d 100644 --- a/tests/e2e/Services/Migrations/MigrationsBase.php +++ b/tests/e2e/Services/Migrations/MigrationsBase.php @@ -445,7 +445,7 @@ trait MigrationsBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Test Collection', ]); @@ -536,7 +536,7 @@ trait MigrationsBase return [ 'databaseId' => $databaseId, - 'tableId' => $collectionId, + 'collectionId' => $collectionId, ]; } @@ -546,14 +546,14 @@ trait MigrationsBase public function testAppwriteMigrationDatabasesDocument(array $data): void { $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'name' => 'Test Document', ] @@ -927,7 +927,7 @@ trait MigrationsBase 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'name' => 'Test collection', - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -1131,7 +1131,7 @@ trait MigrationsBase return [ 'databaseId' => $databaseId, - 'tableId' => $collectionId, + 'collectionId' => $collectionId, 'migrationId' => $migration['body']['$id'], ]; } @@ -1142,7 +1142,7 @@ trait MigrationsBase public function testImportSuccessful(array $response): void { $databaseId = $response['databaseId']; - $collectionId = $response['tableId']; + $collectionId = $response['collectionId']; $migrationId = $response['migrationId']; $documentsCountInCSV = 100; @@ -1176,7 +1176,7 @@ trait MigrationsBase ]); $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertIsArray($documents['body']['rows']); + $this->assertIsArray($documents['body']['documents']); $this->assertIsNumeric($documents['body']['total']); $this->assertEquals($documentsCountInCSV, $documents['body']['total']); } diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index feb43d17ab..c743810feb 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -61,7 +61,7 @@ trait WebhooksBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Actors', 'permissions' => [ Permission::read(Role::any()), @@ -83,10 +83,10 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -155,12 +155,12 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.columns.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.columns.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.columns.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.columns.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -181,12 +181,12 @@ trait WebhooksBase // $this->assertEquals($webhook['method'], 'DELETE'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.columns.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.columns.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.columns.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.columns.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.attributes.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.attributes.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -211,7 +211,7 @@ trait WebhooksBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'firstName' => 'Chris', 'lastName' => 'Evans', @@ -234,16 +234,16 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -254,7 +254,7 @@ trait WebhooksBase $this->assertIsArray($webhook['data']['$permissions']); $this->assertCount(3, $webhook['data']['$permissions']); - $data['rowId'] = $document['body']['$id']; + $data['documentId'] = $document['body']['$id']; return $data; } @@ -270,7 +270,7 @@ trait WebhooksBase /** * Test for SUCCESS */ - $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $data['rowId'], array_merge([ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $actorsId . '/documents/' . $data['documentId'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -296,16 +296,16 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -335,7 +335,7 @@ trait WebhooksBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'firstName' => 'Bradly', 'lastName' => 'Cooper', @@ -366,16 +366,16 @@ trait WebhooksBase $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.documents.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.*.documents.{$documentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -1119,7 +1119,7 @@ trait WebhooksBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'newCollection' . $i, 'permissions' => [ Permission::read(Role::any()), diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php index 83a29b741f..d2f132e960 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php @@ -48,10 +48,10 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -79,7 +79,7 @@ class WebhooksCustomServerTest extends Scope ]), [ 'key' => 'fullname', 'type' => 'key', - 'columns' => ['lastName', 'firstName'], + 'attributes' => ['lastName', 'firstName'], 'orders' => ['ASC', 'ASC'], ]); @@ -96,12 +96,12 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.indexes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.indexes.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -121,12 +121,12 @@ class WebhooksCustomServerTest extends Scope // $this->assertEquals($webhook['method'], 'DELETE'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.indexes.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.indexes.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$actorsId}.indexes.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -159,7 +159,7 @@ class WebhooksCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Demo', 'permissions' => [ Permission::read(Role::any()), @@ -189,10 +189,10 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("databases.{$databaseId}.tables.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); diff --git a/tests/unit/Messaging/MessagingTest.php b/tests/unit/Messaging/MessagingTest.php index 2cb15c5750..c2b6490869 100644 --- a/tests/unit/Messaging/MessagingTest.php +++ b/tests/unit/Messaging/MessagingTest.php @@ -35,7 +35,7 @@ class MessagingTest extends TestCase Role::team(ID::custom('def'))->toString(), Role::team(ID::custom('def'), 'guest')->toString(), ], - ['files' => 0, 'rows' => 0, 'rows.789' => 0, 'account.123' => 0] + ['files' => 0, 'documents' => 0, 'documents.789' => 0, 'account.123' => 0] ); $event = [ @@ -115,13 +115,13 @@ class MessagingTest extends TestCase $this->assertEmpty($receivers); $event['roles'] = [Role::any()->toString()]; - $event['data']['channels'] = ['rows.123']; + $event['data']['channels'] = ['documents.123']; $receivers = $realtime->getSubscribers($event); $this->assertEmpty($receivers); - $event['data']['channels'] = ['rows.789']; + $event['data']['channels'] = ['documents.789']; $receivers = $realtime->getSubscribers($event); @@ -153,8 +153,8 @@ class MessagingTest extends TestCase $channels = [ 0 => 'files', - 1 => 'rows', - 2 => 'rows.789', + 1 => 'documents', + 2 => 'documents.789', 3 => 'account', 4 => 'account.456' ]; @@ -162,8 +162,8 @@ class MessagingTest extends TestCase $channels = Realtime::convertChannels($channels, $user->getId()); $this->assertCount(4, $channels); $this->assertArrayHasKey('files', $channels); - $this->assertArrayHasKey('rows', $channels); - $this->assertArrayHasKey('rows.789', $channels); + $this->assertArrayHasKey('documents', $channels); + $this->assertArrayHasKey('documents.789', $channels); $this->assertArrayHasKey('account', $channels); $this->assertArrayNotHasKey('account.456', $channels); } @@ -190,8 +190,8 @@ class MessagingTest extends TestCase ]); $channels = [ 0 => 'files', - 1 => 'rows', - 2 => 'rows.789', + 1 => 'documents', + 2 => 'documents.789', 3 => 'account', 4 => 'account.456' ]; @@ -200,8 +200,8 @@ class MessagingTest extends TestCase $this->assertCount(5, $channels); $this->assertArrayHasKey('files', $channels); - $this->assertArrayHasKey('rows', $channels); - $this->assertArrayHasKey('rows.789', $channels); + $this->assertArrayHasKey('documents', $channels); + $this->assertArrayHasKey('documents.789', $channels); $this->assertArrayHasKey('account.123', $channels); $this->assertArrayHasKey('account', $channels); $this->assertArrayNotHasKey('account.456', $channels); @@ -213,10 +213,10 @@ class MessagingTest extends TestCase * Test Collection Level Permissions */ $result = Realtime::fromPayload( - event: 'databases.database_id.tables.collection_id.rows.document_id.create', + event: 'databases.database_id.collections.collection_id.documents.document_id.create', payload: new Document([ '$id' => ID::custom('test'), - '$collection' => ID::custom('table'), + '$collection' => ID::custom('collection'), '$permissions' => [ Permission::read(Role::team('123abc')), Permission::update(Role::team('123abc')), @@ -226,8 +226,8 @@ class MessagingTest extends TestCase database: new Document([ '$id' => ID::custom('database'), ]), - table: new Document([ - '$id' => ID::custom('table'), + collection: new Document([ + '$id' => ID::custom('collection'), '$permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -243,10 +243,10 @@ class MessagingTest extends TestCase * Test Document Level Permissions */ $result = Realtime::fromPayload( - event: 'databases.database_id.tables.collection_id.rows.document_id.create', + event: 'databases.database_id.collections.collection_id.documents.document_id.create', payload: new Document([ '$id' => ID::custom('test'), - '$collection' => ID::custom('table'), + '$collection' => ID::custom('collection'), '$permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -256,8 +256,8 @@ class MessagingTest extends TestCase database: new Document([ '$id' => ID::custom('database'), ]), - table: new Document([ - '$id' => ID::custom('table'), + collection: new Document([ + '$id' => ID::custom('collection'), '$permissions' => [ Permission::read(Role::team('123abc')), Permission::update(Role::team('123abc')), From 94fbf19e546b30b0154eefd7907486d1e301c73b Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 15:11:14 +0530 Subject: [PATCH 105/343] fix|add: tables api tests to realtime. --- .../Realtime/RealtimeConsoleClientTest.php | 398 +++++++++++++++++- .../Realtime/RealtimeCustomClientTest.php | 276 ++++++------ 2 files changed, 513 insertions(+), 161 deletions(-) diff --git a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php index bb21ef8619..a81baf5aaa 100644 --- a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php @@ -123,9 +123,8 @@ class RealtimeConsoleClientTest extends Scope $client->close(); } - public function testAttributes(): array + public function testAttributesCollectionsAPI(): array { - $user = $this->getUser(); $projectId = 'console'; $client = $this->getWebsocket(['console'], [ @@ -162,7 +161,7 @@ class RealtimeConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Actors', 'permissions' => [ Permission::read(Role::any()), @@ -184,13 +183,128 @@ class RealtimeConsoleClientTest extends Scope ]); $projectId = $this->getProject()['$id']; - $attributeKey = $name['body']['key']; - $this->assertEquals($name['headers']['status-code'], 202); - $this->assertEquals($name['body']['key'], 'name'); - $this->assertEquals($name['body']['type'], 'string'); - $this->assertEquals($name['body']['size'], 256); - $this->assertEquals($name['body']['required'], true); + $this->assertEquals(202, $name['headers']['status-code']); + $this->assertEquals('name', $name['body']['key']); + $this->assertEquals('string', $name['body']['type']); + $this->assertEquals(256, $name['body']['size']); + $this->assertTrue($name['body']['required']); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('event', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertArrayHasKey('timestamp', $response['data']); + $this->assertCount(2, $response['data']['channels']); + $this->assertContains('console', $response['data']['channels']); + $this->assertContains("projects.{$projectId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.attributes.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.attributes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}", $response['data']['events']); + $this->assertContains("databases.*", $response['data']['events']); + $this->assertNotEmpty($response['data']['payload']); + $this->assertEquals('processing', $response['data']['payload']['status']); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('event', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertArrayHasKey('timestamp', $response['data']); + $this->assertCount(2, $response['data']['channels']); + $this->assertContains('console', $response['data']['channels']); + $this->assertContains("projects.{$projectId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.attributes.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.attributes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}", $response['data']['events']); + $this->assertContains("databases.*", $response['data']['events']); + $this->assertNotEmpty($response['data']['payload']); + $this->assertEquals('available', $response['data']['payload']['status']); + + $client->close(); + + return ['actorsId' => $actorsId, 'databaseId' => $databaseId]; + } + + public function testAttributesTablesAPI(): array + { + $projectId = 'console'; + + $client = $this->getWebsocket(['console'], [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + ], $projectId); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertCount(1, $response['data']['channels']); + $this->assertContains('console', $response['data']['channels']); + $this->assertNotEmpty($response['data']['user']); + + /** + * Create database + */ + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'databaseId' => ID::unique(), + 'name' => 'Actors DB', + ]); + + $databaseId = $database['body']['$id']; + + /** + * Test Attributes + */ + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'tableId' => ID::unique(), + 'name' => 'Actors', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $actorsId = $actors['body']['$id']; + + $name = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actorsId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $projectId = $this->getProject()['$id']; + + $this->assertEquals(202, $name['headers']['status-code']); + $this->assertEquals('name', $name['body']['key']); + $this->assertEquals('string', $name['body']['type']); + $this->assertEquals(256, $name['body']['size']); + $this->assertTrue($name['body']['required']); + $response = json_decode($client->receive(), true); $this->assertArrayHasKey('type', $response); @@ -235,15 +349,13 @@ class RealtimeConsoleClientTest extends Scope $client->close(); - $data = ['actorsId' => $actorsId, 'databaseId' => $databaseId]; - - return $data; + return ['actorsId' => $actorsId, 'databaseId' => $databaseId]; } /** - * @depends testAttributes + * @depends testAttributesCollectionsAPI */ - public function testIndexes(array $data) + public function testIndexesCollectionAPI(array $data) { $projectId = 'console'; $actorsId = $data['actorsId']; @@ -269,6 +381,90 @@ class RealtimeConsoleClientTest extends Scope $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actorsId . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'key' => 'key_name', + 'type' => 'key', + 'attributes' => [ + 'name', + ], + ]); + + $this->assertEquals(202, $index['headers']['status-code']); + + $projectId = $this->getProject()['$id']; + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('event', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertArrayHasKey('timestamp', $response['data']); + $this->assertCount(2, $response['data']['channels']); + $this->assertContains('console', $response['data']['channels']); + $this->assertContains("projects.{$projectId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.indexes.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertNotEmpty($response['data']['payload']); + $this->assertEquals('processing', $response['data']['payload']['status']); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('event', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertArrayHasKey('timestamp', $response['data']); + $this->assertCount(2, $response['data']['channels']); + $this->assertContains('console', $response['data']['channels']); + $this->assertContains("projects.{$projectId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.indexes.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertNotEmpty($response['data']['payload']); + $this->assertEquals('available', $response['data']['payload']['status']); + + $client->close(); + + return $data; + } + + /** + * @depends testAttributesTablesAPI + */ + public function testIndexesTablesAPI(array $data) + { + $projectId = 'console'; + $actorsId = $data['actorsId']; + $databaseId = $data['databaseId']; + $client = $this->getWebsocket(['console'], [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + ], $projectId); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertCount(1, $response['data']['channels']); + $this->assertContains('console', $response['data']['channels']); + $this->assertNotEmpty($response['data']['user']); + + /** + * Test Indexes + */ + $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actorsId . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'key' => 'key_name', 'type' => 'key', @@ -277,10 +473,9 @@ class RealtimeConsoleClientTest extends Scope ], ]); - $this->assertEquals($index['headers']['status-code'], 202); + $this->assertEquals(202, $index['headers']['status-code']); $projectId = $this->getProject()['$id']; - $indexKey = $index['body']['key']; $response = json_decode($client->receive(), true); @@ -326,9 +521,9 @@ class RealtimeConsoleClientTest extends Scope } /** - * @depends testIndexes + * @depends testIndexesCollectionAPI */ - public function testDeleteIndex(array $data) + public function testDeleteIndexCollectionsAPI(array $data) { $actorsId = $data['actorsId']; $projectId = 'console'; @@ -360,7 +555,88 @@ class RealtimeConsoleClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals($attribute['headers']['status-code'], 204); + $this->assertEquals(204, $attribute['headers']['status-code']); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('event', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertArrayHasKey('timestamp', $response['data']); + $this->assertCount(2, $response['data']['channels']); + $this->assertContains('console', $response['data']['channels']); + $this->assertContains("projects.{$projectId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.indexes.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertNotEmpty($response['data']['payload']); + + /** Delete index generates two events. One from the API and one from the database worker */ + $response = json_decode($client->receive(), true); + + + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('event', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertArrayHasKey('timestamp', $response['data']); + $this->assertCount(2, $response['data']['channels']); + $this->assertContains('console', $response['data']['channels']); + $this->assertContains("projects.{$projectId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.indexes.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.indexes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertNotEmpty($response['data']['payload']); + + $client->close(); + + return $data; + } + + /** + * @depends testIndexesTablesAPI + */ + public function testDeleteIndexTablesAPI(array $data) + { + $projectId = 'console'; + $actorsId = $data['actorsId']; + $databaseId = $data['databaseId']; + + $client = $this->getWebsocket(['console'], [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + ], $projectId); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertCount(1, $response['data']['channels']); + $this->assertContains('console', $response['data']['channels']); + $this->assertNotEmpty($response['data']['user']); + + $projectId = $this->getProject()['$id']; + + /** + * Test Delete Index + */ + $indexKey = 'key_name'; + $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $actorsId . '/indexes/' . $indexKey, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(204, $attribute['headers']['status-code']); $response = json_decode($client->receive(), true); @@ -382,6 +658,7 @@ class RealtimeConsoleClientTest extends Scope /** Delete index generates two events. One from the API and one from the database worker */ $response = json_decode($client->receive(), true); + $this->assertArrayHasKey('type', $response); $this->assertArrayHasKey('data', $response); $this->assertEquals('event', $response['type']); @@ -404,12 +681,12 @@ class RealtimeConsoleClientTest extends Scope } /** - * @depends testDeleteIndex + * @depends testDeleteIndexCollectionsAPI */ - public function testDeleteAttribute(array $data) + public function testDeleteAttributeCollectionsAPI(array $data) { - $actorsId = $data['actorsId']; $projectId = 'console'; + $actorsId = $data['actorsId']; $databaseId = $data['databaseId']; $client = $this->getWebsocket(['console'], [ @@ -438,7 +715,82 @@ class RealtimeConsoleClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals($attribute['headers']['status-code'], 204); + $this->assertEquals(204, $attribute['headers']['status-code']); + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('event', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertArrayHasKey('timestamp', $response['data']); + $this->assertCount(2, $response['data']['channels']); + $this->assertContains('console', $response['data']['channels']); + $this->assertContains("projects.{$projectId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.attributes.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.attributes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertNotEmpty($response['data']['payload']); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('event', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertArrayHasKey('timestamp', $response['data']); + $this->assertCount(2, $response['data']['channels']); + $this->assertContains('console', $response['data']['channels']); + $this->assertContains("projects.{$projectId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.attributes.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.attributes.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); + $this->assertNotEmpty($response['data']['payload']); + + $client->close(); + } + + /** + * @depends testDeleteIndexTablesAPI + */ + public function testDeleteAttributeTablesAPI(array $data) + { + $projectId = 'console'; + $actorsId = $data['actorsId']; + $databaseId = $data['databaseId']; + + $client = $this->getWebsocket(['console'], [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + ], $projectId); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('connected', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertCount(1, $response['data']['channels']); + $this->assertContains('console', $response['data']['channels']); + $this->assertNotEmpty($response['data']['user']); + + $attributeKey = 'name'; + $projectId = $this->getProject()['$id']; + + /** + * Test Delete Attribute + */ + $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['actorsId'] . '/columns/' . $attributeKey, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(204, $attribute['headers']['status-code']); $response = json_decode($client->receive(), true); $this->assertArrayHasKey('type', $response); diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index eef7978a0e..dab096c316 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -31,7 +31,7 @@ class RealtimeCustomClientTest extends Scope 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session ]; - $client = $this->getWebsocket(['rows'], $headers); + $client = $this->getWebsocket(['documents'], $headers); $response = json_decode($client->receive(), true); $this->assertArrayHasKey('type', $response); @@ -40,7 +40,7 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']['user']); $this->assertCount(1, $response['data']['channels']); - $this->assertContains('rows', $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); $this->assertEquals($userId, $response['data']['user']['$id']); $client->close(); @@ -60,7 +60,7 @@ class RealtimeCustomClientTest extends Scope $client->close(); - $client = $this->getWebsocket(['account', 'rows', 'account.123'], $headers); + $client = $this->getWebsocket(['account', 'documents', 'account.123'], $headers); $response = json_decode($client->receive(), true); $this->assertArrayHasKey('type', $response); @@ -69,7 +69,7 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']['user']); $this->assertCount(3, $response['data']['channels']); - $this->assertContains('rows', $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); $this->assertContains('account', $response['data']['channels']); $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertEquals($userId, $response['data']['user']['$id']); @@ -80,12 +80,12 @@ class RealtimeCustomClientTest extends Scope 'account', 'files', 'files.1', - 'tables', - 'tables.1.rows', - 'tables.2.rows', - 'rows', - 'tables.1.rows.1', - 'tables.2.rows.2', + 'collections', + 'collections.1.documents', + 'collections.2.documents', + 'documents', + 'collections.1.documents.1', + 'collections.2.documents.2', ], $headers); $response = json_decode($client->receive(), true); @@ -100,12 +100,12 @@ class RealtimeCustomClientTest extends Scope $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains('files', $response['data']['channels']); $this->assertContains('files.1', $response['data']['channels']); - $this->assertContains('tables', $response['data']['channels']); - $this->assertContains('tables.1.rows', $response['data']['channels']); - $this->assertContains('tables.2.rows', $response['data']['channels']); - $this->assertContains('rows', $response['data']['channels']); - $this->assertContains('tables.1.rows.1', $response['data']['channels']); - $this->assertContains('tables.2.rows.2', $response['data']['channels']); + $this->assertContains('collections', $response['data']['channels']); + $this->assertContains('collections.1.documents', $response['data']['channels']); + $this->assertContains('collections.2.documents', $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertContains('collections.1.documents.1', $response['data']['channels']); + $this->assertContains('collections.2.documents.2', $response['data']['channels']); $this->assertEquals($userId, $response['data']['user']['$id']); $client->close(); @@ -245,7 +245,7 @@ class RealtimeCustomClientTest extends Scope /** * Test for FAILURE */ - $client = $this->getWebsocket(['rows'], ['origin' => 'http://appwrite.unknown']); + $client = $this->getWebsocket(['documents'], ['origin' => 'http://appwrite.unknown']); $payload = json_decode($client->receive(), true); $this->assertArrayHasKey('type', $payload); @@ -675,7 +675,7 @@ class RealtimeCustomClientTest extends Scope $session = $user['session'] ?? ''; $projectId = $this->getProject()['$id']; - $client = $this->getWebsocket(['rows', 'tables'], [ + $client = $this->getWebsocket(['documents', 'collections'], [ 'origin' => 'http://localhost', 'cookie' => 'a_session_' . $projectId . '=' . $session ]); @@ -687,8 +687,8 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('connected', $response['type']); $this->assertNotEmpty($response['data']); $this->assertCount(2, $response['data']['channels']); - $this->assertContains('rows', $response['data']['channels']); - $this->assertContains('tables', $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertContains('collections', $response['data']['channels']); $this->assertNotEmpty($response['data']['user']); $this->assertEquals($user['$id'], $response['data']['user']['$id']); @@ -714,7 +714,7 @@ class RealtimeCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Actors', 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), @@ -734,11 +734,11 @@ class RealtimeCustomClientTest extends Scope 'required' => true, ]); - $this->assertEquals($name['headers']['status-code'], 202); - $this->assertEquals($name['body']['key'], 'name'); - $this->assertEquals($name['body']['type'], 'string'); - $this->assertEquals($name['body']['size'], 256); - $this->assertEquals($name['body']['required'], true); + $this->assertEquals(202, $name['headers']['status-code']); + $this->assertEquals('name', $name['body']['key']); + $this->assertEquals('string', $name['body']['type']); + $this->assertEquals(256, $name['body']['size']); + $this->assertTrue($name['body']['required']); sleep(2); @@ -749,7 +749,7 @@ class RealtimeCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'name' => 'Chris Evans' ], @@ -769,24 +769,24 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(6, $response['data']['channels']); // includes old and new channels - $this->assertContains('rows', $response['data']['channels']); - $this->assertContains('databases.' . $databaseId . '.tables.' . $actorsId . '.rows.' . $documentId, $response['data']['channels']); - $this->assertContains('databases.' . $databaseId . '.tables.' . $actorsId . '.rows', $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.*.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); + $this->assertCount(3, $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertContains('databases.' . $databaseId . '.collections.' . $actorsId . '.documents.' . $documentId, $response['data']['channels']); + $this->assertContains('databases.' . $databaseId . '.collections.' . $actorsId . '.documents', $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); - $this->assertEquals($response['data']['payload']['name'], 'Chris Evans'); + $this->assertEquals('Chris Evans', $response['data']['payload']['name']); /** * Test Document Update @@ -795,7 +795,7 @@ class RealtimeCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'name' => 'Chris Evans 2' ], @@ -813,25 +813,25 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(6, $response['data']['channels']); // includes old and new channels - $this->assertContains('rows', $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); + $this->assertCount(3, $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); - $this->assertEquals($response['data']['payload']['name'], 'Chris Evans 2'); + $this->assertEquals('Chris Evans 2', $response['data']['payload']['name']); /** * Test Document Delete @@ -840,7 +840,7 @@ class RealtimeCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'name' => 'Bradley Cooper' ], @@ -867,24 +867,24 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(6, $response['data']['channels']); // includes old and new channels - $this->assertContains('rows', $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.*.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); + $this->assertCount(3, $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); - $this->assertEquals($response['data']['payload']['name'], 'Bradley Cooper'); + $this->assertEquals('Bradley Cooper', $response['data']['payload']['name']); $client->close(); } @@ -895,7 +895,7 @@ class RealtimeCustomClientTest extends Scope $session = $user['session'] ?? ''; $projectId = $this->getProject()['$id']; - $client = $this->getWebsocket(['rows', 'tables'], [ + $client = $this->getWebsocket(['documents', 'collections'], [ 'origin' => 'http://localhost', 'cookie' => 'a_session_' . $projectId . '=' . $session ]); @@ -907,8 +907,8 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('connected', $response['type']); $this->assertNotEmpty($response['data']); $this->assertCount(2, $response['data']['channels']); - $this->assertContains('rows', $response['data']['channels']); - $this->assertContains('tables', $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertContains('collections', $response['data']['channels']); $this->assertNotEmpty($response['data']['user']); $this->assertEquals($user['$id'], $response['data']['user']['$id']); @@ -934,7 +934,7 @@ class RealtimeCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Actors', 'permissions' => [ Permission::read(Role::any()), @@ -956,11 +956,11 @@ class RealtimeCustomClientTest extends Scope 'required' => true, ]); - $this->assertEquals($name['headers']['status-code'], 202); - $this->assertEquals($name['body']['key'], 'name'); - $this->assertEquals($name['body']['type'], 'string'); - $this->assertEquals($name['body']['size'], 256); - $this->assertEquals($name['body']['required'], true); + $this->assertEquals(202, $name['headers']['status-code']); + $this->assertEquals('name', $name['body']['key']); + $this->assertEquals('string', $name['body']['type']); + $this->assertEquals(256, $name['body']['size']); + $this->assertTrue($name['body']['required']); sleep(2); @@ -971,7 +971,7 @@ class RealtimeCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'name' => 'Chris Evans' ], @@ -987,24 +987,24 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(6, $response['data']['channels']); // includes old and new channels - $this->assertContains('rows', $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.*.create", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); + $this->assertCount(3, $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.*.create", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); - $this->assertEquals($response['data']['payload']['name'], 'Chris Evans'); + $this->assertEquals('Chris Evans', $response['data']['payload']['name']); /** * Test Document Update @@ -1026,25 +1026,25 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(6, $response['data']['channels']); // includes old and new channels - $this->assertContains('rows', $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.*.update", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); + $this->assertCount(3, $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.*.update", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); - $this->assertEquals($response['data']['payload']['name'], 'Chris Evans 2'); + $this->assertEquals('Chris Evans 2', $response['data']['payload']['name']); /** * Test Document Delete @@ -1053,7 +1053,7 @@ class RealtimeCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rowId' => ID::unique(), + 'documentId' => ID::unique(), 'data' => [ 'name' => 'Bradley Cooper' ], @@ -1076,24 +1076,24 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(6, $response['data']['channels']); // includes old and new channels - $this->assertContains('rows', $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows", $response['data']['channels']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}.rows.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.{$actorsId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.{$documentId}", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.*.delete", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*.rows.*", $response['data']['events']); - $this->assertContains("databases.{$databaseId}.tables.*", $response['data']['events']); + $this->assertCount(3, $response['data']['channels']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.{$documentId}", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.*.delete", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*.documents.*", $response['data']['events']); + $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); - $this->assertEquals($response['data']['payload']['name'], 'Bradley Cooper'); + $this->assertEquals('Bradley Cooper', $response['data']['payload']['name']); $client->close(); } @@ -1293,7 +1293,7 @@ class RealtimeCustomClientTest extends Scope $functionId = $function['body']['$id'] ?? ''; - $this->assertEquals($function['headers']['status-code'], 201); + $this->assertEquals(201, $function['headers']['status-code']); $this->assertNotEmpty($function['body']['$id']); $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ @@ -1308,7 +1308,7 @@ class RealtimeCustomClientTest extends Scope $deploymentId = $deployment['body']['$id'] ?? ''; - $this->assertEquals($deployment['headers']['status-code'], 202); + $this->assertEquals(202, $deployment['headers']['status-code']); $this->assertNotEmpty($deployment['body']['$id']); // Poll until deployment is built @@ -1468,7 +1468,7 @@ class RealtimeCustomClientTest extends Scope 'name' => 'Manchester' ]); - $this->assertEquals($team['headers']['status-code'], 200); + $this->assertEquals(200, $team['headers']['status-code']); $this->assertNotEmpty($team['body']['$id']); $response = json_decode($client->receive(), true); @@ -1500,9 +1500,9 @@ class RealtimeCustomClientTest extends Scope ] ]); - $this->assertEquals($team['headers']['status-code'], 200); - $this->assertEquals($team['body']['funcKey1'], 'funcValue1'); - $this->assertEquals($team['body']['funcKey2'], 'funcValue2'); + $this->assertEquals(200, $team['headers']['status-code']); + $this->assertEquals('funcValue1', $team['body']['funcKey1']); + $this->assertEquals('funcValue2', $team['body']['funcKey2']); $response = json_decode($client->receive(), true); @@ -1521,8 +1521,8 @@ class RealtimeCustomClientTest extends Scope $this->assertContains("teams.*.update", $response['data']['events']); $this->assertContains("teams.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); - $this->assertEquals($response['data']['payload']['funcKey1'], 'funcValue1'); - $this->assertEquals($response['data']['payload']['funcKey2'], 'funcValue2'); + $this->assertEquals('funcValue1', $response['data']['payload']['funcKey1']); + $this->assertEquals('funcValue2', $response['data']['payload']['funcKey2']); $client->close(); From 1756acd89cac2301b888da421812710608034607 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 15:16:10 +0530 Subject: [PATCH 106/343] fix: realtime channel count. --- .../Services/Realtime/RealtimeCustomClientTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index dab096c316..1106c74ee0 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -769,7 +769,7 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(3, $response['data']['channels']); + $this->assertCount(6, $response['data']['channels']); $this->assertContains('documents', $response['data']['channels']); $this->assertContains('databases.' . $databaseId . '.collections.' . $actorsId . '.documents.' . $documentId, $response['data']['channels']); $this->assertContains('databases.' . $databaseId . '.collections.' . $actorsId . '.documents', $response['data']['channels']); @@ -813,7 +813,7 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(3, $response['data']['channels']); + $this->assertCount(6, $response['data']['channels']); $this->assertContains('documents', $response['data']['channels']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); @@ -867,7 +867,7 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(3, $response['data']['channels']); + $this->assertCount(6, $response['data']['channels']); $this->assertContains('documents', $response['data']['channels']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); @@ -987,7 +987,7 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(3, $response['data']['channels']); + $this->assertCount(6, $response['data']['channels']); $this->assertContains('documents', $response['data']['channels']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); @@ -1026,7 +1026,7 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(3, $response['data']['channels']); + $this->assertCount(6, $response['data']['channels']); $this->assertContains('documents', $response['data']['channels']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); @@ -1076,7 +1076,7 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('event', $response['type']); $this->assertNotEmpty($response['data']); $this->assertArrayHasKey('timestamp', $response['data']); - $this->assertCount(3, $response['data']['channels']); + $this->assertCount(6, $response['data']['channels']); $this->assertContains('documents', $response['data']['channels']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents.{$documentId}", $response['data']['channels']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.documents", $response['data']['channels']); From f16ba8dee3d8c0e3924b9f13c25ee574d59693d3 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 17:25:36 +0530 Subject: [PATCH 107/343] add: table api tests. --- .github/workflows/tests.yml | 2 + .../Collections/Documents/Create.php | 1 - .../Databases/Tables/DatabasesBase.php | 4919 +++++++++++++++++ .../Tables/DatabasesConsoleClientTest.php | 336 ++ .../Tables/DatabasesCustomClientTest.php | 893 +++ .../Tables/DatabasesCustomServerTest.php | 4113 ++++++++++++++ .../Tables/DatabasesPermissionsGuestTest.php | 278 + .../Tables/DatabasesPermissionsMemberTest.php | 271 + .../Tables/DatabasesPermissionsScope.php | 87 + .../Tables/DatabasesPermissionsTeamTest.php | 208 + 10 files changed, 11107 insertions(+), 1 deletion(-) create mode 100644 tests/e2e/Services/Databases/Tables/DatabasesBase.php create mode 100644 tests/e2e/Services/Databases/Tables/DatabasesConsoleClientTest.php create mode 100644 tests/e2e/Services/Databases/Tables/DatabasesCustomClientTest.php create mode 100644 tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php create mode 100644 tests/e2e/Services/Databases/Tables/DatabasesPermissionsGuestTest.php create mode 100644 tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php create mode 100644 tests/e2e/Services/Databases/Tables/DatabasesPermissionsScope.php create mode 100644 tests/e2e/Services/Databases/Tables/DatabasesPermissionsTeamTest.php diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4775272185..335e46c16b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -146,6 +146,7 @@ jobs: Avatars, Console, Databases/Collections, + Databases/Tables, Functions, FunctionsSchedule, GraphQL, @@ -214,6 +215,7 @@ jobs: Avatars, Console, Databases/Collections, + Databases/Tables, Functions, FunctionsSchedule, GraphQL, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index 4c63837d57..a8f1561f84 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -253,7 +253,6 @@ class Create extends Action throw new Exception($this->getParentNotFoundException()); } - // Add $collectionId and $databaseId for all documents $processDocument = function (Document $table, Document $document) use (&$processDocument, $dbForProject, $database) { $document->setAttribute('$databaseId', $database->getId()); diff --git a/tests/e2e/Services/Databases/Tables/DatabasesBase.php b/tests/e2e/Services/Databases/Tables/DatabasesBase.php new file mode 100644 index 0000000000..5532bbac46 --- /dev/null +++ b/tests/e2e/Services/Databases/Tables/DatabasesBase.php @@ -0,0 +1,4919 @@ +client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Test Database' + ]); + + $this->assertNotEmpty($database['body']['$id']); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('Test Database', $database['body']['name']); + + return ['databaseId' => $database['body']['$id']]; + } + + /** + * @depends testCreateDatabase + */ + public function testCreateCollection(array $data): array + { + $databaseId = $data['databaseId']; + /** + * Test for SUCCESS + */ + $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Movies', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + ], + ]); + + $this->assertEquals(201, $movies['headers']['status-code']); + $this->assertEquals($movies['body']['name'], 'Movies'); + + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Actors', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + ], + ]); + + $this->assertEquals(201, $actors['headers']['status-code']); + $this->assertEquals($actors['body']['name'], 'Actors'); + + return [ + 'databaseId' => $databaseId, + 'moviesId' => $movies['body']['$id'], + 'actorsId' => $actors['body']['$id'], + ]; + } + + /** + * @depends testCreateCollection + */ + public function testConsoleProject(array $data) + { + if ($this->getSide() === 'server') { + // Server side can't get past the invalid key check anyway + $this->expectNotToPerformAssertions(); + return; + } + + $response = $this->client->call( + Client::METHOD_GET, + '/databases/console/tables/' . $data['moviesId'] . '/rows', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => 'console', + ], $this->getHeaders()) + ); + + $this->assertEquals(401, $response['headers']['status-code']); + $this->assertEquals('general_access_forbidden', $response['body']['type']); + $this->assertEquals('This endpoint is not available for the console project. The Appwrite Console is a reserved project ID and cannot be used with the Appwrite SDKs and APIs. Please check if your project ID is correct.', $response['body']['message']); + + $response = $this->client->call( + Client::METHOD_GET, + '/databases/console/tables/' . $data['moviesId'] . '/rows', + array_merge([ + 'content-type' => 'application/json', + // 'x-appwrite-project' => '', empty header + ], $this->getHeaders()) + ); + $this->assertEquals(401, $response['headers']['status-code']); + $this->assertEquals('No Appwrite project was specified. Please specify your project ID when initializing your Appwrite SDK.', $response['body']['message']); + } + + /** + * @depends testCreateCollection + */ + public function testDisableCollection(array $data): void + { + $databaseId = $data['databaseId']; + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'name' => 'Movies', + 'enabled' => false, + 'documentSecurity' => true, + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertFalse($response['body']['enabled']); + + if ($this->getSide() === 'client') { + $responseCreateDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Captain America', + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ], + ]); + + $this->assertEquals(404, $responseCreateDocument['headers']['status-code']); + + $responseListDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $responseListDocument['headers']['status-code']); + + $responseGetDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/someID', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $responseGetDocument['headers']['status-code']); + } + + $response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'name' => 'Movies', + 'enabled' => true, + 'documentSecurity' => true, + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertTrue($response['body']['enabled']); + } + + /** + * @depends testCreateCollection + */ + public function testCreateAttributes(array $data): array + { + $databaseId = $data['databaseId']; + + $title = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 256, + 'required' => true, + ]); + + $description = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'description', + 'size' => 512, + 'required' => false, + 'default' => '', + ]); + + $tagline = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'tagline', + 'size' => 512, + 'required' => false, + 'default' => '', + ]); + + $releaseYear = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'releaseYear', + 'required' => true, + 'min' => 1900, + 'max' => 2200, + ]); + + $duration = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'duration', + 'required' => false, + 'min' => 60, + ]); + + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'actors', + 'size' => 256, + 'required' => false, + 'array' => true, + ]); + + $datetime = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/columns/datetime', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'birthDay', + 'required' => false, + ]); + + $relationship = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $data['actorsId'], + 'type' => 'oneToMany', + 'twoWay' => true, + 'key' => 'starringActors', + 'twoWayKey' => 'movie' + ]); + + $integers = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'integers', + 'required' => false, + 'array' => true, + 'min' => 10, + 'max' => 99, + ]); + + $this->assertEquals(202, $title['headers']['status-code']); + $this->assertEquals($title['body']['key'], 'title'); + $this->assertEquals($title['body']['type'], 'string'); + $this->assertEquals($title['body']['size'], 256); + $this->assertEquals($title['body']['required'], true); + + $this->assertEquals(202, $description['headers']['status-code']); + $this->assertEquals($description['body']['key'], 'description'); + $this->assertEquals($description['body']['type'], 'string'); + $this->assertEquals($description['body']['size'], 512); + $this->assertEquals($description['body']['required'], false); + $this->assertEquals($description['body']['default'], ''); + + $this->assertEquals(202, $tagline['headers']['status-code']); + $this->assertEquals($tagline['body']['key'], 'tagline'); + $this->assertEquals($tagline['body']['type'], 'string'); + $this->assertEquals($tagline['body']['size'], 512); + $this->assertEquals($tagline['body']['required'], false); + $this->assertEquals($tagline['body']['default'], ''); + + $this->assertEquals(202, $releaseYear['headers']['status-code']); + $this->assertEquals($releaseYear['body']['key'], 'releaseYear'); + $this->assertEquals($releaseYear['body']['type'], 'integer'); + $this->assertEquals($releaseYear['body']['required'], true); + + $this->assertEquals(202, $duration['headers']['status-code']); + $this->assertEquals($duration['body']['key'], 'duration'); + $this->assertEquals($duration['body']['type'], 'integer'); + $this->assertEquals($duration['body']['required'], false); + + $this->assertEquals(202, $actors['headers']['status-code']); + $this->assertEquals($actors['body']['key'], 'actors'); + $this->assertEquals($actors['body']['type'], 'string'); + $this->assertEquals($actors['body']['size'], 256); + $this->assertEquals($actors['body']['required'], false); + $this->assertEquals($actors['body']['array'], true); + + $this->assertEquals($datetime['headers']['status-code'], 202); + $this->assertEquals($datetime['body']['key'], 'birthDay'); + $this->assertEquals($datetime['body']['type'], 'datetime'); + $this->assertEquals($datetime['body']['required'], false); + + $this->assertEquals($relationship['headers']['status-code'], 202); + $this->assertEquals($relationship['body']['key'], 'starringActors'); + $this->assertEquals($relationship['body']['type'], 'relationship'); + $this->assertEquals($relationship['body']['relatedTable'], $data['actorsId']); + $this->assertEquals($relationship['body']['relationType'], 'oneToMany'); + $this->assertEquals($relationship['body']['twoWay'], true); + $this->assertEquals($relationship['body']['twoWayKey'], 'movie'); + + $this->assertEquals(202, $integers['headers']['status-code']); + $this->assertEquals($integers['body']['key'], 'integers'); + $this->assertEquals($integers['body']['type'], 'integer'); + $this->assertArrayNotHasKey('size', $integers['body']); + $this->assertEquals($integers['body']['required'], false); + $this->assertEquals($integers['body']['array'], true); + + // wait for database worker to create attributes + sleep(2); + + $movies = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertIsArray($movies['body']['columns']); + $this->assertCount(9, $movies['body']['columns']); + $this->assertEquals($movies['body']['columns'][0]['key'], $title['body']['key']); + $this->assertEquals($movies['body']['columns'][1]['key'], $description['body']['key']); + $this->assertEquals($movies['body']['columns'][2]['key'], $tagline['body']['key']); + $this->assertEquals($movies['body']['columns'][3]['key'], $releaseYear['body']['key']); + $this->assertEquals($movies['body']['columns'][4]['key'], $duration['body']['key']); + $this->assertEquals($movies['body']['columns'][5]['key'], $actors['body']['key']); + $this->assertEquals($movies['body']['columns'][6]['key'], $datetime['body']['key']); + $this->assertEquals($movies['body']['columns'][7]['key'], $relationship['body']['key']); + $this->assertEquals($movies['body']['columns'][8]['key'], $integers['body']['key']); + + return $data; + } + + /** + * @depends testCreateAttributes + */ + public function testListAttributes(array $data): void + { + $databaseId = $data['databaseId']; + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/columns', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'queries' => [ + Query::equal('type', ['string'])->toString(), + Query::limit(2)->toString(), + Query::cursorAfter(new Document(['$id' => 'title']))->toString() + ], + ]); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(2, \count($response['body']['columns'])); + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/columns', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'queries' => [Query::select(['key'])->toString()], + ]); + $this->assertEquals(Exception::GENERAL_ARGUMENT_INVALID, $response['body']['type']); + $this->assertEquals(400, $response['headers']['status-code']); + } + + /** + * @depends testCreateDatabase + */ + public function testPatchAttribute(array $data): void + { + $databaseId = $data['databaseId']; + + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'patch', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + ], + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + $this->assertEquals($table['body']['name'], 'patch'); + + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/tables/'.$table['body']['$id'].'/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'required' => true, + 'size' => 100, + ]); + $this->assertEquals(202, $attribute['headers']['status-code']); + $this->assertEquals($attribute['body']['size'], 100); + + sleep(1); + + $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/tables/'.$table['body']['$id'].'/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'titleIndex', + 'type' => 'key', + 'columns' => ['title'], + ]); + $this->assertEquals(202, $index['headers']['status-code']); + + sleep(1); + + /** + * Update attribute size to exceed Index maximum length + */ + $attribute = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/tables/'.$table['body']['$id'].'/columns/string/'.$attribute['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'size' => 1000, + 'required' => true, + 'default' => null, + ]); + + $this->assertEquals(400, $attribute['headers']['status-code']); + $this->assertStringContainsString('Index length is longer than the maximum: 76', $attribute['body']['message']); + } + + public function testUpdateAttributeEnum(): void + { + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Test Database 2' + ]); + + $players = $this->client->call(Client::METHOD_POST, '/databases/' . $database['body']['$id'] . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Players', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + ], + ]); + + // Create enum attribute + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $database['body']['$id'] . '/tables/' . $players['body']['$id'] . '/columns/enum', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'key' => 'position', + 'elements' => ['goalkeeper', 'defender', 'midfielder', 'forward'], + 'required' => true, + 'array' => false, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + $this->assertEquals($attribute['body']['key'], 'position'); + $this->assertEquals($attribute['body']['elements'], ['goalkeeper', 'defender', 'midfielder', 'forward']); + + \sleep(2); + + // Update enum attribute + $attribute = $this->client->call(Client::METHOD_PATCH, '/databases/' . $database['body']['$id'] . '/tables/' . $players['body']['$id'] . '/columns/enum/' . $attribute['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'elements' => ['goalkeeper', 'defender', 'midfielder', 'forward', 'coach'], + 'required' => true, + 'default' => null + ]); + + $this->assertEquals(200, $attribute['headers']['status-code']); + $this->assertEquals($attribute['body']['elements'], ['goalkeeper', 'defender', 'midfielder', 'forward', 'coach']); + } + + /** + * @depends testCreateAttributes + */ + public function testAttributeResponseModels(array $data): array + { + $databaseId = $data['databaseId']; + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Response Models', + // 'permissions' missing on purpose to make sure it's optional + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + $this->assertEquals($table['body']['name'], 'Response Models'); + + $tableId = $table['body']['$id']; + + $columnsPath = "/databases/" . $databaseId . "/tables/{$tableId}/columns"; + + $string = $this->client->call(Client::METHOD_POST, $columnsPath . '/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'string', + 'size' => 16, + 'required' => false, + 'default' => 'default', + ]); + + $email = $this->client->call(Client::METHOD_POST, $columnsPath . '/email', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'email', + 'required' => false, + 'default' => 'default@example.com', + ]); + + $enum = $this->client->call(Client::METHOD_POST, $columnsPath . '/enum', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'enum', + 'elements' => ['yes', 'no', 'maybe'], + 'required' => false, + 'default' => 'maybe', + ]); + + $ip = $this->client->call(Client::METHOD_POST, $columnsPath . '/ip', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'ip', + 'required' => false, + 'default' => '192.0.2.0', + ]); + + $url = $this->client->call(Client::METHOD_POST, $columnsPath . '/url', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'url', + 'required' => false, + 'default' => 'http://example.com', + ]); + + $integer = $this->client->call(Client::METHOD_POST, $columnsPath . '/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'integer', + 'required' => false, + 'min' => 1, + 'max' => 5, + 'default' => 3 + ]); + + $float = $this->client->call(Client::METHOD_POST, $columnsPath . '/float', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'float', + 'required' => false, + 'min' => 1.5, + 'max' => 5.5, + 'default' => 3.5 + ]); + + $boolean = $this->client->call(Client::METHOD_POST, $columnsPath . '/boolean', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'boolean', + 'required' => false, + 'default' => true, + ]); + + $datetime = $this->client->call(Client::METHOD_POST, $columnsPath . '/datetime', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'datetime', + 'required' => false, + 'default' => null, + ]); + + $relationship = $this->client->call(Client::METHOD_POST, $columnsPath . '/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $data['actorsId'], + 'type' => 'oneToMany', + 'twoWay' => true, + 'key' => 'relationship', + 'twoWayKey' => 'twoWayKey' + ]); + + $strings = $this->client->call(Client::METHOD_POST, $columnsPath . '/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'names', + 'size' => 512, + 'required' => false, + 'array' => true, + ]); + + $integers = $this->client->call(Client::METHOD_POST, $columnsPath . '/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'numbers', + 'required' => false, + 'array' => true, + 'min' => 1, + 'max' => 999, + ]); + + $this->assertEquals(202, $string['headers']['status-code']); + $this->assertEquals('string', $string['body']['key']); + $this->assertEquals('string', $string['body']['type']); + $this->assertEquals(false, $string['body']['required']); + $this->assertEquals(false, $string['body']['array']); + $this->assertEquals(16, $string['body']['size']); + $this->assertEquals('default', $string['body']['default']); + + $this->assertEquals(202, $email['headers']['status-code']); + $this->assertEquals('email', $email['body']['key']); + $this->assertEquals('string', $email['body']['type']); + $this->assertEquals(false, $email['body']['required']); + $this->assertEquals(false, $email['body']['array']); + $this->assertEquals('email', $email['body']['format']); + $this->assertEquals('default@example.com', $email['body']['default']); + + $this->assertEquals(202, $enum['headers']['status-code']); + $this->assertEquals('enum', $enum['body']['key']); + $this->assertEquals('string', $enum['body']['type']); + $this->assertEquals(false, $enum['body']['required']); + $this->assertEquals(false, $enum['body']['array']); + $this->assertEquals('enum', $enum['body']['format']); + $this->assertEquals('maybe', $enum['body']['default']); + $this->assertIsArray($enum['body']['elements']); + $this->assertEquals(['yes', 'no', 'maybe'], $enum['body']['elements']); + + $this->assertEquals(202, $ip['headers']['status-code']); + $this->assertEquals('ip', $ip['body']['key']); + $this->assertEquals('string', $ip['body']['type']); + $this->assertEquals(false, $ip['body']['required']); + $this->assertEquals(false, $ip['body']['array']); + $this->assertEquals('ip', $ip['body']['format']); + $this->assertEquals('192.0.2.0', $ip['body']['default']); + + $this->assertEquals(202, $url['headers']['status-code']); + $this->assertEquals('url', $url['body']['key']); + $this->assertEquals('string', $url['body']['type']); + $this->assertEquals(false, $url['body']['required']); + $this->assertEquals(false, $url['body']['array']); + $this->assertEquals('url', $url['body']['format']); + $this->assertEquals('http://example.com', $url['body']['default']); + + $this->assertEquals(202, $integer['headers']['status-code']); + $this->assertEquals('integer', $integer['body']['key']); + $this->assertEquals('integer', $integer['body']['type']); + $this->assertEquals(false, $integer['body']['required']); + $this->assertEquals(false, $integer['body']['array']); + $this->assertEquals(1, $integer['body']['min']); + $this->assertEquals(5, $integer['body']['max']); + $this->assertEquals(3, $integer['body']['default']); + + $this->assertEquals(202, $float['headers']['status-code']); + $this->assertEquals('float', $float['body']['key']); + $this->assertEquals('double', $float['body']['type']); + $this->assertEquals(false, $float['body']['required']); + $this->assertEquals(false, $float['body']['array']); + $this->assertEquals(1.5, $float['body']['min']); + $this->assertEquals(5.5, $float['body']['max']); + $this->assertEquals(3.5, $float['body']['default']); + + $this->assertEquals(202, $boolean['headers']['status-code']); + $this->assertEquals('boolean', $boolean['body']['key']); + $this->assertEquals('boolean', $boolean['body']['type']); + $this->assertEquals(false, $boolean['body']['required']); + $this->assertEquals(false, $boolean['body']['array']); + $this->assertEquals(true, $boolean['body']['default']); + + $this->assertEquals(202, $datetime['headers']['status-code']); + $this->assertEquals('datetime', $datetime['body']['key']); + $this->assertEquals('datetime', $datetime['body']['type']); + $this->assertEquals(false, $datetime['body']['required']); + $this->assertEquals(false, $datetime['body']['array']); + $this->assertEquals(null, $datetime['body']['default']); + + $this->assertEquals(202, $relationship['headers']['status-code']); + $this->assertEquals('relationship', $relationship['body']['key']); + $this->assertEquals('relationship', $relationship['body']['type']); + $this->assertEquals(false, $relationship['body']['required']); + $this->assertEquals(false, $relationship['body']['array']); + $this->assertEquals($data['actorsId'], $relationship['body']['relatedTable']); + $this->assertEquals('oneToMany', $relationship['body']['relationType']); + $this->assertEquals(true, $relationship['body']['twoWay']); + $this->assertEquals('twoWayKey', $relationship['body']['twoWayKey']); + + $this->assertEquals(202, $strings['headers']['status-code']); + $this->assertEquals('names', $strings['body']['key']); + $this->assertEquals('string', $strings['body']['type']); + $this->assertEquals(false, $strings['body']['required']); + $this->assertEquals(true, $strings['body']['array']); + $this->assertEquals(null, $strings['body']['default']); + + $this->assertEquals(202, $integers['headers']['status-code']); + $this->assertEquals('numbers', $integers['body']['key']); + $this->assertEquals('integer', $integers['body']['type']); + $this->assertEquals(false, $integers['body']['required']); + $this->assertEquals(true, $integers['body']['array']); + $this->assertEquals(1, $integers['body']['min']); + $this->assertEquals(999, $integers['body']['max']); + $this->assertEquals(null, $integers['body']['default']); + + // Wait for database worker to create attributes + sleep(5); + + $stringResponse = $this->client->call(Client::METHOD_GET, $columnsPath . '/' . $string['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $emailResponse = $this->client->call(Client::METHOD_GET, $columnsPath . '/' . $email['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $enumResponse = $this->client->call(Client::METHOD_GET, $columnsPath . '/' . $enum['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $ipResponse = $this->client->call(Client::METHOD_GET, $columnsPath . '/' . $ip['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $urlResponse = $this->client->call(Client::METHOD_GET, $columnsPath . '/' . $url['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $integerResponse = $this->client->call(Client::METHOD_GET, $columnsPath . '/' . $integer['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $floatResponse = $this->client->call(Client::METHOD_GET, $columnsPath . '/' . $float['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $booleanResponse = $this->client->call(Client::METHOD_GET, $columnsPath . '/' . $boolean['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $datetimeResponse = $this->client->call(Client::METHOD_GET, $columnsPath . '/' . $datetime['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $relationshipResponse = $this->client->call(Client::METHOD_GET, $columnsPath . '/' . $relationship['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $stringsResponse = $this->client->call(Client::METHOD_GET, $columnsPath . '/' . $strings['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $integersResponse = $this->client->call(Client::METHOD_GET, $columnsPath . '/' . $integers['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $stringResponse['headers']['status-code']); + $this->assertEquals($string['body']['key'], $stringResponse['body']['key']); + $this->assertEquals($string['body']['type'], $stringResponse['body']['type']); + $this->assertEquals('available', $stringResponse['body']['status']); + $this->assertEquals($string['body']['required'], $stringResponse['body']['required']); + $this->assertEquals($string['body']['array'], $stringResponse['body']['array']); + $this->assertEquals(16, $stringResponse['body']['size']); + $this->assertEquals($string['body']['default'], $stringResponse['body']['default']); + + $this->assertEquals(200, $emailResponse['headers']['status-code']); + $this->assertEquals($email['body']['key'], $emailResponse['body']['key']); + $this->assertEquals($email['body']['type'], $emailResponse['body']['type']); + $this->assertEquals('available', $emailResponse['body']['status']); + $this->assertEquals($email['body']['required'], $emailResponse['body']['required']); + $this->assertEquals($email['body']['array'], $emailResponse['body']['array']); + $this->assertEquals($email['body']['format'], $emailResponse['body']['format']); + $this->assertEquals($email['body']['default'], $emailResponse['body']['default']); + + $this->assertEquals(200, $enumResponse['headers']['status-code']); + $this->assertEquals($enum['body']['key'], $enumResponse['body']['key']); + $this->assertEquals($enum['body']['type'], $enumResponse['body']['type']); + $this->assertEquals('available', $enumResponse['body']['status']); + $this->assertEquals($enum['body']['required'], $enumResponse['body']['required']); + $this->assertEquals($enum['body']['array'], $enumResponse['body']['array']); + $this->assertEquals($enum['body']['format'], $enumResponse['body']['format']); + $this->assertEquals($enum['body']['default'], $enumResponse['body']['default']); + $this->assertEquals($enum['body']['elements'], $enumResponse['body']['elements']); + + $this->assertEquals(200, $ipResponse['headers']['status-code']); + $this->assertEquals($ip['body']['key'], $ipResponse['body']['key']); + $this->assertEquals($ip['body']['type'], $ipResponse['body']['type']); + $this->assertEquals('available', $ipResponse['body']['status']); + $this->assertEquals($ip['body']['required'], $ipResponse['body']['required']); + $this->assertEquals($ip['body']['array'], $ipResponse['body']['array']); + $this->assertEquals($ip['body']['format'], $ipResponse['body']['format']); + $this->assertEquals($ip['body']['default'], $ipResponse['body']['default']); + + $this->assertEquals(200, $urlResponse['headers']['status-code']); + $this->assertEquals($url['body']['key'], $urlResponse['body']['key']); + $this->assertEquals($url['body']['type'], $urlResponse['body']['type']); + $this->assertEquals('available', $urlResponse['body']['status']); + $this->assertEquals($url['body']['required'], $urlResponse['body']['required']); + $this->assertEquals($url['body']['array'], $urlResponse['body']['array']); + $this->assertEquals($url['body']['format'], $urlResponse['body']['format']); + $this->assertEquals($url['body']['default'], $urlResponse['body']['default']); + + $this->assertEquals(200, $integerResponse['headers']['status-code']); + $this->assertEquals($integer['body']['key'], $integerResponse['body']['key']); + $this->assertEquals($integer['body']['type'], $integerResponse['body']['type']); + $this->assertEquals('available', $integerResponse['body']['status']); + $this->assertEquals($integer['body']['required'], $integerResponse['body']['required']); + $this->assertEquals($integer['body']['array'], $integerResponse['body']['array']); + $this->assertEquals($integer['body']['min'], $integerResponse['body']['min']); + $this->assertEquals($integer['body']['max'], $integerResponse['body']['max']); + $this->assertEquals($integer['body']['default'], $integerResponse['body']['default']); + + $this->assertEquals(200, $floatResponse['headers']['status-code']); + $this->assertEquals($float['body']['key'], $floatResponse['body']['key']); + $this->assertEquals($float['body']['type'], $floatResponse['body']['type']); + $this->assertEquals('available', $floatResponse['body']['status']); + $this->assertEquals($float['body']['required'], $floatResponse['body']['required']); + $this->assertEquals($float['body']['array'], $floatResponse['body']['array']); + $this->assertEquals($float['body']['min'], $floatResponse['body']['min']); + $this->assertEquals($float['body']['max'], $floatResponse['body']['max']); + $this->assertEquals($float['body']['default'], $floatResponse['body']['default']); + + $this->assertEquals(200, $booleanResponse['headers']['status-code']); + $this->assertEquals($boolean['body']['key'], $booleanResponse['body']['key']); + $this->assertEquals($boolean['body']['type'], $booleanResponse['body']['type']); + $this->assertEquals('available', $booleanResponse['body']['status']); + $this->assertEquals($boolean['body']['required'], $booleanResponse['body']['required']); + $this->assertEquals($boolean['body']['array'], $booleanResponse['body']['array']); + $this->assertEquals($boolean['body']['default'], $booleanResponse['body']['default']); + + $this->assertEquals(200, $datetimeResponse['headers']['status-code']); + $this->assertEquals($datetime['body']['key'], $datetimeResponse['body']['key']); + $this->assertEquals($datetime['body']['type'], $datetimeResponse['body']['type']); + $this->assertEquals('available', $datetimeResponse['body']['status']); + $this->assertEquals($datetime['body']['required'], $datetimeResponse['body']['required']); + $this->assertEquals($datetime['body']['array'], $datetimeResponse['body']['array']); + $this->assertEquals($datetime['body']['default'], $datetimeResponse['body']['default']); + + $this->assertEquals(200, $relationshipResponse['headers']['status-code']); + $this->assertEquals($relationship['body']['key'], $relationshipResponse['body']['key']); + $this->assertEquals($relationship['body']['type'], $relationshipResponse['body']['type']); + $this->assertEquals('available', $relationshipResponse['body']['status']); + $this->assertEquals($relationship['body']['required'], $relationshipResponse['body']['required']); + $this->assertEquals($relationship['body']['array'], $relationshipResponse['body']['array']); + $this->assertEquals($relationship['body']['relatedTable'], $relationshipResponse['body']['relatedTable']); + $this->assertEquals($relationship['body']['relationType'], $relationshipResponse['body']['relationType']); + $this->assertEquals($relationship['body']['twoWay'], $relationshipResponse['body']['twoWay']); + $this->assertEquals($relationship['body']['twoWayKey'], $relationshipResponse['body']['twoWayKey']); + + $columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $columns['headers']['status-code']); + $this->assertEquals(12, $columns['body']['total']); + + $columns = $columns['body']['columns']; + $this->assertIsArray($columns); + $this->assertCount(12, $columns); + + $this->assertEquals($stringResponse['body']['key'], $columns[0]['key']); + $this->assertEquals($stringResponse['body']['type'], $columns[0]['type']); + $this->assertEquals($stringResponse['body']['status'], $columns[0]['status']); + $this->assertEquals($stringResponse['body']['required'], $columns[0]['required']); + $this->assertEquals($stringResponse['body']['array'], $columns[0]['array']); + $this->assertEquals($stringResponse['body']['size'], $columns[0]['size']); + $this->assertEquals($stringResponse['body']['default'], $columns[0]['default']); + + $this->assertEquals($emailResponse['body']['key'], $columns[1]['key']); + $this->assertEquals($emailResponse['body']['type'], $columns[1]['type']); + $this->assertEquals($emailResponse['body']['status'], $columns[1]['status']); + $this->assertEquals($emailResponse['body']['required'], $columns[1]['required']); + $this->assertEquals($emailResponse['body']['array'], $columns[1]['array']); + $this->assertEquals($emailResponse['body']['default'], $columns[1]['default']); + $this->assertEquals($emailResponse['body']['format'], $columns[1]['format']); + + $this->assertEquals($enumResponse['body']['key'], $columns[2]['key']); + $this->assertEquals($enumResponse['body']['type'], $columns[2]['type']); + $this->assertEquals($enumResponse['body']['status'], $columns[2]['status']); + $this->assertEquals($enumResponse['body']['required'], $columns[2]['required']); + $this->assertEquals($enumResponse['body']['array'], $columns[2]['array']); + $this->assertEquals($enumResponse['body']['default'], $columns[2]['default']); + $this->assertEquals($enumResponse['body']['format'], $columns[2]['format']); + $this->assertEquals($enumResponse['body']['elements'], $columns[2]['elements']); + + $this->assertEquals($ipResponse['body']['key'], $columns[3]['key']); + $this->assertEquals($ipResponse['body']['type'], $columns[3]['type']); + $this->assertEquals($ipResponse['body']['status'], $columns[3]['status']); + $this->assertEquals($ipResponse['body']['required'], $columns[3]['required']); + $this->assertEquals($ipResponse['body']['array'], $columns[3]['array']); + $this->assertEquals($ipResponse['body']['default'], $columns[3]['default']); + $this->assertEquals($ipResponse['body']['format'], $columns[3]['format']); + + $this->assertEquals($urlResponse['body']['key'], $columns[4]['key']); + $this->assertEquals($urlResponse['body']['type'], $columns[4]['type']); + $this->assertEquals($urlResponse['body']['status'], $columns[4]['status']); + $this->assertEquals($urlResponse['body']['required'], $columns[4]['required']); + $this->assertEquals($urlResponse['body']['array'], $columns[4]['array']); + $this->assertEquals($urlResponse['body']['default'], $columns[4]['default']); + $this->assertEquals($urlResponse['body']['format'], $columns[4]['format']); + + $this->assertEquals($integerResponse['body']['key'], $columns[5]['key']); + $this->assertEquals($integerResponse['body']['type'], $columns[5]['type']); + $this->assertEquals($integerResponse['body']['status'], $columns[5]['status']); + $this->assertEquals($integerResponse['body']['required'], $columns[5]['required']); + $this->assertEquals($integerResponse['body']['array'], $columns[5]['array']); + $this->assertEquals($integerResponse['body']['default'], $columns[5]['default']); + $this->assertEquals($integerResponse['body']['min'], $columns[5]['min']); + $this->assertEquals($integerResponse['body']['max'], $columns[5]['max']); + + $this->assertEquals($floatResponse['body']['key'], $columns[6]['key']); + $this->assertEquals($floatResponse['body']['type'], $columns[6]['type']); + $this->assertEquals($floatResponse['body']['status'], $columns[6]['status']); + $this->assertEquals($floatResponse['body']['required'], $columns[6]['required']); + $this->assertEquals($floatResponse['body']['array'], $columns[6]['array']); + $this->assertEquals($floatResponse['body']['default'], $columns[6]['default']); + $this->assertEquals($floatResponse['body']['min'], $columns[6]['min']); + $this->assertEquals($floatResponse['body']['max'], $columns[6]['max']); + + $this->assertEquals($booleanResponse['body']['key'], $columns[7]['key']); + $this->assertEquals($booleanResponse['body']['type'], $columns[7]['type']); + $this->assertEquals($booleanResponse['body']['status'], $columns[7]['status']); + $this->assertEquals($booleanResponse['body']['required'], $columns[7]['required']); + $this->assertEquals($booleanResponse['body']['array'], $columns[7]['array']); + $this->assertEquals($booleanResponse['body']['default'], $columns[7]['default']); + + $this->assertEquals($datetimeResponse['body']['key'], $columns[8]['key']); + $this->assertEquals($datetimeResponse['body']['type'], $columns[8]['type']); + $this->assertEquals($datetimeResponse['body']['status'], $columns[8]['status']); + $this->assertEquals($datetimeResponse['body']['required'], $columns[8]['required']); + $this->assertEquals($datetimeResponse['body']['array'], $columns[8]['array']); + $this->assertEquals($datetimeResponse['body']['default'], $columns[8]['default']); + + $this->assertEquals($relationshipResponse['body']['key'], $columns[9]['key']); + $this->assertEquals($relationshipResponse['body']['type'], $columns[9]['type']); + $this->assertEquals($relationshipResponse['body']['status'], $columns[9]['status']); + $this->assertEquals($relationshipResponse['body']['required'], $columns[9]['required']); + $this->assertEquals($relationshipResponse['body']['array'], $columns[9]['array']); + $this->assertEquals($relationshipResponse['body']['relatedTable'], $columns[9]['relatedTable']); + $this->assertEquals($relationshipResponse['body']['relationType'], $columns[9]['relationType']); + $this->assertEquals($relationshipResponse['body']['twoWay'], $columns[9]['twoWay']); + $this->assertEquals($relationshipResponse['body']['twoWayKey'], $columns[9]['twoWayKey']); + + $this->assertEquals($stringsResponse['body']['key'], $columns[10]['key']); + $this->assertEquals($stringsResponse['body']['type'], $columns[10]['type']); + $this->assertEquals($stringsResponse['body']['status'], $columns[10]['status']); + $this->assertEquals($stringsResponse['body']['required'], $columns[10]['required']); + $this->assertEquals($stringsResponse['body']['array'], $columns[10]['array']); + $this->assertEquals($stringsResponse['body']['default'], $columns[10]['default']); + + $this->assertEquals($integersResponse['body']['key'], $columns[11]['key']); + $this->assertEquals($integersResponse['body']['type'], $columns[11]['type']); + $this->assertEquals($integersResponse['body']['status'], $columns[11]['status']); + $this->assertEquals($integersResponse['body']['required'], $columns[11]['required']); + $this->assertEquals($integersResponse['body']['array'], $columns[11]['array']); + $this->assertEquals($integersResponse['body']['default'], $columns[11]['default']); + $this->assertEquals($integersResponse['body']['min'], $columns[11]['min']); + $this->assertEquals($integersResponse['body']['max'], $columns[11]['max']); + + $table = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $table['headers']['status-code']); + + $columns = $table['body']['columns']; + + $this->assertIsArray($columns); + $this->assertCount(12, $columns); + + $this->assertEquals($stringResponse['body']['key'], $columns[0]['key']); + $this->assertEquals($stringResponse['body']['type'], $columns[0]['type']); + $this->assertEquals($stringResponse['body']['status'], $columns[0]['status']); + $this->assertEquals($stringResponse['body']['required'], $columns[0]['required']); + $this->assertEquals($stringResponse['body']['array'], $columns[0]['array']); + $this->assertEquals($stringResponse['body']['size'], $columns[0]['size']); + $this->assertEquals($stringResponse['body']['default'], $columns[0]['default']); + + $this->assertEquals($emailResponse['body']['key'], $columns[1]['key']); + $this->assertEquals($emailResponse['body']['type'], $columns[1]['type']); + $this->assertEquals($emailResponse['body']['status'], $columns[1]['status']); + $this->assertEquals($emailResponse['body']['required'], $columns[1]['required']); + $this->assertEquals($emailResponse['body']['array'], $columns[1]['array']); + $this->assertEquals($emailResponse['body']['default'], $columns[1]['default']); + $this->assertEquals($emailResponse['body']['format'], $columns[1]['format']); + + $this->assertEquals($enumResponse['body']['key'], $columns[2]['key']); + $this->assertEquals($enumResponse['body']['type'], $columns[2]['type']); + $this->assertEquals($enumResponse['body']['status'], $columns[2]['status']); + $this->assertEquals($enumResponse['body']['required'], $columns[2]['required']); + $this->assertEquals($enumResponse['body']['array'], $columns[2]['array']); + $this->assertEquals($enumResponse['body']['default'], $columns[2]['default']); + $this->assertEquals($enumResponse['body']['format'], $columns[2]['format']); + $this->assertEquals($enumResponse['body']['elements'], $columns[2]['elements']); + + $this->assertEquals($ipResponse['body']['key'], $columns[3]['key']); + $this->assertEquals($ipResponse['body']['type'], $columns[3]['type']); + $this->assertEquals($ipResponse['body']['status'], $columns[3]['status']); + $this->assertEquals($ipResponse['body']['required'], $columns[3]['required']); + $this->assertEquals($ipResponse['body']['array'], $columns[3]['array']); + $this->assertEquals($ipResponse['body']['default'], $columns[3]['default']); + $this->assertEquals($ipResponse['body']['format'], $columns[3]['format']); + + $this->assertEquals($urlResponse['body']['key'], $columns[4]['key']); + $this->assertEquals($urlResponse['body']['type'], $columns[4]['type']); + $this->assertEquals($urlResponse['body']['status'], $columns[4]['status']); + $this->assertEquals($urlResponse['body']['required'], $columns[4]['required']); + $this->assertEquals($urlResponse['body']['array'], $columns[4]['array']); + $this->assertEquals($urlResponse['body']['default'], $columns[4]['default']); + $this->assertEquals($urlResponse['body']['format'], $columns[4]['format']); + + $this->assertEquals($integerResponse['body']['key'], $columns[5]['key']); + $this->assertEquals($integerResponse['body']['type'], $columns[5]['type']); + $this->assertEquals($integerResponse['body']['status'], $columns[5]['status']); + $this->assertEquals($integerResponse['body']['required'], $columns[5]['required']); + $this->assertEquals($integerResponse['body']['array'], $columns[5]['array']); + $this->assertEquals($integerResponse['body']['default'], $columns[5]['default']); + $this->assertEquals($integerResponse['body']['min'], $columns[5]['min']); + $this->assertEquals($integerResponse['body']['max'], $columns[5]['max']); + + $this->assertEquals($floatResponse['body']['key'], $columns[6]['key']); + $this->assertEquals($floatResponse['body']['type'], $columns[6]['type']); + $this->assertEquals($floatResponse['body']['status'], $columns[6]['status']); + $this->assertEquals($floatResponse['body']['required'], $columns[6]['required']); + $this->assertEquals($floatResponse['body']['array'], $columns[6]['array']); + $this->assertEquals($floatResponse['body']['default'], $columns[6]['default']); + $this->assertEquals($floatResponse['body']['min'], $columns[6]['min']); + $this->assertEquals($floatResponse['body']['max'], $columns[6]['max']); + + $this->assertEquals($booleanResponse['body']['key'], $columns[7]['key']); + $this->assertEquals($booleanResponse['body']['type'], $columns[7]['type']); + $this->assertEquals($booleanResponse['body']['status'], $columns[7]['status']); + $this->assertEquals($booleanResponse['body']['required'], $columns[7]['required']); + $this->assertEquals($booleanResponse['body']['array'], $columns[7]['array']); + $this->assertEquals($booleanResponse['body']['default'], $columns[7]['default']); + + $this->assertEquals($datetimeResponse['body']['key'], $columns[8]['key']); + $this->assertEquals($datetimeResponse['body']['type'], $columns[8]['type']); + $this->assertEquals($datetimeResponse['body']['status'], $columns[8]['status']); + $this->assertEquals($datetimeResponse['body']['required'], $columns[8]['required']); + $this->assertEquals($datetimeResponse['body']['array'], $columns[8]['array']); + $this->assertEquals($datetimeResponse['body']['default'], $columns[8]['default']); + + $this->assertEquals($relationshipResponse['body']['key'], $columns[9]['key']); + $this->assertEquals($relationshipResponse['body']['type'], $columns[9]['type']); + $this->assertEquals($relationshipResponse['body']['status'], $columns[9]['status']); + $this->assertEquals($relationshipResponse['body']['required'], $columns[9]['required']); + $this->assertEquals($relationshipResponse['body']['array'], $columns[9]['array']); + $this->assertEquals($relationshipResponse['body']['relatedTable'], $columns[9]['relatedTable']); + $this->assertEquals($relationshipResponse['body']['relationType'], $columns[9]['relationType']); + $this->assertEquals($relationshipResponse['body']['twoWay'], $columns[9]['twoWay']); + $this->assertEquals($relationshipResponse['body']['twoWayKey'], $columns[9]['twoWayKey']); + + $this->assertEquals($stringsResponse['body']['key'], $columns[10]['key']); + $this->assertEquals($stringsResponse['body']['type'], $columns[10]['type']); + $this->assertEquals($stringsResponse['body']['status'], $columns[10]['status']); + $this->assertEquals($stringsResponse['body']['required'], $columns[10]['required']); + $this->assertEquals($stringsResponse['body']['array'], $columns[10]['array']); + $this->assertEquals($stringsResponse['body']['default'], $columns[10]['default']); + + $this->assertEquals($integersResponse['body']['key'], $columns[11]['key']); + $this->assertEquals($integersResponse['body']['type'], $columns[11]['type']); + $this->assertEquals($integersResponse['body']['status'], $columns[11]['status']); + $this->assertEquals($integersResponse['body']['required'], $columns[11]['required']); + $this->assertEquals($integersResponse['body']['array'], $columns[11]['array']); + $this->assertEquals($integersResponse['body']['default'], $columns[11]['default']); + $this->assertEquals($integersResponse['body']['min'], $columns[11]['min']); + $this->assertEquals($integersResponse['body']['max'], $columns[11]['max']); + + /** + * Test for FAILURE + */ + $badEnum = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'enum', + 'elements' => ['yes', 'no', ''], + 'required' => false, + 'default' => 'maybe', + ]); + + $this->assertEquals(400, $badEnum['headers']['status-code']); + $this->assertEquals('Invalid `elements` param: Value must a valid array no longer than 100 items and Value must be a valid string and at least 1 chars and no longer than 255 chars', $badEnum['body']['message']); + + return $data; + } + + /** + * @depends testCreateAttributes + */ + public function testCreateIndexes(array $data): array + { + $databaseId = $data['databaseId']; + + $titleIndex = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'titleIndex', + 'type' => 'fulltext', + 'columns' => ['title'], + ]); + + $this->assertEquals(202, $titleIndex['headers']['status-code']); + $this->assertEquals('titleIndex', $titleIndex['body']['key']); + $this->assertEquals('fulltext', $titleIndex['body']['type']); + $this->assertCount(1, $titleIndex['body']['columns']); + $this->assertEquals('title', $titleIndex['body']['columns'][0]); + + $releaseYearIndex = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'releaseYear', + 'type' => 'key', + 'columns' => ['releaseYear'], + ]); + + $this->assertEquals(202, $releaseYearIndex['headers']['status-code']); + $this->assertEquals('releaseYear', $releaseYearIndex['body']['key']); + $this->assertEquals('key', $releaseYearIndex['body']['type']); + $this->assertCount(1, $releaseYearIndex['body']['columns']); + $this->assertEquals('releaseYear', $releaseYearIndex['body']['columns'][0]); + + $releaseWithDate1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'releaseYearDated', + 'type' => 'key', + 'columns' => ['releaseYear', '$createdAt', '$updatedAt'], + ]); + + $this->assertEquals(202, $releaseWithDate1['headers']['status-code']); + $this->assertEquals('releaseYearDated', $releaseWithDate1['body']['key']); + $this->assertEquals('key', $releaseWithDate1['body']['type']); + $this->assertCount(3, $releaseWithDate1['body']['columns']); + $this->assertEquals('releaseYear', $releaseWithDate1['body']['columns'][0]); + $this->assertEquals('$createdAt', $releaseWithDate1['body']['columns'][1]); + $this->assertEquals('$updatedAt', $releaseWithDate1['body']['columns'][2]); + + $releaseWithDate2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'birthDay', + 'type' => 'key', + 'columns' => ['birthDay'], + ]); + + $this->assertEquals(202, $releaseWithDate2['headers']['status-code']); + $this->assertEquals('birthDay', $releaseWithDate2['body']['key']); + $this->assertEquals('key', $releaseWithDate2['body']['type']); + $this->assertCount(1, $releaseWithDate2['body']['columns']); + $this->assertEquals('birthDay', $releaseWithDate2['body']['columns'][0]); + + // Test for failure + $fulltextReleaseYear = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'releaseYearDated', + 'type' => 'fulltext', + 'columns' => ['releaseYear'], + ]); + + $this->assertEquals(400, $fulltextReleaseYear['headers']['status-code']); + $this->assertEquals($fulltextReleaseYear['body']['message'], 'Attribute "releaseYear" cannot be part of a FULLTEXT index, must be of type string'); + + $noAttributes = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'none', + 'type' => 'key', + 'columns' => [], + ]); + + $this->assertEquals(400, $noAttributes['headers']['status-code']); + $this->assertEquals($noAttributes['body']['message'], 'No attributes provided for index'); + + $duplicates = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'duplicate', + 'type' => 'fulltext', + 'columns' => ['releaseYear', 'releaseYear'], + ]); + + $this->assertEquals(400, $duplicates['headers']['status-code']); + $this->assertEquals($duplicates['body']['message'], 'Duplicate attributes provided'); + + $tooLong = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'key' => 'tooLong', + 'type' => 'key', + 'columns' => ['description', 'tagline'], + ]); + + $this->assertEquals(400, $tooLong['headers']['status-code']); + $this->assertStringContainsString('Index length is longer than the maximum', $tooLong['body']['message']); + + $fulltextArray = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'key' => 'ft', + 'type' => 'fulltext', + 'columns' => ['actors'], + ]); + + $this->assertEquals(400, $fulltextArray['headers']['status-code']); + $this->assertEquals('"Fulltext" index is forbidden on array attributes', $fulltextArray['body']['message']); + + $actorsArray = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'key' => 'index-actors', + 'type' => 'key', + 'columns' => ['actors'], + ]); + + $this->assertEquals(202, $actorsArray['headers']['status-code']); + + $twoLevelsArray = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'key' => 'index-ip-actors', + 'type' => 'key', + 'columns' => ['releaseYear', 'actors'], // 2 levels + 'orders' => ['DESC', 'DESC'], + ]); + + $this->assertEquals(202, $twoLevelsArray['headers']['status-code']); + $this->assertEquals('DESC', $twoLevelsArray['body']['orders'][0]); + $this->assertEquals(null, $twoLevelsArray['body']['orders'][1]); // Overwrite by API (array) + + $unknown = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'key' => 'index-unknown', + 'type' => 'key', + 'columns' => ['Unknown'], + ]); + + $this->assertEquals(400, $unknown['headers']['status-code']); + $this->assertEquals('Unknown column: Unknown. Verify the column name or create the column.', $unknown['body']['message']); + + $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'key' => 'integers-order', + 'type' => 'key', + 'columns' => ['integers'], // array attribute + 'orders' => ['DESC'], // Check order is removed in API + ]); + $this->assertEquals(202, $index1['headers']['status-code']); + + $index2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'key' => 'integers-size', + 'type' => 'key', + 'columns' => ['integers'], // array attribute + ]); + $this->assertEquals(202, $index2['headers']['status-code']); + + /** + * Create Indexes by worker + */ + sleep(2); + + $movies = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), []); + + $this->assertIsArray($movies['body']['indexes']); + $this->assertCount(8, $movies['body']['indexes']); + $this->assertEquals($titleIndex['body']['key'], $movies['body']['indexes'][0]['key']); + $this->assertEquals($releaseYearIndex['body']['key'], $movies['body']['indexes'][1]['key']); + $this->assertEquals($releaseWithDate1['body']['key'], $movies['body']['indexes'][2]['key']); + $this->assertEquals($releaseWithDate2['body']['key'], $movies['body']['indexes'][3]['key']); + foreach ($movies['body']['indexes'] as $index) { + $this->assertEquals('available', $index['status']); + } + + return $data; + } + + /** + * @depends testCreateIndexes + */ + public function testListIndexes(array $data): void + { + $databaseId = $data['databaseId']; + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'queries' => [ + Query::equal('type', ['key'])->toString(), + Query::limit(2)->toString() + ], + ]); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(2, \count($response['body']['indexes'])); + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'queries' => [ + Query::select(['key'])->toString(), + ], + ]); + $this->assertEquals(Exception::GENERAL_ARGUMENT_INVALID, $response['body']['type']); + $this->assertEquals(400, $response['headers']['status-code']); + } + + /** + * @depends testCreateIndexes + */ + public function testCreateDocument(array $data): array + { + $databaseId = $data['databaseId']; + $row1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Captain America', + 'releaseYear' => 1944, + 'birthDay' => '1975-06-12 14:12:55+02:00', + 'actors' => [ + 'Chris Evans', + 'Samuel Jackson', + ] + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + $row2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Spider-Man: Far From Home', + 'releaseYear' => 2019, + 'birthDay' => null, + 'actors' => [ + 'Tom Holland', + 'Zendaya Maree Stoermer', + 'Samuel Jackson', + ], + 'integers' => [50,60] + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + $row3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Spider-Man: Homecoming', + 'releaseYear' => 2017, + 'birthDay' => '1975-06-12 14:12:55 America/New_York', + 'duration' => 65, + 'actors' => [ + 'Tom Holland', + 'Zendaya Maree Stoermer', + ], + 'integers' => [50] + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + $row4 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'releaseYear' => 2020, // Missing title, expect an 400 error + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + $this->assertEquals(201, $row1['headers']['status-code']); + $this->assertEquals($data['moviesId'], $row1['body']['$tableId']); + $this->assertArrayNotHasKey('$table', $row1['body']); + $this->assertEquals($databaseId, $row1['body']['$databaseId']); + $this->assertEquals($row1['body']['title'], 'Captain America'); + $this->assertEquals($row1['body']['releaseYear'], 1944); + $this->assertIsArray($row1['body']['$permissions']); + $this->assertCount(3, $row1['body']['$permissions']); + $this->assertCount(2, $row1['body']['actors']); + $this->assertEquals($row1['body']['actors'][0], 'Chris Evans'); + $this->assertEquals($row1['body']['actors'][1], 'Samuel Jackson'); + $this->assertEquals($row1['body']['birthDay'], '1975-06-12T12:12:55.000+00:00'); + + $this->assertEquals(201, $row2['headers']['status-code']); + $this->assertEquals($data['moviesId'], $row2['body']['$tableId']); + $this->assertArrayNotHasKey('$table', $row2['body']); + $this->assertEquals($databaseId, $row2['body']['$databaseId']); + $this->assertEquals($row2['body']['title'], 'Spider-Man: Far From Home'); + $this->assertEquals($row2['body']['releaseYear'], 2019); + $this->assertEquals($row2['body']['duration'], null); + $this->assertIsArray($row2['body']['$permissions']); + $this->assertCount(3, $row2['body']['$permissions']); + $this->assertCount(3, $row2['body']['actors']); + $this->assertEquals($row2['body']['actors'][0], 'Tom Holland'); + $this->assertEquals($row2['body']['actors'][1], 'Zendaya Maree Stoermer'); + $this->assertEquals($row2['body']['actors'][2], 'Samuel Jackson'); + $this->assertEquals($row2['body']['birthDay'], null); + $this->assertEquals($row2['body']['integers'][0], 50); + $this->assertEquals($row2['body']['integers'][1], 60); + + $this->assertEquals(201, $row3['headers']['status-code']); + $this->assertEquals($data['moviesId'], $row3['body']['$tableId']); + $this->assertArrayNotHasKey('$table', $row3['body']); + $this->assertEquals($databaseId, $row3['body']['$databaseId']); + $this->assertEquals($row3['body']['title'], 'Spider-Man: Homecoming'); + $this->assertEquals($row3['body']['releaseYear'], 2017); + $this->assertEquals($row3['body']['duration'], 65); + $this->assertIsArray($row3['body']['$permissions']); + $this->assertCount(3, $row3['body']['$permissions']); + $this->assertCount(2, $row3['body']['actors']); + $this->assertEquals($row3['body']['actors'][0], 'Tom Holland'); + $this->assertEquals($row3['body']['actors'][1], 'Zendaya Maree Stoermer'); + $this->assertEquals($row3['body']['birthDay'], '1975-06-12T18:12:55.000+00:00'); // UTC for NY + + $this->assertEquals(400, $row4['headers']['status-code']); + + // Delete document 4 with incomplete path + $this->assertEquals(404, $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()))['headers']['status-code']); + + return $data; + } + + /** + * @depends testCreateDocument + */ + public function testListDocuments(array $data): array + { + $databaseId = $data['databaseId']; + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::orderAsc('releaseYear')->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(1944, $rows['body']['rows'][0]['releaseYear']); + $this->assertEquals(2017, $rows['body']['rows'][1]['releaseYear']); + $this->assertEquals(2019, $rows['body']['rows'][2]['releaseYear']); + $this->assertFalse(array_key_exists('$internalId', $rows['body']['rows'][0])); + $this->assertFalse(array_key_exists('$internalId', $rows['body']['rows'][1])); + $this->assertFalse(array_key_exists('$internalId', $rows['body']['rows'][2])); + $this->assertCount(3, $rows['body']['rows']); + + foreach ($rows['body']['rows'] as $row) { + $this->assertArrayNotHasKey('$table', $row); + $this->assertEquals($databaseId, $row['$databaseId']); + $this->assertEquals($data['moviesId'], $row['$tableId']); + } + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::orderDesc('releaseYear')->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(1944, $rows['body']['rows'][2]['releaseYear']); + $this->assertEquals(2017, $rows['body']['rows'][1]['releaseYear']); + $this->assertEquals(2019, $rows['body']['rows'][0]['releaseYear']); + $this->assertCount(3, $rows['body']['rows']); + + // changing description attribute to be null by default instead of empty string + $patchNull = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/columns/string/description', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'default' => null, + 'required' => false, + ]); + // creating a dummy doc with null description + $row1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Dummy', + 'releaseYear' => 1944, + 'birthDay' => '1975-06-12 14:12:55+02:00', + 'actors' => [ + 'Dummy', + ], + ] + ]); + + $this->assertEquals(201, $row1['headers']['status-code']); + // fetching docs with cursor after the dummy doc with order attr description which is null + $rowsPaginated = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::orderAsc('dummy')->toString(), + Query::cursorAfter(new Document(['$id' => $row1['body']['$id']]))->toString() + ], + ]); + // should throw 400 as the order attr description of the selected doc is null + $this->assertEquals(400, $rowsPaginated['headers']['status-code']); + + // deleting the dummy doc created + $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $row1['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + return ['rows' => $rows['body']['rows'], 'databaseId' => $databaseId]; + } + + + /** + * @depends testListDocuments + */ + public function testGetDocument(array $data): void + { + $databaseId = $data['databaseId']; + foreach ($data['rows'] as $row) { + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $row['$tableId'] . '/rows/' . $row['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($response['body']['$id'], $row['$id']); + $this->assertEquals($row['$tableId'], $response['body']['$tableId']); + $this->assertArrayNotHasKey('$table', $response['body']); + $this->assertEquals($row['$databaseId'], $response['body']['$databaseId']); + $this->assertEquals($response['body']['title'], $row['title']); + $this->assertEquals($response['body']['releaseYear'], $row['releaseYear']); + $this->assertEquals($response['body']['$permissions'], $row['$permissions']); + $this->assertEquals($response['body']['birthDay'], $row['birthDay']); + $this->assertFalse(array_key_exists('$internalId', $response['body'])); + $this->assertFalse(array_key_exists('$tenant', $response['body'])); + } + } + + /** + * @depends testListDocuments + */ + public function testGetDocumentWithQueries(array $data): void + { + $databaseId = $data['databaseId']; + $row = $data['rows'][0]; + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $row['$tableId'] . '/rows/' . $row['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['title', 'releaseYear', '$id'])->toString(), + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($row['title'], $response['body']['title']); + $this->assertEquals($row['releaseYear'], $response['body']['releaseYear']); + $this->assertArrayNotHasKey('birthDay', $response['body']); + } + + /** + * @depends testCreateDocument + */ + public function testListDocumentsAfterPagination(array $data): array + { + $databaseId = $data['databaseId']; + /** + * Test after without order. + */ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $base['headers']['status-code']); + $this->assertEquals('Captain America', $base['body']['rows'][0]['title']); + $this->assertEquals('Spider-Man: Far From Home', $base['body']['rows'][1]['title']); + $this->assertEquals('Spider-Man: Homecoming', $base['body']['rows'][2]['title']); + $this->assertCount(3, $base['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => $base['body']['rows'][0]['$id']]))->toString() + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals($base['body']['rows'][1]['$id'], $rows['body']['rows'][0]['$id']); + $this->assertEquals($base['body']['rows'][2]['$id'], $rows['body']['rows'][1]['$id']); + $this->assertCount(2, $rows['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => $base['body']['rows'][2]['$id']]))->toString() + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEmpty($rows['body']['rows']); + + /** + * Test with ASC order and after. + */ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::orderAsc('releaseYear')->toString() + ], + ]); + + $this->assertEquals(200, $base['headers']['status-code']); + $this->assertEquals(1944, $base['body']['rows'][0]['releaseYear']); + $this->assertEquals(2017, $base['body']['rows'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['rows'][2]['releaseYear']); + $this->assertCount(3, $base['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => $base['body']['rows'][1]['$id']]))->toString(), + Query::orderAsc('releaseYear')->toString() + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals($base['body']['rows'][2]['$id'], $rows['body']['rows'][0]['$id']); + $this->assertCount(1, $rows['body']['rows']); + + /** + * Test with DESC order and after. + */ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::orderDesc('releaseYear')->toString() + ], + ]); + + $this->assertEquals(200, $base['headers']['status-code']); + $this->assertEquals(1944, $base['body']['rows'][2]['releaseYear']); + $this->assertEquals(2017, $base['body']['rows'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['rows'][0]['releaseYear']); + $this->assertCount(3, $base['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => $base['body']['rows'][1]['$id']]))->toString(), + Query::orderDesc('releaseYear')->toString() + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals($base['body']['rows'][2]['$id'], $rows['body']['rows'][0]['$id']); + $this->assertCount(1, $rows['body']['rows']); + + /** + * Test after with unknown document. + */ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => 'unknown']))->toString(), + ], + ]); + + $this->assertEquals(400, $rows['headers']['status-code']); + + /** + * Test null value for cursor + */ + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + '{"method":"cursorAfter","values":[null]}', + ], + ]); + + $this->assertEquals(400, $rows['headers']['status-code']); + + return []; + } + + /** + * @depends testCreateDocument + */ + public function testListDocumentsBeforePagination(array $data): array + { + $databaseId = $data['databaseId']; + /** + * Test before without order. + */ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $base['headers']['status-code']); + $this->assertEquals('Captain America', $base['body']['rows'][0]['title']); + $this->assertEquals('Spider-Man: Far From Home', $base['body']['rows'][1]['title']); + $this->assertEquals('Spider-Man: Homecoming', $base['body']['rows'][2]['title']); + $this->assertCount(3, $base['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorBefore(new Document(['$id' => $base['body']['rows'][2]['$id']]))->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals($base['body']['rows'][0]['$id'], $rows['body']['rows'][0]['$id']); + $this->assertEquals($base['body']['rows'][1]['$id'], $rows['body']['rows'][1]['$id']); + $this->assertCount(2, $rows['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorBefore(new Document(['$id' => $base['body']['rows'][0]['$id']]))->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEmpty($rows['body']['rows']); + + /** + * Test with ASC order and after. + */ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::orderAsc('releaseYear')->toString(), + ], + ]); + + $this->assertEquals(200, $base['headers']['status-code']); + $this->assertEquals(1944, $base['body']['rows'][0]['releaseYear']); + $this->assertEquals(2017, $base['body']['rows'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['rows'][2]['releaseYear']); + $this->assertCount(3, $base['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorBefore(new Document(['$id' => $base['body']['rows'][1]['$id']]))->toString(), + Query::orderAsc('releaseYear')->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals($base['body']['rows'][0]['$id'], $rows['body']['rows'][0]['$id']); + $this->assertCount(1, $rows['body']['rows']); + + /** + * Test with DESC order and after. + */ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::orderDesc('releaseYear')->toString(), + ], + ]); + + $this->assertEquals(200, $base['headers']['status-code']); + $this->assertEquals(1944, $base['body']['rows'][2]['releaseYear']); + $this->assertEquals(2017, $base['body']['rows'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['rows'][0]['releaseYear']); + $this->assertCount(3, $base['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorBefore(new Document(['$id' => $base['body']['rows'][1]['$id']]))->toString(), + Query::orderDesc('releaseYear')->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals($base['body']['rows'][0]['$id'], $rows['body']['rows'][0]['$id']); + $this->assertCount(1, $rows['body']['rows']); + + return []; + } + + /** + * @depends testCreateDocument + */ + public function testListDocumentsLimitAndOffset(array $data): array + { + $databaseId = $data['databaseId']; + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::orderAsc('releaseYear')->toString(), + Query::limit(1)->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(1944, $rows['body']['rows'][0]['releaseYear']); + $this->assertCount(1, $rows['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::orderAsc('releaseYear')->toString(), + Query::limit(2)->toString(), + Query::offset(1)->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(2017, $rows['body']['rows'][0]['releaseYear']); + $this->assertEquals(2019, $rows['body']['rows'][1]['releaseYear']); + $this->assertCount(2, $rows['body']['rows']); + + return []; + } + + /** + * @depends testCreateDocument + */ + public function testDocumentsListQueries(array $data): array + { + $databaseId = $data['databaseId']; + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::search('title', 'Captain America')->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(1944, $rows['body']['rows'][0]['releaseYear']); + $this->assertCount(1, $rows['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('$id', [$rows['body']['rows'][0]['$id']])->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(1944, $rows['body']['rows'][0]['releaseYear']); + $this->assertCount(1, $rows['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::search('title', 'Homecoming')->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(2017, $rows['body']['rows'][0]['releaseYear']); + $this->assertCount(1, $rows['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::search('title', 'spider')->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(2019, $rows['body']['rows'][0]['releaseYear']); + $this->assertEquals(2017, $rows['body']['rows'][1]['releaseYear']); + $this->assertCount(2, $rows['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + '{"method":"contains","attribute":"title","values":[bad]}' + ], + ]); + + $this->assertEquals(400, $rows['headers']['status-code']); + $this->assertEquals('Invalid query: Syntax error', $rows['body']['message']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::contains('title', ['spi'])->toString(), // like query + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(2, $rows['body']['total']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('releaseYear', [1944])->toString(), + ], + ]); + + $this->assertCount(1, $rows['body']['rows']); + $this->assertEquals('Captain America', $rows['body']['rows'][0]['title']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::notEqual('releaseYear', 1944)->toString(), + ], + ]); + + $this->assertCount(2, $rows['body']['rows']); + $this->assertEquals('Spider-Man: Far From Home', $rows['body']['rows'][0]['title']); + $this->assertEquals('Spider-Man: Homecoming', $rows['body']['rows'][1]['title']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::greaterThan('$createdAt', '1976-06-12')->toString(), + ], + ]); + + $this->assertCount(3, $rows['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::lessThan('$createdAt', '1976-06-12')->toString(), + ], + ]); + + $this->assertCount(0, $rows['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::contains('actors', ['Tom Holland', 'Samuel Jackson'])->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(3, $rows['body']['total']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::contains('actors', ['Tom'])->toString(), // Full-match not like + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(0, $rows['body']['total']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::greaterThan('birthDay', '16/01/2024 12:00:00AM')->toString(), + ], + ]); + + $this->assertEquals(400, $rows['headers']['status-code']); + $this->assertEquals('Invalid query: Query value is invalid for attribute "birthDay"', $rows['body']['message']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::greaterThan('birthDay', '1960-01-01 10:10:10+02:30')->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals('1975-06-12T12:12:55.000+00:00', $rows['body']['rows'][0]['birthDay']); + $this->assertEquals('1975-06-12T18:12:55.000+00:00', $rows['body']['rows'][1]['birthDay']); + $this->assertCount(2, $rows['body']['rows']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::isNull('integers')->toString(), + ], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(1, $rows['body']['total']); + + /** + * Test for Failure + */ + $conditions = []; + + for ($i = 0; $i < APP_DATABASE_QUERY_MAX_VALUES + 1; $i++) { + $conditions[] = $i; + } + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('releaseYear', $conditions)->toString(), + ], + ]); + $this->assertEquals(400, $rows['headers']['status-code']); + $this->assertEquals('Invalid query: Query on attribute has greater than '.APP_DATABASE_QUERY_MAX_VALUES.' values: releaseYear', $rows['body']['message']); + + $value = ''; + + for ($i = 0; $i < 101; $i++) { + $value .= "[" . $i . "] Too long title to cross 2k chars query limit "; + } + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::search('title', $value)->toString(), + ], + ]); + + // Todo: Not sure what to do we with Query length Test VS old? JSON validator will fails if query string will be truncated? + //$this->assertEquals(400, $rows['headers']['status-code']); + + // Todo: Disabled for CL - Uncomment after ProxyDatabase cleanup for find method + // $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + // 'content-type' => 'application/json', + // 'x-appwrite-project' => $this->getProject()['$id'], + // ], $this->getHeaders()), [ + // 'queries' => [ + // Query::search('actors', 'Tom')->toString(), + // ], + // ]); + // $this->assertEquals(400, $rows['headers']['status-code']); + // $this->assertEquals('Invalid query: Cannot query search on attribute "actors" because it is an array.', $rows['body']['message']); + + return []; + } + + /** + * @depends testCreateDocument + */ + public function testUpdateDocument(array $data): array + { + $databaseId = $data['databaseId']; + $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Thor: Ragnaroc', + 'releaseYear' => 2017, + 'birthDay' => '1976-06-12 14:12:55', + 'actors' => [], + '$createdAt' => 5 // Should be ignored + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ], + ]); + + $id = $row['body']['$id']; + + $this->assertEquals(201, $row['headers']['status-code']); + $this->assertEquals($data['moviesId'], $row['body']['$tableId']); + $this->assertArrayNotHasKey('$table', $row['body']); + $this->assertEquals($databaseId, $row['body']['$databaseId']); + $this->assertEquals($row['body']['title'], 'Thor: Ragnaroc'); + $this->assertEquals($row['body']['releaseYear'], 2017); + $dateValidator = new DatetimeValidator(); + $this->assertEquals(true, $dateValidator->isValid($row['body']['$createdAt'])); + $this->assertEquals(true, $dateValidator->isValid($row['body']['birthDay'])); + $this->assertContains(Permission::read(Role::user($this->getUser()['$id'])), $row['body']['$permissions']); + $this->assertContains(Permission::update(Role::user($this->getUser()['$id'])), $row['body']['$permissions']); + $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $row['body']['$permissions']); + + $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Ragnarok', + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + ]); + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals($row['body']['$id'], $id); + $this->assertEquals($data['moviesId'], $row['body']['$tableId']); + $this->assertArrayNotHasKey('$table', $row['body']); + $this->assertEquals($databaseId, $row['body']['$databaseId']); + $this->assertEquals($row['body']['title'], 'Thor: Ragnarok'); + $this->assertEquals($row['body']['releaseYear'], 2017); + $this->assertContains(Permission::read(Role::users()), $row['body']['$permissions']); + $this->assertContains(Permission::update(Role::users()), $row['body']['$permissions']); + $this->assertContains(Permission::delete(Role::users()), $row['body']['$permissions']); + + $row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $id = $row['body']['$id']; + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals($data['moviesId'], $row['body']['$tableId']); + $this->assertArrayNotHasKey('$table', $row['body']); + $this->assertEquals($databaseId, $row['body']['$databaseId']); + $this->assertEquals($row['body']['title'], 'Thor: Ragnarok'); + $this->assertEquals($row['body']['releaseYear'], 2017); + + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-timestamp' => DateTime::formatTz(DateTime::now()), + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Ragnarok', + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + /** + * Test for failure + */ + + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-timestamp' => 'invalid', + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Ragnarok', + ], + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertEquals('Invalid X-Appwrite-Timestamp header value', $response['body']['message']); + $this->assertEquals(Exception::GENERAL_ARGUMENT_INVALID, $response['body']['type']); + + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-timestamp' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -1000)), + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Ragnarok', + ], + ]); + + $this->assertEquals(409, $response['headers']['status-code']); + $this->assertEquals('Remote row is newer than local.', $response['body']['message']); + $this->assertEquals(Exception::ROW_UPDATE_CONFLICT, $response['body']['type']); + + return []; + } + + /** + * @depends testCreateDocument + */ + public function testDeleteDocument(array $data): array + { + $databaseId = $data['databaseId']; + $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Thor: Ragnarok', + 'releaseYear' => 2017, + 'birthDay' => '1975-06-12 14:12:55', + 'actors' => [], + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + $id = $row['body']['$id']; + + $this->assertEquals(201, $row['headers']['status-code']); + + $row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $row['headers']['status-code']); + + $row = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(204, $row['headers']['status-code']); + + $row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $row['headers']['status-code']); + + return $data; + } + + public function testInvalidDocumentStructure() + { + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'InvalidDocumentDatabase', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('InvalidDocumentDatabase', $database['body']['name']); + + $databaseId = $database['body']['$id']; + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'invalidDocumentStructure', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + $this->assertEquals('invalidDocumentStructure', $table['body']['name']); + + $tableId = $table['body']['$id']; + + $email = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'email', + 'required' => false, + ]); + + $enum = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'enum', + 'elements' => ['yes', 'no', 'maybe'], + 'required' => false, + ]); + + $ip = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'ip', + 'required' => false, + ]); + + $url = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'url', + 'size' => 256, + 'required' => false, + ]); + + $range = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'range', + 'required' => false, + 'min' => 1, + 'max' => 10, + ]); + + // TODO@kodumbeats min and max are rounded in error message + $floatRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'floatRange', + 'required' => false, + 'min' => 1.1, + 'max' => 1.4, + ]); + + $probability = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'probability', + 'required' => false, + 'default' => 0, + 'min' => 0, + 'max' => 1, + ]); + + $upperBound = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'upperBound', + 'required' => false, + 'max' => 10, + ]); + + $lowerBound = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'lowerBound', + 'required' => false, + 'min' => 5, + ]); + + /** + * Test for failure + */ + + $invalidRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ + 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'invalidRange', + 'required' => false, + 'min' => 4, + 'max' => 3, + ]); + + $defaultArray = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ + 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'defaultArray', + 'required' => false, + 'default' => 42, + 'array' => true, + ]); + + $defaultRequired = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'attributeId' => ID::custom('defaultRequired'), + 'required' => true, + 'default' => 12 + ]); + + $enumDefault = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'attributeId' => ID::custom('enumDefault'), + 'elements' => ['north', 'west'], + 'default' => 'south' + ]); + + $enumDefaultStrict = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'attributeId' => ID::custom('enumDefault'), + 'elements' => ['north', 'west'], + 'default' => 'NORTH' + ]); + + $goodDatetime = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'birthDay', + 'required' => false, + 'default' => null + ]); + + $datetimeDefault = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'badBirthDay', + 'required' => false, + 'default' => 'bad' + ]); + + $this->assertEquals(202, $email['headers']['status-code']); + $this->assertEquals(202, $ip['headers']['status-code']); + $this->assertEquals(202, $url['headers']['status-code']); + $this->assertEquals(202, $range['headers']['status-code']); + $this->assertEquals(202, $floatRange['headers']['status-code']); + $this->assertEquals(202, $probability['headers']['status-code']); + $this->assertEquals(202, $upperBound['headers']['status-code']); + $this->assertEquals(202, $lowerBound['headers']['status-code']); + $this->assertEquals(202, $enum['headers']['status-code']); + $this->assertEquals(202, $goodDatetime['headers']['status-code']); + $this->assertEquals(400, $invalidRange['headers']['status-code']); + $this->assertEquals(400, $defaultArray['headers']['status-code']); + $this->assertEquals(400, $defaultRequired['headers']['status-code']); + $this->assertEquals(400, $enumDefault['headers']['status-code']); + $this->assertEquals(400, $enumDefaultStrict['headers']['status-code']); + $this->assertEquals('Minimum value must be lesser than maximum value', $invalidRange['body']['message']); + $this->assertEquals('Cannot set default value for array columns', $defaultArray['body']['message']); + $this->assertEquals(400, $datetimeDefault['headers']['status-code']); + // wait for worker to add attributes + sleep(3); + + $table = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), []); + + $this->assertCount(10, $table['body']['columns']); + + /** + * Test for successful validation + */ + + $goodEmail = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'email' => 'user@example.com', + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $goodEnum = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'enum' => 'yes', + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $goodIp = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'ip' => '1.1.1.1', + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $goodUrl = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'url' => 'http://www.example.com', + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $goodRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'range' => 3, + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $goodFloatRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'floatRange' => 1.4, + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $goodProbability = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'probability' => 0.99999, + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $notTooHigh = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'upperBound' => 8, + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $notTooLow = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'lowerBound' => 8, + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $this->assertEquals(201, $goodEmail['headers']['status-code']); + $this->assertEquals(201, $goodEnum['headers']['status-code']); + $this->assertEquals(201, $goodIp['headers']['status-code']); + $this->assertEquals(201, $goodUrl['headers']['status-code']); + $this->assertEquals(201, $goodRange['headers']['status-code']); + $this->assertEquals(201, $goodFloatRange['headers']['status-code']); + $this->assertEquals(201, $goodProbability['headers']['status-code']); + $this->assertEquals(201, $notTooHigh['headers']['status-code']); + $this->assertEquals(201, $notTooLow['headers']['status-code']); + + /* + * Test that custom validators reject documents + */ + + $badEmail = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'email' => 'user@@example.com', + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $badEnum = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'enum' => 'badEnum', + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $badIp = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'ip' => '1.1.1.1.1', + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $badUrl = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'url' => 'example...com', + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $badRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'range' => 11, + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $badFloatRange = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'floatRange' => 2.5, + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $badProbability = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'probability' => 1.1, + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $tooHigh = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'upperBound' => 11, + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $tooLow = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'lowerBound' => 3, + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $badTime = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => 'unique()', + 'data' => [ + 'birthDay' => '2020-10-10 27:30:10+01:00', + ], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], + ]); + + $this->assertEquals(400, $badEmail['headers']['status-code']); + $this->assertEquals(400, $badEnum['headers']['status-code']); + $this->assertEquals(400, $badIp['headers']['status-code']); + $this->assertEquals(400, $badUrl['headers']['status-code']); + $this->assertEquals(400, $badRange['headers']['status-code']); + $this->assertEquals(400, $badFloatRange['headers']['status-code']); + $this->assertEquals(400, $badProbability['headers']['status-code']); + $this->assertEquals(400, $tooHigh['headers']['status-code']); + $this->assertEquals(400, $tooLow['headers']['status-code']); + $this->assertEquals(400, $badTime['headers']['status-code']); + $this->assertEquals('Invalid document structure: Attribute "email" has invalid format. Value must be a valid email address', $badEmail['body']['message']); + $this->assertEquals('Invalid document structure: Attribute "enum" has invalid format. Value must be one of (yes, no, maybe)', $badEnum['body']['message']); + $this->assertEquals('Invalid document structure: Attribute "ip" has invalid format. Value must be a valid IP address', $badIp['body']['message']); + $this->assertEquals('Invalid document structure: Attribute "url" has invalid format. Value must be a valid URL', $badUrl['body']['message']); + $this->assertEquals('Invalid document structure: Attribute "range" has invalid format. Value must be a valid range between 1 and 10', $badRange['body']['message']); + $this->assertEquals('Invalid document structure: Attribute "floatRange" has invalid format. Value must be a valid range between 1 and 1', $badFloatRange['body']['message']); + $this->assertEquals('Invalid document structure: Attribute "probability" has invalid format. Value must be a valid range between 0 and 1', $badProbability['body']['message']); + $this->assertEquals('Invalid document structure: Attribute "upperBound" has invalid format. Value must be a valid range between -9,223,372,036,854,775,808 and 10', $tooHigh['body']['message']); + $this->assertEquals('Invalid document structure: Attribute "lowerBound" has invalid format. Value must be a valid range between 5 and 9,223,372,036,854,775,807', $tooLow['body']['message']); + } + + /** + * @depends testDeleteDocument + */ + public function testDefaultPermissions(array $data): array + { + $databaseId = $data['databaseId']; + $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Captain America', + 'releaseYear' => 1944, + 'actors' => [], + ], + ]); + + $id = $row['body']['$id']; + + $this->assertEquals(201, $row['headers']['status-code']); + $this->assertEquals($row['body']['title'], 'Captain America'); + $this->assertEquals($row['body']['releaseYear'], 1944); + $this->assertIsArray($row['body']['$permissions']); + + if ($this->getSide() == 'client') { + $this->assertCount(3, $row['body']['$permissions']); + $this->assertContains(Permission::read(Role::user($this->getUser()['$id'])), $row['body']['$permissions']); + $this->assertContains(Permission::update(Role::user($this->getUser()['$id'])), $row['body']['$permissions']); + $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $row['body']['$permissions']); + } + + if ($this->getSide() == 'server') { + $this->assertCount(0, $row['body']['$permissions']); + $this->assertEquals([], $row['body']['$permissions']); + } + + // Updated Permissions + + $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Captain America 2', + 'releaseYear' => 1945, + 'actors' => [], + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])) + ], + ]); + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals($row['body']['title'], 'Captain America 2'); + $this->assertEquals($row['body']['releaseYear'], 1945); + + // This differs from the old permissions model because we don't inherit + // existing document permissions on update, unless none were supplied, + // so that specific types can be removed if wanted. + $this->assertCount(2, $row['body']['$permissions']); + $this->assertEquals([ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + ], $row['body']['$permissions']); + + $row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals($row['body']['title'], 'Captain America 2'); + $this->assertEquals($row['body']['releaseYear'], 1945); + + $this->assertCount(2, $row['body']['$permissions']); + $this->assertEquals([ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + ], $row['body']['$permissions']); + + // Reset Permissions + + $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Captain America 3', + 'releaseYear' => 1946, + 'actors' => [], + ], + 'permissions' => [], + ]); + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals($row['body']['title'], 'Captain America 3'); + $this->assertEquals($row['body']['releaseYear'], 1946); + $this->assertCount(0, $row['body']['$permissions']); + $this->assertEquals([], $row['body']['$permissions']); + + // Check client side can no longer read the document. + $row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + switch ($this->getSide()) { + case 'client': + $this->assertEquals(404, $row['headers']['status-code']); + break; + case 'server': + $this->assertEquals(200, $row['headers']['status-code']); + break; + } + + return $data; + } + + public function testEnforceCollectionAndDocumentPermissions(): void + { + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'EnforceCollectionAndDocumentPermissions', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('EnforceCollectionAndDocumentPermissions', $database['body']['name']); + + $databaseId = $database['body']['$id']; + $user = $this->getUser()['$id']; + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'enforceCollectionAndDocumentPermissions', + 'documentSecurity' => true, + 'permissions' => [ + Permission::read(Role::user($user)), + Permission::create(Role::user($user)), + Permission::update(Role::user($user)), + Permission::delete(Role::user($user)), + ], + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + $this->assertEquals($table['body']['name'], 'enforceCollectionAndDocumentPermissions'); + $this->assertEquals($table['body']['documentSecurity'], true); + + $tableId = $table['body']['$id']; + + sleep(2); + + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'attribute', + 'size' => 64, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code'], 202); + $this->assertEquals('attribute', $attribute['body']['key']); + + // wait for db to add attribute + sleep(2); + + $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'key_attribute', + 'type' => 'key', + 'columns' => [$attribute['body']['key']], + ]); + + $this->assertEquals(202, $index['headers']['status-code']); + $this->assertEquals('key_attribute', $index['body']['key']); + + // wait for db to add attribute + sleep(2); + + $row1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'attribute' => 'one', + ], + 'permissions' => [ + Permission::read(Role::user($user)), + Permission::update(Role::user($user)), + Permission::delete(Role::user($user)), + ] + ]); + + $this->assertEquals(201, $row1['headers']['status-code']); + + $row2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'attribute' => 'one', + ], + 'permissions' => [ + Permission::update(Role::user($user)), + Permission::delete(Role::user($user)), + ] + ]); + + $this->assertEquals(201, $row2['headers']['status-code']); + + $row3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'rowId' => ID::unique(), + 'data' => [ + 'attribute' => 'one', + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom('other'))), + Permission::update(Role::user(ID::custom('other'))), + ], + ]); + + $this->assertEquals(201, $row3['headers']['status-code']); + + $rowsUser1 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Current user has read permission on the collection so can get any document + $this->assertEquals(3, $rowsUser1['body']['total']); + $this->assertCount(3, $rowsUser1['body']['rows']); + + $row3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row3['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Current user has read permission on the collection so can get any document + $this->assertEquals(200, $row3GetWithCollectionRead['headers']['status-code']); + + $email = uniqid() . 'user@localhost.test'; + $password = 'password'; + $name = 'User Name'; + $this->client->call(Client::METHOD_POST, '/account', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'userId' => ID::custom('other'), + 'email' => $email, + 'password' => $password, + 'name' => $name, + ]); + $session2 = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'email' => $email, + 'password' => $password, + ]); + $session2 = $session2['cookies']['a_session_' . $this->getProject()['$id']]; + + $row3GetWithDocumentRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row3['body']['$id'], [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + ]); + + // Current user has no collection permissions but has read permission for this document + $this->assertEquals(200, $row3GetWithDocumentRead['headers']['status-code']); + + $row2GetFailure = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row2['body']['$id'], [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + ]); + + // Current user has no collection or document permissions for this document + $this->assertEquals(404, $row2GetFailure['headers']['status-code']); + + $rowsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + ]); + + // Current user has no collection permissions but has read permission for one document + $this->assertEquals(1, $rowsUser2['body']['total']); + $this->assertCount(1, $rowsUser2['body']['rows']); + } + + public function testEnforceCollectionPermissions() + { + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'EnforceCollectionPermissions', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('EnforceCollectionPermissions', $database['body']['name']); + + $databaseId = $database['body']['$id']; + $user = $this->getUser()['$id']; + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'enforceCollectionPermissions', + 'permissions' => [ + Permission::read(Role::user($user)), + Permission::create(Role::user($user)), + Permission::update(Role::user($user)), + Permission::delete(Role::user($user)), + ], + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + $this->assertEquals($table['body']['name'], 'enforceCollectionPermissions'); + $this->assertEquals($table['body']['documentSecurity'], false); + + $tableId = $table['body']['$id']; + + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'attribute', + 'size' => 64, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code'], 202); + $this->assertEquals('attribute', $attribute['body']['key']); + + \sleep(2); + + $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'key_attribute', + 'type' => 'key', + 'columns' => [$attribute['body']['key']], + ]); + + $this->assertEquals(202, $index['headers']['status-code']); + $this->assertEquals('key_attribute', $index['body']['key']); + + \sleep(2); + + $row1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'attribute' => 'one', + ], + 'permissions' => [ + Permission::read(Role::user($user)), + Permission::update(Role::user($user)), + Permission::delete(Role::user($user)), + ] + ]); + + $this->assertEquals(201, $row1['headers']['status-code']); + + $row2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'attribute' => 'one', + ], + 'permissions' => [ + Permission::update(Role::user($user)), + Permission::delete(Role::user($user)), + ] + ]); + + $this->assertEquals(201, $row2['headers']['status-code']); + + $row3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'rowId' => ID::unique(), + 'data' => [ + 'attribute' => 'one', + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom('other2'))), + Permission::update(Role::user(ID::custom('other2'))), + ], + ]); + + $this->assertEquals(201, $row3['headers']['status-code']); + + $rowsUser1 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Current user has read permission on the collection so can get any document + $this->assertEquals(3, $rowsUser1['body']['total']); + $this->assertCount(3, $rowsUser1['body']['rows']); + + $row3GetWithCollectionRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row3['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Current user has read permission on the collection so can get any document + $this->assertEquals(200, $row3GetWithCollectionRead['headers']['status-code']); + + $email = uniqid() . 'user2@localhost.test'; + $password = 'password'; + $name = 'User Name'; + $this->client->call(Client::METHOD_POST, '/account', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'userId' => ID::custom('other2'), + 'email' => $email, + 'password' => $password, + 'name' => $name, + ]); + $session2 = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'email' => $email, + 'password' => $password, + ]); + $session2 = $session2['cookies']['a_session_' . $this->getProject()['$id']]; + + $row3GetWithDocumentRead = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row3['body']['$id'], [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + ]); + + // other2 has no collection permissions and document permissions are disabled + $this->assertEquals(404, $row3GetWithDocumentRead['headers']['status-code']); + + $rowsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + ]); + + // other2 has no collection permissions and document permissions are disabled + $this->assertEquals(401, $rowsUser2['headers']['status-code']); + + // Enable document permissions + $table = $this->client->call(CLient::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $tableId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'name' => $table['body']['name'], + 'documentSecurity' => true, + ]); + + $rowsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, + ]); + + // Current user has no collection permissions read access to one document + $this->assertEquals(1, $rowsUser2['body']['total']); + $this->assertCount(1, $rowsUser2['body']['rows']); + } + + /** + * @depends testDefaultPermissions + */ + public function testUniqueIndexDuplicate(array $data): array + { + $databaseId = $data['databaseId']; + $uniqueIndex = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'unique_title', + 'type' => 'unique', + 'columns' => ['title'], + ]); + + $this->assertEquals(202, $uniqueIndex['headers']['status-code']); + + sleep(2); + + // test for failure + $duplicate = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Captain America', + 'releaseYear' => 1944, + 'actors' => [ + 'Chris Evans', + 'Samuel Jackson', + ] + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $this->assertEquals(409, $duplicate['headers']['status-code']); + + // Test for exception when updating document to conflict + $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Captain America 5', + 'releaseYear' => 1944, + 'actors' => [ + 'Chris Evans', + 'Samuel Jackson', + ] + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $this->assertEquals(201, $row['headers']['status-code']); + + // Test for exception when updating document to conflict + $duplicate = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $row['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Captain America', + 'releaseYear' => 1944, + 'actors' => [ + 'Chris Evans', + 'Samuel Jackson', + ] + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $this->assertEquals(409, $duplicate['headers']['status-code']); + + return $data; + } + + /** + * @depends testUniqueIndexDuplicate + */ + public function testPersistantCreatedAt(array $data): array + { + $headers = $this->getSide() === 'client' ? array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()) : [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]; + + $row = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/tables/' . $data['moviesId'] . '/rows', $headers, [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Creation Date Test', + 'releaseYear' => 2000 + ] + ]); + + $this->assertEquals($row['body']['title'], 'Creation Date Test'); + + $rowId = $row['body']['$id']; + $createdAt = $row['body']['$createdAt']; + $updatedAt = $row['body']['$updatedAt']; + + \sleep(1); + + $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, $headers, [ + 'data' => [ + 'title' => 'Updated Date Test', + ] + ]); + + $updatedAtSecond = $row['body']['$updatedAt']; + + $this->assertEquals($row['body']['title'], 'Updated Date Test'); + $this->assertEquals($row['body']['$createdAt'], $createdAt); + $this->assertNotEquals($row['body']['$updatedAt'], $updatedAt); + + \sleep(1); + + $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, $headers, [ + 'data' => [ + 'title' => 'Again Updated Date Test', + '$createdAt' => '2022-08-01 13:09:23.040', // $createdAt is not updatable + '$updatedAt' => '2022-08-01 13:09:23.050' // system will update it not api + ] + ]); + + $this->assertEquals($row['body']['title'], 'Again Updated Date Test'); + $this->assertEquals($row['body']['$createdAt'], $createdAt); + $this->assertNotEquals($row['body']['$createdAt'], '2022-08-01 13:09:23.040'); + $this->assertNotEquals($row['body']['$updatedAt'], $updatedAt); + $this->assertNotEquals($row['body']['$updatedAt'], $updatedAtSecond); + $this->assertNotEquals($row['body']['$updatedAt'], '2022-08-01 13:09:23.050'); + + return $data; + } + + public function testUpdatePermissionsWithEmptyPayload(): array + { + // Create Database + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'Empty Permissions', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + + $databaseId = $database['body']['$id']; + + // Create collection + $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Movies', + 'permissions' => [ + Permission::create(Role::user(ID::custom($this->getUser()['$id']))), + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $movies['headers']['status-code']); + $this->assertEquals($movies['body']['name'], 'Movies'); + + $moviesId = $movies['body']['$id']; + + // create attribute + $title = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $moviesId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 256, + 'required' => true, + ]); + + $this->assertEquals(202, $title['headers']['status-code']); + + // wait for database worker to create attributes + sleep(2); + + // add document + $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $moviesId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Captain America', + ], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $id = $row['body']['$id']; + + $this->assertEquals(201, $row['headers']['status-code']); + $this->assertCount(3, $row['body']['$permissions']); + $this->assertContains(Permission::read(Role::any()), $row['body']['$permissions']); + $this->assertContains(Permission::update(Role::any()), $row['body']['$permissions']); + $this->assertContains(Permission::delete(Role::any()), $row['body']['$permissions']); + + // Send only read permission + $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $moviesId . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'permissions' => [ + Permission::read(Role::user(ID::custom($this->getUser()['$id']))), + ] + ]); + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertCount(1, $row['body']['$permissions']); + + // Send only mutation permissions + $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $moviesId . '/rows/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'permissions' => [ + Permission::update(Role::user(ID::custom($this->getUser()['$id']))), + Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), + ], + ]); + + if ($this->getSide() == 'server') { + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertCount(2, $row['body']['$permissions']); + $this->assertContains(Permission::update(Role::user($this->getUser()['$id'])), $row['body']['$permissions']); + $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $row['body']['$permissions']); + } + + // remove collection + $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $moviesId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + return []; + } + + /** + * @depends testCreateDatabase + */ + public function testAttributeBooleanDefault(array $data): void + { + $databaseId = $data['databaseId']; + + /** + * Test for SUCCESS + */ + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Boolean' + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + + $tableId = $table['body']['$id']; + + $true = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'true', + 'required' => false, + 'default' => true + ]); + + $this->assertEquals(202, $true['headers']['status-code']); + + $false = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'false', + 'required' => false, + 'default' => false + ]); + + $this->assertEquals(202, $false['headers']['status-code']); + } + + /** + * @depends testCreateDatabase + */ + public function testOneToOneRelationship(array $data): array + { + $databaseId = $data['databaseId']; + + $person = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'person', + 'name' => 'person', + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + Permission::create(Role::user($this->getUser()['$id'])), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $person['headers']['status-code']); + + $library = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'library', + 'name' => 'library', + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::create(Role::user($this->getUser()['$id'])), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $library['headers']['status-code']); + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'fullName', + 'size' => 255, + 'required' => false, + ]); + + sleep(1); // Wait for worker + + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => 'library', + 'type' => Database::RELATION_ONE_TO_ONE, + 'key' => 'library', + 'twoWay' => true, + 'onDelete' => Database::RELATION_MUTATE_CASCADE, + ]); + + sleep(1); // Wait for worker + + $libraryName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $library['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'libraryName', + 'size' => 255, + 'required' => true, + ]); + + sleep(1); // Wait for worker + + $this->assertEquals(202, $libraryName['headers']['status-code']); + $this->assertEquals(202, $relation['headers']['status-code']); + $this->assertEquals('library', $relation['body']['key']); + $this->assertEquals('relationship', $relation['body']['type']); + $this->assertEquals('processing', $relation['body']['status']); + + $columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/columns', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $columns['headers']['status-code']); + $this->assertEquals(2, $columns['body']['total']); + $columns = $columns['body']['columns']; + $this->assertEquals('library', $columns[1]['relatedTable']); + $this->assertEquals('oneToOne', $columns[1]['relationType']); + $this->assertEquals(true, $columns[1]['twoWay']); + $this->assertEquals('person', $columns[1]['twoWayKey']); + $this->assertEquals(Database::RELATION_MUTATE_CASCADE, $columns[1]['onDelete']); + + $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/tables/{$person['body']['$id']}/columns/library", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $attribute['headers']['status-code']); + $this->assertEquals('available', $attribute['body']['status']); + $this->assertEquals('library', $attribute['body']['key']); + $this->assertEquals('relationship', $attribute['body']['type']); + $this->assertEquals(false, $attribute['body']['required']); + $this->assertEquals(false, $attribute['body']['array']); + $this->assertEquals('oneToOne', $attribute['body']['relationType']); + $this->assertEquals(true, $attribute['body']['twoWay']); + $this->assertEquals('person', $attribute['body']['twoWayKey']); + $this->assertEquals(Database::RELATION_MUTATE_CASCADE, $attribute['body']['onDelete']); + + $person1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'library' => [ + '$id' => 'library1', + '$permissions' => [ + Permission::read(Role::any()), + ], + 'libraryName' => 'Library 1', + ], + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + $this->assertEquals('Library 1', $person1['body']['library']['libraryName']); + + // Create without nested ID + $person2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'library' => [ + 'libraryName' => 'Library 2', + ], + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + $this->assertEquals('Library 2', $person2['body']['library']['libraryName']); + + // Ensure IDs were set and internal IDs removed + $this->assertEquals($databaseId, $person1['body']['$databaseId']); + $this->assertEquals($databaseId, $person1['body']['library']['$databaseId']); + + $this->assertEquals($person['body']['$id'], $person1['body']['$tableId']); + $this->assertEquals($library['body']['$id'], $person1['body']['library']['$tableId']); + + $this->assertArrayNotHasKey('$table', $person1['body']); + $this->assertArrayNotHasKey('$table', $person1['body']['library']); + $this->assertArrayNotHasKey('$internalId', $person1['body']); + $this->assertArrayNotHasKey('$internalId', $person1['body']['library']); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['fullName', 'library.*'])->toString(), + Query::equal('library', ['library1'])->toString(), + ], + ]); + + $this->assertEquals(1, $rows['body']['total']); + $this->assertEquals('Library 1', $rows['body']['rows'][0]['library']['libraryName']); + $this->assertArrayHasKey('fullName', $rows['body']['rows'][0]); + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('library.libraryName', ['Library 1'])->toString(), + ], + ]); + + $this->assertEquals(400, $rows['headers']['status-code']); + $this->assertEquals('Invalid query: Cannot query nested attribute on: library', $rows['body']['message']); + + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/columns/library', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + sleep(2); + + $this->assertEquals(204, $response['headers']['status-code']); + + $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/tables/{$person['body']['$id']}/columns/library", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(404, $attribute['headers']['status-code']); + + $person1 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/rows/' . $person1['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertArrayNotHasKey('library', $person1['body']); + + //Test Deletion of related twoKey + $columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $library['body']['$id'] . '/columns', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $columns['headers']['status-code']); + $this->assertEquals(1, $columns['body']['total']); + $this->assertEquals('libraryName', $columns['body']['columns'][0]['key']); + + return [ + 'databaseId' => $databaseId, + 'personCollection' => $person['body']['$id'], + 'libraryCollection' => $library['body']['$id'], + ]; + } + + /** + * @depends testOneToOneRelationship + */ + public function testOneToManyRelationship(array $data): array + { + $databaseId = $data['databaseId']; + $personCollection = $data['personCollection']; + $libraryCollection = $data['libraryCollection']; + + // One person can own several libraries + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $personCollection . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => 'library', + 'type' => Database::RELATION_ONE_TO_MANY, + 'twoWay' => true, + 'key' => 'libraries', + 'twoWayKey' => 'person_one_to_many', + ]); + + sleep(1); + + $libraryAttributesResponse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $libraryCollection . '/columns', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertIsArray($libraryAttributesResponse['body']['columns']); + $this->assertEquals(2, $libraryAttributesResponse['body']['total']); + $this->assertEquals('person_one_to_many', $libraryAttributesResponse['body']['columns'][1]['key']); + + $libraryCollectionResponse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $libraryCollection, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertIsArray($libraryCollectionResponse['body']['columns']); + $this->assertCount(2, $libraryCollectionResponse['body']['columns']); + + $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/tables/{$personCollection}/columns/libraries", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $attribute['headers']['status-code']); + $this->assertEquals('available', $attribute['body']['status']); + $this->assertEquals('libraries', $attribute['body']['key']); + $this->assertEquals('relationship', $attribute['body']['type']); + $this->assertEquals(false, $attribute['body']['required']); + $this->assertEquals(false, $attribute['body']['array']); + $this->assertEquals('oneToMany', $attribute['body']['relationType']); + $this->assertEquals(true, $attribute['body']['twoWay']); + $this->assertEquals('person_one_to_many', $attribute['body']['twoWayKey']); + $this->assertEquals('restrict', $attribute['body']['onDelete']); + + $person2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $personCollection . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => 'person10', + 'data' => [ + 'fullName' => 'Stevie Wonder', + 'libraries' => [ + [ + '$id' => 'library10', + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'libraryName' => 'Library 10', + ], + [ + '$id' => 'library11', + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'libraryName' => 'Library 11', + ] + ], + ], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ] + ]); + + $this->assertEquals(201, $person2['headers']['status-code']); + $this->assertArrayHasKey('libraries', $person2['body']); + $this->assertEquals(2, count($person2['body']['libraries'])); + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $personCollection . '/rows/' . $person2['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertArrayNotHasKey('$table', $response['body']); + $this->assertArrayHasKey('libraries', $response['body']); + $this->assertEquals(2, count($response['body']['libraries'])); + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $libraryCollection . '/rows/library11', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertArrayHasKey('person_one_to_many', $response['body']); + $this->assertEquals('person10', $response['body']['person_one_to_many']['$id']); + + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $personCollection . '/columns/libraries/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'onDelete' => Database::RELATION_MUTATE_CASCADE, + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + $attribute = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/tables/{$personCollection}/columns/libraries", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $attribute['headers']['status-code']); + $this->assertEquals('available', $attribute['body']['status']); + $this->assertEquals('libraries', $attribute['body']['key']); + $this->assertEquals('relationship', $attribute['body']['type']); + $this->assertEquals(false, $attribute['body']['required']); + $this->assertEquals(false, $attribute['body']['array']); + $this->assertEquals('oneToMany', $attribute['body']['relationType']); + $this->assertEquals(true, $attribute['body']['twoWay']); + $this->assertEquals(Database::RELATION_MUTATE_CASCADE, $attribute['body']['onDelete']); + + return ['databaseId' => $databaseId, 'personCollection' => $personCollection]; + } + + /** + * @depends testCreateDatabase + */ + public function testManyToOneRelationship(array $data): array + { + $databaseId = $data['databaseId']; + + // Create album collection + $albums = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Albums', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + ], + ]); + + // Create album name attribute + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $albums['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 255, + 'required' => true, + ]); + + // Create artist collection + $artists = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Artists', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + ], + ]); + + // Create artist name attribute + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $artists['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 255, + 'required' => true, + ]); + + // Create relationship + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $albums['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $artists['body']['$id'], + 'type' => Database::RELATION_MANY_TO_ONE, + 'twoWay' => true, + 'key' => 'artist', + 'twoWayKey' => 'albums', + ]); + $this->assertEquals(202, $response['headers']['status-code']); + $this->assertEquals('artist', $response['body']['key']); + $this->assertEquals('relationship', $response['body']['type']); + $this->assertEquals(false, $response['body']['required']); + $this->assertEquals(false, $response['body']['array']); + $this->assertEquals('manyToOne', $response['body']['relationType']); + $this->assertEquals(true, $response['body']['twoWay']); + $this->assertEquals('albums', $response['body']['twoWayKey']); + $this->assertEquals('restrict', $response['body']['onDelete']); + + sleep(1); // Wait for worker + + $permissions = [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ]; + + // Create album + $album = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $albums['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => 'album1', + 'permissions' => $permissions, + 'data' => [ + 'name' => 'Album 1', + 'artist' => [ + '$id' => ID::unique(), + 'name' => 'Artist 1', + ], + ], + ]); + + $this->assertEquals(201, $album['headers']['status-code']); + $this->assertEquals('album1', $album['body']['$id']); + $this->assertEquals('Album 1', $album['body']['name']); + $this->assertEquals('Artist 1', $album['body']['artist']['name']); + $this->assertEquals($permissions, $album['body']['$permissions']); + $this->assertEquals($permissions, $album['body']['artist']['$permissions']); + + $album = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $albums['body']['$id'] . '/rows/album1', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $album['headers']['status-code']); + $this->assertEquals('album1', $album['body']['$id']); + $this->assertEquals('Album 1', $album['body']['name']); + $this->assertEquals('Artist 1', $album['body']['artist']['name']); + $this->assertEquals($permissions, $album['body']['$permissions']); + $this->assertEquals($permissions, $album['body']['artist']['$permissions']); + + $artist = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $artists['body']['$id'] . '/rows/' . $album['body']['artist']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $artist['headers']['status-code']); + $this->assertEquals('Artist 1', $artist['body']['name']); + $this->assertEquals($permissions, $artist['body']['$permissions']); + $this->assertEquals(1, count($artist['body']['albums'])); + $this->assertEquals('album1', $artist['body']['albums'][0]['$id']); + $this->assertEquals('Album 1', $artist['body']['albums'][0]['name']); + $this->assertEquals($permissions, $artist['body']['albums'][0]['$permissions']); + + return [ + 'databaseId' => $databaseId, + 'albumsCollection' => $albums['body']['$id'], + 'artistsCollection' => $artists['body']['$id'], + ]; + } + + /** + * @depends testCreateDatabase + */ + public function testManyToManyRelationship(array $data): array + { + $databaseId = $data['databaseId']; + + // Create sports collection + $sports = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Sports', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + ], + ]); + + // Create sport name attribute + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $sports['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 255, + 'required' => true, + ]); + + // Create player collection + $players = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Players', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + ], + ]); + + // Create player name attribute + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $players['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 255, + 'required' => true, + ]); + + // Create relationship + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $sports['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $players['body']['$id'], + 'type' => Database::RELATION_MANY_TO_MANY, + 'twoWay' => true, + 'key' => 'players', + 'twoWayKey' => 'sports', + 'onDelete' => Database::RELATION_MUTATE_SET_NULL, + ]); + + $this->assertEquals(202, $response['headers']['status-code']); + $this->assertEquals('players', $response['body']['key']); + $this->assertEquals('relationship', $response['body']['type']); + $this->assertEquals(false, $response['body']['required']); + $this->assertEquals(false, $response['body']['array']); + $this->assertEquals('manyToMany', $response['body']['relationType']); + $this->assertEquals(true, $response['body']['twoWay']); + $this->assertEquals('sports', $response['body']['twoWayKey']); + $this->assertEquals('setNull', $response['body']['onDelete']); + + sleep(1); // Wait for worker + + $permissions = [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + ]; + + // Create sport + $sport = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $sports['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => 'sport1', + 'permissions' => $permissions, + 'data' => [ + 'name' => 'Sport 1', + 'players' => [ + [ + '$id' => 'player1', + 'name' => 'Player 1', + ], + [ + '$id' => 'player2', + 'name' => 'Player 2', + ] + ], + ], + ]); + + $this->assertEquals(201, $sport['headers']['status-code']); + $this->assertEquals('sport1', $sport['body']['$id']); + $this->assertEquals('Sport 1', $sport['body']['name']); + $this->assertEquals('Player 1', $sport['body']['players'][0]['name']); + $this->assertEquals('Player 2', $sport['body']['players'][1]['name']); + $this->assertEquals($permissions, $sport['body']['$permissions']); + $this->assertEquals($permissions, $sport['body']['players'][0]['$permissions']); + $this->assertEquals($permissions, $sport['body']['players'][1]['$permissions']); + + $sport = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $sports['body']['$id'] . '/rows/sport1', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $sport['headers']['status-code']); + $this->assertEquals('sport1', $sport['body']['$id']); + $this->assertEquals('Sport 1', $sport['body']['name']); + $this->assertEquals('Player 1', $sport['body']['players'][0]['name']); + $this->assertEquals('Player 2', $sport['body']['players'][1]['name']); + $this->assertEquals($permissions, $sport['body']['$permissions']); + $this->assertEquals($permissions, $sport['body']['players'][0]['$permissions']); + $this->assertEquals($permissions, $sport['body']['players'][1]['$permissions']); + + $player = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $players['body']['$id'] . '/rows/' . $sport['body']['players'][0]['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $player['headers']['status-code']); + $this->assertEquals('Player 1', $player['body']['name']); + $this->assertEquals($permissions, $player['body']['$permissions']); + $this->assertEquals(1, count($player['body']['sports'])); + $this->assertEquals('sport1', $player['body']['sports'][0]['$id']); + $this->assertEquals('Sport 1', $player['body']['sports'][0]['name']); + $this->assertEquals($permissions, $player['body']['sports'][0]['$permissions']); + + return [ + 'databaseId' => $databaseId, + 'sportsCollection' => $sports['body']['$id'], + 'playersCollection' => $players['body']['$id'], + ]; + } + + /** + * @depends testOneToManyRelationship + */ + public function testValidateOperators(array $data): void + { + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['personCollection'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::isNotNull('$id')->toString(), + Query::startsWith('fullName', 'Stevie')->toString(), + Query::endsWith('fullName', 'Wonder')->toString(), + Query::between('$createdAt', '1975-12-06', '2050-12-01')->toString(), + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(1, count($response['body']['rows'])); + $this->assertEquals('person10', $response['body']['rows'][0]['$id']); + $this->assertEquals('Stevie Wonder', $response['body']['rows'][0]['fullName']); + $this->assertEquals(2, count($response['body']['rows'][0]['libraries'])); + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['personCollection'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::isNotNull('$id')->toString(), + Query::isNull('fullName')->toString(), + Query::select(['fullName'])->toString(), + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(2, count($response['body']['rows'])); + $this->assertEquals(null, $response['body']['rows'][0]['fullName']); + $this->assertArrayNotHasKey("libraries", $response['body']['rows'][0]); + $this->assertArrayNotHasKey('$databaseId', $response['body']['rows'][0]); + $this->assertArrayNotHasKey('$tableId', $response['body']['rows'][0]); + } + + /** + * @depends testOneToManyRelationship + */ + public function testSelectQueries(array $data): void + { + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['personCollection'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('fullName', ['Stevie Wonder'])->toString(), + Query::select(['fullName'])->toString(), + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertArrayNotHasKey('libraries', $response['body']['rows'][0]); + $this->assertArrayNotHasKey('$databaseId', $response['body']['rows'][0]); + $this->assertArrayNotHasKey('$tableId', $response['body']['rows'][0]); + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['personCollection'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['libraries.*', '$id'])->toString(), + ], + ]); + $row = $response['body']['rows'][0]; + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertArrayHasKey('libraries', $row); + $this->assertArrayNotHasKey('$databaseId', $row); + $this->assertArrayNotHasKey('$tableId', $row); + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['personCollection'] . '/rows/' . $row['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['fullName', '$id'])->toString(), + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertArrayHasKey('fullName', $response['body']); + $this->assertArrayNotHasKey('libraries', $response['body']); + } + + /** + * @throws \Utopia\Database\Exception + * @throws \Utopia\Database\Exception\Query + */ + public function testOrQueries(): void + { + // Create database + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Or queries' + ]); + + $this->assertNotEmpty($database['body']['$id']); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('Or queries', $database['body']['name']); + + $databaseId = $database['body']['$id']; + + // Create Collection + $presidents = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'USA Presidents', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + ], + ]); + + $this->assertEquals(201, $presidents['headers']['status-code']); + $this->assertEquals($presidents['body']['name'], 'USA Presidents'); + + // Create Attributes + $firstName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $presidents['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'first_name', + 'size' => 256, + 'required' => true, + ]); + $this->assertEquals(202, $firstName['headers']['status-code']); + + $lastName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $presidents['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'last_name', + 'size' => 256, + 'required' => true, + ]); + + $this->assertEquals(202, $lastName['headers']['status-code']); + + // Wait for worker + sleep(2); + + $row1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $presidents['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'first_name' => 'Donald', + 'last_name' => 'Trump', + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + ] + ]); + $this->assertEquals(201, $row1['headers']['status-code']); + + $row2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $presidents['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'first_name' => 'George', + 'last_name' => 'Bush', + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + ] + ]); + $this->assertEquals(201, $row2['headers']['status-code']); + + $row3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $presidents['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'first_name' => 'Joe', + 'last_name' => 'Biden', + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + ] + ]); + + $this->assertEquals(201, $row3['headers']['status-code']); + + $rows = $this->client->call( + Client::METHOD_GET, + '/databases/' . $databaseId . '/tables/' . $presidents['body']['$id'] . '/rows', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), + [ + 'queries' => [ + Query::select(['first_name', 'last_name'])->toString(), + Query::or([ + Query::equal('first_name', ['Donald']), + Query::equal('last_name', ['Bush']) + ])->toString(), + Query::limit(999)->toString(), + Query::offset(0)->toString() + ], + ] + ); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertCount(2, $rows['body']['rows']); + } + + /** + * @depends testCreateDatabase + * @param array $data + * @return void + * @throws \Exception + */ + public function testUpdateWithExistingRelationships(array $data): void + { + $databaseId = $data['databaseId']; + + $table1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Collection1', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + ], + ]); + + $table2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Collection2', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + ], + ]); + + $table1 = $table1['body']['$id']; + $table2 = $table2['body']['$id']; + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1 . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => '49', + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table2 . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => '49', + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1 . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table2, + 'type' => Database::RELATION_ONE_TO_MANY, + 'twoWay' => true, + 'key' => 'collection2' + ]); + + sleep(1); + + $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1 . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'name' => 'Document 1', + 'collection2' => [ + [ + 'name' => 'Document 2', + ], + ], + ], + ]); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1 . '/rows/' . $row['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), [ + 'data' => [ + 'name' => 'Document 1 Updated', + ], + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + } + + /** + * @depends testCreateDatabase + */ + public function testTimeout(array $data): void + { + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Slow Queries', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + ], + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + + $data = [ + '$id' => $table['body']['$id'], + 'databaseId' => $table['body']['databaseId'] + ]; + + $longtext = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'longtext', + 'size' => 100000000, + 'required' => false, + 'default' => null, + ]); + + $this->assertEquals($longtext['headers']['status-code'], 202); + + for ($i = 0; $i < 10; $i++) { + $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'longtext' => file_get_contents(__DIR__ . '../../../../../resources/longtext.txt'), + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + } + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-timeout' => 1, + ], $this->getHeaders()), [ + 'queries' => [ + Query::notEqual('longtext', 'appwrite')->toString(), + ], + ]); + + $this->assertEquals(408, $response['headers']['status-code']); + } +} diff --git a/tests/e2e/Services/Databases/Tables/DatabasesConsoleClientTest.php b/tests/e2e/Services/Databases/Tables/DatabasesConsoleClientTest.php new file mode 100644 index 0000000000..48707d444b --- /dev/null +++ b/tests/e2e/Services/Databases/Tables/DatabasesConsoleClientTest.php @@ -0,0 +1,336 @@ +client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'databaseId' => ID::unique(), + 'name' => 'invalidDocumentDatabase', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); + $this->assertTrue($database['body']['enabled']); + + $databaseId = $database['body']['$id']; + + /** + * Test for SUCCESS + */ + $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'tableId' => ID::unique(), + 'name' => 'Movies', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $movies['headers']['status-code']); + $this->assertEquals($movies['body']['name'], 'Movies'); + + /** + * Test when database is disabled but can still create collections + */ + $database = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'invalidDocumentDatabase Updated', + 'enabled' => false, + ]); + + $this->assertFalse($database['body']['enabled']); + + $tvShows = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'tableId' => ID::unique(), + 'name' => 'TvShows', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'documentSecurity' => true, + ]); + + /** + * Test when collection is disabled but can still modify collections + */ + $database = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $movies['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Movies', + 'enabled' => false, + ]); + + $this->assertEquals(201, $tvShows['headers']['status-code']); + $this->assertEquals($tvShows['body']['name'], 'TvShows'); + + return ['moviesId' => $movies['body']['$id'], 'databaseId' => $databaseId, 'tvShowsId' => $tvShows['body']['$id']]; + } + + /** + * @depends testCreateCollection + * @param array $data + * @throws \Exception + */ + public function testListCollection(array $data) + { + /** + * Test when database is disabled but can still call list collections + */ + $databaseId = $data['databaseId']; + + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders())); + + $this->assertEquals(200, $tables['headers']['status-code']); + $this->assertEquals(2, $tables['body']['total']); + } + + /** + * @depends testCreateCollection + * @param array $data + * @throws \Exception + */ + public function testGetCollection(array $data) + { + $databaseId = $data['databaseId']; + $moviesCollectionId = $data['moviesId']; + + /** + * Test when database and collection are disabled but can still call get collection + */ + $table = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $moviesCollectionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $table['headers']['status-code']); + $this->assertEquals('Movies', $table['body']['name']); + $this->assertEquals($moviesCollectionId, $table['body']['$id']); + $this->assertFalse($table['body']['enabled']); + } + + /** + * @depends testCreateCollection + * @param array $data + * @throws \Exception + * @throws \Exception + */ + public function testUpdateCollection(array $data) + { + $databaseId = $data['databaseId']; + $moviesCollectionId = $data['moviesId']; + + /** + * Test When database and collection are disabled but can still call update collection + */ + $table = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $moviesCollectionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Movies Updated', + 'enabled' => false + ]); + + $this->assertEquals(200, $table['headers']['status-code']); + $this->assertEquals('Movies Updated', $table['body']['name']); + $this->assertEquals($moviesCollectionId, $table['body']['$id']); + $this->assertFalse($table['body']['enabled']); + } + + /** + * @depends testCreateCollection + * @param array $data + * @throws \Exception + * @throws \Exception + */ + public function testDeleteCollection(array $data) + { + $databaseId = $data['databaseId']; + $tvShowsId = $data['tvShowsId']; + + /** + * Test when database and collection are disabled but can still call delete collection + */ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tvShowsId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(204, $response['headers']['status-code']); + $this->assertEquals($response['body'], ""); + } + + /** + * @depends testCreateCollection + */ + public function testGetDatabaseUsage(array $data) + { + $databaseId = $data['databaseId']; + /** + * Test for FAILURE + */ + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/usage', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), [ + 'range' => '32h' + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + /** + * Test for SUCCESS + */ + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/usage', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), [ + 'range' => '24h' + ]); + + + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(15, count($response['body'])); + $this->assertEquals('24h', $response['body']['range']); + $this->assertIsNumeric($response['body']['rowsTotal']); + $this->assertIsNumeric($response['body']['tablesTotal']); + $this->assertIsArray($response['body']['tables']); + $this->assertIsArray($response['body']['rows']); + } + + + /** + * @depends testCreateCollection + */ + public function testGetCollectionUsage(array $data) + { + $databaseId = $data['databaseId']; + /** + * Test for FAILURE + */ + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/usage', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), [ + 'range' => '32h' + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/randomCollectionId/usage', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), [ + 'range' => '24h' + ]); + + $this->assertEquals(404, $response['headers']['status-code']); + + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/usage', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders()), [ + 'range' => '24h' + ]); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(3, count($response['body'])); + $this->assertEquals('24h', $response['body']['range']); + $this->assertIsNumeric($response['body']['rowsTotal']); + $this->assertIsArray($response['body']['rows']); + } + + /** + * @depends testCreateCollection + * @throws \Utopia\Database\Exception\Query + */ + public function testGetCollectionLogs(array $data) + { + $databaseId = $data['databaseId']; + /** + * Test for SUCCESS + */ + $logs = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/logs', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $logs['headers']['status-code']); + $this->assertIsArray($logs['body']['logs']); + $this->assertIsNumeric($logs['body']['total']); + + $logs = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/logs', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::limit(1)->toString()] + ]); + + $this->assertEquals(200, $logs['headers']['status-code']); + $this->assertIsArray($logs['body']['logs']); + $this->assertLessThanOrEqual(1, count($logs['body']['logs'])); + $this->assertIsNumeric($logs['body']['total']); + + $logs = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/logs', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::offset(1)->toString()] + ]); + + $this->assertEquals(200, $logs['headers']['status-code']); + $this->assertIsArray($logs['body']['logs']); + $this->assertIsNumeric($logs['body']['total']); + + $logs = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/logs', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::offset(1)->toString(), Query::limit(1)->toString()] + ]); + + $this->assertEquals(200, $logs['headers']['status-code']); + $this->assertIsArray($logs['body']['logs']); + $this->assertLessThanOrEqual(1, count($logs['body']['logs'])); + $this->assertIsNumeric($logs['body']['total']); + } +} diff --git a/tests/e2e/Services/Databases/Tables/DatabasesCustomClientTest.php b/tests/e2e/Services/Databases/Tables/DatabasesCustomClientTest.php new file mode 100644 index 0000000000..ca8ae08ca0 --- /dev/null +++ b/tests/e2e/Services/Databases/Tables/DatabasesCustomClientTest.php @@ -0,0 +1,893 @@ +client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Test Database' + ]); + + $databaseId = $database['body']['$id']; + + // Collection aliases write to create, update, delete + $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Movies', + 'documentSecurity' => true, + 'permissions' => [ + Permission::write(Role::user($this->getUser()['$id'])), + ], + ]); + + $moviesId = $movies['body']['$id']; + + $this->assertContains(Permission::create(Role::user($this->getUser()['$id'])), $movies['body']['$permissions']); + $this->assertContains(Permission::update(Role::user($this->getUser()['$id'])), $movies['body']['$permissions']); + $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $movies['body']['$permissions']); + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $moviesId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 256, + 'required' => true, + ]); + + sleep(1); + + $this->assertEquals(202, $response['headers']['status-code']); + + // Document aliases write to update, delete + $row1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $moviesId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Captain America', + ], + 'permissions' => [ + Permission::write(Role::user($this->getUser()['$id'])), + ] + ]); + + $this->assertNotContains(Permission::create(Role::user($this->getUser()['$id'])), $row1['body']['$permissions']); + $this->assertContains(Permission::update(Role::user($this->getUser()['$id'])), $row1['body']['$permissions']); + $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $row1['body']['$permissions']); + + /** + * Test for FAILURE + */ + + // Document does not allow create permission + $row2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $moviesId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Captain America', + ], + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + ] + ]); + + $this->assertEquals(400, $row2['headers']['status-code']); + } + + public function testUpdateWithoutPermission(): array + { + // If document has been created by server and client tried to update it without adjusting permissions, permission validation should be skipped + + // As a part of preparation, we get ID of currently logged-in user + $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(200, $response['headers']['status-code']); + + $userId = $response['body']['$id']; + + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::custom('permissionCheckDatabase'), + 'name' => 'Test Database', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('Test Database', $database['body']['name']); + + $databaseId = $database['body']['$id']; + // Create collection + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::custom('permissionCheck'), + 'name' => 'permissionCheck', + 'permissions' => [], + 'documentSecurity' => true, + ]); + $this->assertEquals(201, $response['headers']['status-code']); + + // Add attribute to collection + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/permissionCheck/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 255, + 'required' => true, + ]); + $this->assertEquals(202, $response['headers']['status-code']); + + // Wait for database worker to finish creating attributes + sleep(2); + + // Creating document by server, give read permission to our user + some other user + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/permissionCheck/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => ID::custom('permissionCheckDocument'), + 'data' => [ + 'name' => 'AppwriteBeginner', + ], + 'permissions' => [ + Permission::read(Role::user(ID::custom('user2'))), + Permission::read(Role::user($userId)), + Permission::update(Role::user($userId)), + Permission::delete(Role::user($userId)), + ], + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Update document + // This is the point of this test. We should be allowed to do this action, and it should not fail on permission check + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/permissionCheck/rows/permissionCheckDocument', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'name' => 'AppwriteExpert', + ] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Get name of the document, should be the new one + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/permissionCheck/rows/permissionCheckDocument', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals("AppwriteExpert", $response['body']['name']); + + // Cleanup to prevent collision with other tests + // Delete collection + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/permissionCheck', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(204, $response['headers']['status-code']); + + + // Wait for database worker to finish deleting collection + sleep(2); + + // Make sure collection has been deleted + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/permissionCheck', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + $this->assertEquals(404, $response['headers']['status-code']); + + return []; + } + + public function testUpdateTwoWayRelationship(): void + { + + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Test Database' + ]); + + $databaseId = $database['body']['$id']; + + + // Creating collection 1 + $table1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'level1', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + // Creating collection 2 + $table2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'level2', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + \sleep(2); + + // Creating two way relationship between collection 1 and collection 2 from collection 1 + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table2['body']['$id'], + 'type' => 'oneToMany', + 'twoWay' => true, + 'onDelete' => 'cascade', + 'key' => $table2['body']['$id'], + 'twoWayKey' => $table1['body']['$id'] + ]); + + \sleep(3); + + // Update relation from collection 2 to on delete restrict + $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table2['body']['$id'] . '/columns/' . $table1['body']['$id'] . '/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'onDelete' => 'restrict', + ]); + + // Fetching attributes after updating relation to compare + $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'], [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $table1RelationAttribute = $table1Attributes['body']['columns'][0]; + + $this->assertEquals($relation['body']['side'], $table1RelationAttribute['side']); + $this->assertEquals($relation['body']['twoWayKey'], $table1RelationAttribute['twoWayKey']); + $this->assertEquals($relation['body']['relatedTable'], $table1RelationAttribute['relatedTable']); + $this->assertEquals('restrict', $table1RelationAttribute['onDelete']); + } + + public function testRelationshipSameTwoWayKey(): void + { + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Same two way key' + ]); + + $databaseId = $database['body']['$id']; + + $table1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'c1', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + $table2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'c2', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + \sleep(2); + + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table2['body']['$id'], + 'type' => Database::RELATION_ONE_TO_ONE, + 'twoWay' => false, + 'onDelete' => 'cascade', + 'key' => 'attr1', + 'twoWayKey' => 'same_key' + ]); + + \sleep(2); + + $this->assertEquals(202, $relation['headers']['status-code']); + $this->assertEquals('same_key', $relation['body']['twoWayKey']); + + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table2['body']['$id'], + 'type' => Database::RELATION_ONE_TO_MANY, + 'twoWay' => false, + 'onDelete' => 'cascade', + 'key' => 'attr2', + 'twoWayKey' => 'same_key' + ]); + + \sleep(2); + + $this->assertEquals(409, $relation['body']['code']); + $this->assertEquals('Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.', $relation['body']['message']); + + // twoWayKey is null TwoWayKey is default + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table2['body']['$id'], + 'type' => Database::RELATION_ONE_TO_MANY, + 'twoWay' => false, + 'onDelete' => 'cascade', + 'key' => 'attr3', + ]); + + \sleep(2); + + $this->assertEquals(202, $relation['headers']['status-code']); + $this->assertArrayHasKey('twoWayKey', $relation['body']); + + // twoWayKey is null, TwoWayKey is default, second POST + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table2['body']['$id'], + 'type' => Database::RELATION_ONE_TO_MANY, + 'twoWay' => false, + 'onDelete' => 'cascade', + 'key' => 'attr4', + ]); + + \sleep(2); + + $this->assertEquals('Attribute with the requested key already exists. Attribute keys must be unique, try again with a different key.', $relation['body']['message']); + $this->assertEquals(409, $relation['body']['code']); + + // RelationshipManyToMany + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table2['body']['$id'], + 'type' => Database::RELATION_MANY_TO_MANY, + 'twoWay' => true, + 'onDelete' => 'setNull', + 'key' => 'songs', + 'twoWayKey' => 'playlist', + ]); + + \sleep(2); + + $this->assertEquals(202, $relation['headers']['status-code']); + $this->assertArrayHasKey('twoWayKey', $relation['body']); + + // Second RelationshipManyToMany on Same collections + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table2['body']['$id'], + 'type' => Database::RELATION_MANY_TO_MANY, + 'twoWay' => true, + 'onDelete' => 'setNull', + 'key' => 'songs2', + 'twoWayKey' => 'playlist2', + ]); + + \sleep(2); + + $this->assertEquals(409, $relation['body']['code']); + $this->assertEquals('Creating more than one "manyToMany" relationship on the same table is currently not permitted.', $relation['body']['message']); + } + + public function testUpdateWithoutRelationPermission(): void + { + $userId = $this->getUser()['$id']; + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => ID::unique(), + ]); + + $databaseId = $database['body']['$id']; + + // Creating collection 1 + $table1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::custom('collection1'), + 'name' => ID::custom('collection1'), + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($userId)), + Permission::read(Role::user($userId)), + Permission::delete(Role::user($userId)), + ] + ]); + + // Creating collection 2 + $table2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::custom('collection2'), + 'name' => ID::custom('collection2'), + 'documentSecurity' => false, + 'permissions' => [ + Permission::read(Role::user($userId)), + ] + ]); + + $table3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::custom('collection3'), + 'name' => ID::custom('collection3'), + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($userId)), + Permission::read(Role::user($userId)), + Permission::delete(Role::user($userId)), + ] + ]); + + $table4 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::custom('collection4'), + 'name' => ID::custom('collection4'), + 'documentSecurity' => false, + 'permissions' => [ + Permission::read(Role::user($userId)), + ] + ]); + + $table5 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::custom('collection5'), + 'name' => ID::custom('collection5'), + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($userId)), + Permission::read(Role::user($userId)), + Permission::delete(Role::user($userId)), + ] + ]); + + // Creating one to one relationship from collection 1 to colletion 2 + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table2['body']['$id'], + 'type' => 'oneToOne', + 'twoWay' => false, + 'onDelete' => 'setNull', + 'key' => $table2['body']['$id'] + ]); + + // Creating one to one relationship from collection 2 to colletion 3 + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table2['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table3['body']['$id'], + 'type' => 'oneToOne', + 'twoWay' => false, + 'onDelete' => 'setNull', + 'key' => $table3['body']['$id'] + ]); + + // Creating one to one relationship from collection 3 to colletion 4 + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table3['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table4['body']['$id'], + 'type' => 'oneToOne', + 'twoWay' => false, + 'onDelete' => 'setNull', + 'key' => $table4['body']['$id'] + ]); + + // Creating one to one relationship from collection 4 to colletion 5 + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table4['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table5['body']['$id'], + 'type' => 'oneToOne', + 'twoWay' => false, + 'onDelete' => 'setNull', + 'key' => $table5['body']['$id'] + ]); + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => "Title", + 'size' => 100, + 'required' => false, + 'array' => false, + 'default' => null, + ]); + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table2['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => "Rating", + 'size' => 100, + 'required' => false, + 'array' => false, + 'default' => null, + ]); + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table3['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => "Rating", + 'size' => 100, + 'required' => false, + 'array' => false, + 'default' => null, + ]); + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table4['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => "Rating", + 'size' => 100, + 'required' => false, + 'array' => false, + 'default' => null, + ]); + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table5['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => "Rating", + 'size' => 100, + 'required' => false, + 'array' => false, + 'default' => null, + ]); + + \sleep(2); + // Creating parent document with a child reference to test the permissions + $parentDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => ID::custom($table1['body']['$id']), + 'data' => [ + 'Title' => 'Captain America', + $table2['body']['$id'] => [ + '$id' => ID::custom($table2['body']['$id']), + 'Rating' => '10', + $table3['body']['$id'] => [ + '$id' => ID::custom($table3['body']['$id']), + 'Rating' => '10', + $table4['body']['$id'] => [ + '$id' => ID::custom($table4['body']['$id']), + 'Rating' => '10', + $table5['body']['$id'] => [ + '$id' => ID::custom($table5['body']['$id']), + 'Rating' => '10' + ] + ] + ] + ] + ] + ]); + + $this->assertEquals(201, $parentDocument['headers']['status-code']); + // This is the point of the test. We should not need any authorization permission to update the document with same data. + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/rows/' . $table1['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::custom($table1['body']['$id']), + 'data' => [ + 'Title' => 'Captain America', + $table2['body']['$id'] => [ + '$id' => $table2['body']['$id'], + 'Rating' => '10', + $table3['body']['$id'] => [ + '$id' => $table3['body']['$id'], + 'Rating' => '10', + $table4['body']['$id'] => [ + '$id' => $table4['body']['$id'], + 'Rating' => '10', + $table5['body']['$id'] => [ + '$id' => $table5['body']['$id'], + 'Rating' => '10' + ] + ] + ] + ] + ] + ]); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($parentDocument['body'], $response['body']); + + // Giving update permission of collection 3 to user. + $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/collection3', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::custom('collection3'), + 'name' => ID::custom('collection3'), + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($userId)), + Permission::read(Role::user($userId)), + Permission::update(Role::user($userId)), + Permission::delete(Role::user($userId)), + ] + ]); + + // This is the point of this test. We should be allowed to do this action, and it should not fail on permission check + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/rows/' . $table1['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'Title' => 'Captain America', + $table2['body']['$id'] => [ + '$id' => ID::custom($table2['body']['$id']), + 'Rating' => '10', + $table3['body']['$id'] => [ + '$id' => ID::custom($table3['body']['$id']), + 'Rating' => '11', + $table4['body']['$id'] => [ + '$id' => ID::custom($table4['body']['$id']), + 'Rating' => '10', + $table5['body']['$id'] => [ + '$id' => ID::custom($table5['body']['$id']), + 'Rating' => '11' + ] + ] + ] + ] + ] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(11, $response['body'][$table2['body']['$id']]['collection3']['Rating']); + + // We should not be allowed to update the document as we do not have permission for collection 2. + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/rows/' . $table1['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'Title' => 'Captain America', + $table2['body']['$id'] => [ + '$id' => ID::custom($table2['body']['$id']), + 'Rating' => '11', + $table3['body']['$id'] => null, + ] + ] + ]); + + $this->assertEquals(401, $response['headers']['status-code']); + + // We should not be allowed to update the document as we do not have permission for collection 2. + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table2['body']['$id'] . '/rows/' . $table2['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'Rating' => '11', + ] + ]); + + $this->assertEquals(401, $response['headers']['status-code']); + + // Removing update permission from collection 3. + $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/collection3', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::custom('collection3'), + 'name' => ID::custom('collection3'), + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($userId)), + Permission::read(Role::user($userId)), + Permission::delete(Role::user($userId)), + ] + ]); + + // Giving update permission to collection 2. + $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/collection2', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::custom('collection2'), + 'name' => ID::custom('collection2'), + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($userId)), + Permission::update(Role::user($userId)), + Permission::read(Role::user($userId)), + Permission::delete(Role::user($userId)), + ] + ]); + + // Creating collection 3 new document + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table3['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => ID::custom('collection3Doc1'), + 'data' => [ + 'Rating' => '20' + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // We should be allowed to link a new document from collection 3 to collection 2. + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/rows/' . $table1['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'Title' => 'Captain America', + $table2['body']['$id'] => [ + '$id' => ID::custom($table2['body']['$id']), + $table3['body']['$id'] => 'collection3Doc1', + ] + ] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + + // We should be allowed to link and create a new document from collection 3 to collection 2. + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/rows/' . $table1['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'Title' => 'Captain America', + $table2['body']['$id'] => [ + '$id' => ID::custom($table2['body']['$id']), + $table3['body']['$id'] => [ + '$id' => ID::custom('collection3Doc2') + ], + ] + ] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + } +} diff --git a/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php new file mode 100644 index 0000000000..dca8a16363 --- /dev/null +++ b/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php @@ -0,0 +1,4113 @@ +client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::custom('first'), + 'name' => 'Test 1', + ]); + + $this->assertEquals(201, $test1['headers']['status-code']); + $this->assertEquals('Test 1', $test1['body']['name']); + + $test2 = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::custom('second'), + 'name' => 'Test 2', + ]); + $this->assertEquals(201, $test2['headers']['status-code']); + $this->assertEquals('Test 2', $test2['body']['name']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(2, $databases['body']['total']); + $this->assertEquals($test1['body']['$id'], $databases['body']['databases'][0]['$id']); + $this->assertEquals($test2['body']['$id'], $databases['body']['databases'][1]['$id']); + + $base = array_reverse($databases['body']['databases']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::limit(1)->toString(), + ], + ]); + $this->assertEquals(200, $databases['headers']['status-code']); + $this->assertCount(1, $databases['body']['databases']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::offset(1)->toString(), + ], + ]); + $this->assertEquals(200, $databases['headers']['status-code']); + $this->assertCount(1, $databases['body']['databases']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('name', ['Test 1', 'Test 2'])->toString(), + ], + ]); + $this->assertEquals(200, $databases['headers']['status-code']); + $this->assertCount(2, $databases['body']['databases']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('name', ['Test 2'])->toString(), + ], + ]); + $this->assertEquals(200, $databases['headers']['status-code']); + $this->assertCount(1, $databases['body']['databases']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('$id', ['first'])->toString(), + ], + ]); + $this->assertEquals(200, $databases['headers']['status-code']); + $this->assertCount(1, $databases['body']['databases']); + + /** + * Test for Order + */ + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::orderDesc()->toString(), + ], + ]); + + $this->assertEquals(2, $databases['body']['total']); + $this->assertEquals($base[0]['$id'], $databases['body']['databases'][0]['$id']); + $this->assertEquals($base[1]['$id'], $databases['body']['databases'][1]['$id']); + + /** + * Test for After + */ + $base = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => $base['body']['databases'][0]['$id']]))->toString(), + ], + ]); + + $this->assertCount(1, $databases['body']['databases']); + $this->assertEquals($base['body']['databases'][1]['$id'], $databases['body']['databases'][0]['$id']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => $base['body']['databases'][1]['$id']]))->toString(), + ], + ]); + + $this->assertCount(0, $databases['body']['databases']); + $this->assertEmpty($databases['body']['databases']); + + /** + * Test for Before + */ + $base = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorBefore(new Document(['$id' => $base['body']['databases'][1]['$id']]))->toString(), + ], + ]); + + $this->assertCount(1, $databases['body']['databases']); + $this->assertEquals($base['body']['databases'][0]['$id'], $databases['body']['databases'][0]['$id']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorBefore(new Document(['$id' => $base['body']['databases'][0]['$id']]))->toString(), + ], + ]); + + $this->assertCount(0, $databases['body']['databases']); + $this->assertEmpty($databases['body']['databases']); + + /** + * Test for Search + */ + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'first' + ]); + + $this->assertEquals(1, $databases['body']['total']); + $this->assertEquals('first', $databases['body']['databases'][0]['$id']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'Test' + ]); + + $this->assertEquals(2, $databases['body']['total']); + $this->assertEquals('Test 1', $databases['body']['databases'][0]['name']); + $this->assertEquals('Test 2', $databases['body']['databases'][1]['name']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'Nonexistent' + ]); + + $this->assertEquals(0, $databases['body']['total']); + + /** + * Test for FAILURE + */ + $response = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => 'unknown']))->toString(), + ], + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // This collection already exists + $response = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'name' => 'Test 1', + 'databaseId' => ID::custom('first'), + ]); + + $this->assertEquals(409, $response['headers']['status-code']); + return ['databaseId' => $test1['body']['$id']]; + } + + /** + * @depends testListDatabases + */ + public function testGetDatabase(array $data): array + { + $databaseId = $data['databaseId']; + /** + * Test for SUCCESS + */ + $database = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $this->assertEquals(200, $database['headers']['status-code']); + $this->assertEquals($databaseId, $database['body']['$id']); + $this->assertEquals('Test 1', $database['body']['name']); + $this->assertEquals(true, $database['body']['enabled']); + return ['databaseId' => $database['body']['$id']]; + } + + /** + * @depends testListDatabases + */ + public function testUpdateDatabase(array $data) + { + $databaseId = $data['databaseId']; + + $database = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'name' => 'Test 1 Updated', + 'enabled' => false, + ]); + + $this->assertEquals(200, $database['headers']['status-code']); + $this->assertEquals('Test 1 Updated', $database['body']['name']); + $this->assertFalse($database['body']['enabled']); + + // Now update the database without the passing the enabled parameter + $database = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'name' => 'Test 1' + ]); + + $this->assertEquals(200, $database['headers']['status-code']); + $this->assertEquals('Test 1', $database['body']['name']); + $this->assertTrue($database['body']['enabled']); + } + + /** + * @depends testListDatabases + */ + public function testDeleteDatabase($data) + { + $databaseId = $data['databaseId']; + + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], $this->getHeaders())); + + $this->assertEquals(204, $response['headers']['status-code']); + $this->assertEquals("", $response['body']); + + // Try to get the collection and check if it has been deleted + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + } + + public function testListCollections(): array + { + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'invalidDocumentDatabase', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); + $this->assertTrue($database['body']['enabled']); + + $databaseId = $database['body']['$id']; + /** + * Test for SUCCESS + */ + $test1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'name' => 'Test 1', + 'tableId' => ID::custom('first'), + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'documentSecurity' => true, + ]); + + $test2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'name' => 'Test 2', + 'tableId' => ID::custom('second'), + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'documentSecurity' => true, + ]); + + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(2, $tables['body']['total']); + $this->assertEquals($test1['body']['$id'], $tables['body']['tables'][0]['$id']); + $this->assertEquals($test1['body']['enabled'], $tables['body']['tables'][0]['enabled']); + $this->assertEquals($test2['body']['$id'], $tables['body']['tables'][1]['$id']); + $this->assertEquals($test1['body']['enabled'], $tables['body']['tables'][0]['enabled']); + + $base = array_reverse($tables['body']['tables']); + + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::limit(1)->toString(), + ], + ]); + + $this->assertEquals(200, $tables['headers']['status-code']); + $this->assertCount(1, $tables['body']['tables']); + + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::offset(1)->toString(), + ], + ]); + + $this->assertEquals(200, $tables['headers']['status-code']); + $this->assertCount(1, $tables['body']['tables']); + + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('enabled', [true])->toString(), + ], + ]); + + $this->assertEquals(200, $tables['headers']['status-code']); + $this->assertCount(2, $tables['body']['tables']); + + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('enabled', [false])->toString(), + ], + ]); + + $this->assertEquals(200, $tables['headers']['status-code']); + $this->assertCount(0, $tables['body']['tables']); + + /** + * Test for Order + */ + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::orderDesc()->toString(), + ], + ]); + + $this->assertEquals(2, $tables['body']['total']); + $this->assertEquals($base[0]['$id'], $tables['body']['tables'][0]['$id']); + $this->assertEquals($base[1]['$id'], $tables['body']['tables'][1]['$id']); + + /** + * Test for After + */ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => $base['body']['tables'][0]['$id']]))->toString(), + ], + ]); + + $this->assertCount(1, $tables['body']['tables']); + $this->assertEquals($base['body']['tables'][1]['$id'], $tables['body']['tables'][0]['$id']); + + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => $base['body']['tables'][1]['$id']]))->toString(), + ], + ]); + + $this->assertCount(0, $tables['body']['tables']); + $this->assertEmpty($tables['body']['tables']); + + /** + * Test for Before + */ + $base = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorBefore(new Document(['$id' => $base['body']['tables'][1]['$id']]))->toString(), + ], + ]); + + $this->assertCount(1, $tables['body']['tables']); + $this->assertEquals($base['body']['tables'][0]['$id'], $tables['body']['tables'][0]['$id']); + + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorBefore(new Document(['$id' => $base['body']['tables'][0]['$id']]))->toString(), + ], + ]); + + $this->assertCount(0, $tables['body']['tables']); + $this->assertEmpty($tables['body']['tables']); + + /** + * Test for Search + */ + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'first' + ]); + + $this->assertEquals(1, $tables['body']['total']); + $this->assertEquals('first', $tables['body']['tables'][0]['$id']); + + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'Test' + ]); + + $this->assertEquals(2, $tables['body']['total']); + $this->assertEquals('Test 1', $tables['body']['tables'][0]['name']); + $this->assertEquals('Test 2', $tables['body']['tables'][1]['name']); + + $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'Nonexistent' + ]); + + $this->assertEquals(0, $tables['body']['total']); + + /** + * Test for FAILURE + */ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => 'unknown']))->toString(), + ], + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // This collection already exists + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'name' => 'Test 1', + 'tableId' => ID::custom('first'), + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(409, $response['headers']['status-code']); + return [ + 'databaseId' => $databaseId, + 'tableId' => $test1['body']['$id'], + ]; + } + + /** + * @depends testListCollections + */ + public function testGetCollection(array $data): void + { + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + $table = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], $this->getHeaders())); + + $this->assertEquals(200, $table['headers']['status-code']); + $this->assertEquals('Test 1', $table['body']['name']); + $this->assertEquals('first', $table['body']['$id']); + $this->assertTrue($table['body']['enabled']); + } + + /** + * @depends testListCollections + */ + public function testUpdateCollection(array $data) + { + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + $table = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'name' => 'Test 1 Updated', + 'enabled' => false + ]); + + $this->assertEquals(200, $table['headers']['status-code']); + $this->assertEquals('Test 1 Updated', $table['body']['name']); + $this->assertEquals('first', $table['body']['$id']); + $this->assertFalse($table['body']['enabled']); + } + + /** + * @depends testListCollections + */ + public function testCreateEncryptedAttribute(array $data): void + { + + $databaseId = $data['databaseId']; + + /** + * Test for SUCCESS + */ + + // Create collection + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Encrypted Actors Data', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $actors['headers']['status-code']); + $this->assertEquals($actors['body']['name'], 'Encrypted Actors Data'); + + /** + * Test for creating encrypted attributes + */ + + $columnsPath = '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/columns'; + + $firstName = $this->client->call(Client::METHOD_POST, $columnsPath . '/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'firstName', + 'size' => 256, + 'required' => true, + ]); + + $lastName = $this->client->call(Client::METHOD_POST, $columnsPath . '/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'lastName', + 'size' => 256, + 'required' => true, + 'encrypt' => true, + ]); + + + /** + * Check status of every attribute + */ + $this->assertEquals(202, $firstName['headers']['status-code']); + $this->assertEquals('firstName', $firstName['body']['key']); + $this->assertEquals('string', $firstName['body']['type']); + + $this->assertEquals(202, $lastName['headers']['status-code']); + $this->assertEquals('lastName', $lastName['body']['key']); + $this->assertEquals('string', $lastName['body']['type']); + + // Wait for database worker to finish creating attributes + sleep(2); + + // Creating document to ensure cache is purged on schema change + $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => ID::unique(), + 'data' => [ + 'firstName' => 'Jonah', + 'lastName' => 'Jameson', + ], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + // Check document to ensure cache is purged on schema change + $row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/rows/' . $row['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals('Jonah', $row['body']['firstName']); + $this->assertEquals('Jameson', $row['body']['lastName']); + } + + public function testDeleteAttribute(): array + { + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'invalidDocumentDatabase', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); + + $databaseId = $database['body']['$id']; + /** + * Test for SUCCESS + */ + + // Create collection + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Actors', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $actors['headers']['status-code']); + $this->assertEquals($actors['body']['name'], 'Actors'); + + $firstName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'firstName', + 'size' => 256, + 'required' => true, + ]); + + $lastName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'lastName', + 'size' => 256, + 'required' => true, + ]); + + $unneeded = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'unneeded', + 'size' => 256, + 'required' => true, + ]); + + // Wait for database worker to finish creating attributes + sleep(2); + + // Creating document to ensure cache is purged on schema change + $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => ID::unique(), + 'data' => [ + 'firstName' => 'lorem', + 'lastName' => 'ipsum', + 'unneeded' => 'dolor' + ], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'key_lastName', + 'type' => 'key', + 'columns' => [ + 'lastName', + ], + ]); + + // Wait for database worker to finish creating index + sleep(2); + + $table = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), []); + + $unneededId = $unneeded['body']['key']; + + $this->assertEquals(200, $table['headers']['status-code']); + $this->assertIsArray($table['body']['columns']); + $this->assertCount(3, $table['body']['columns']); + $this->assertEquals($table['body']['columns'][0]['key'], $firstName['body']['key']); + $this->assertEquals($table['body']['columns'][1]['key'], $lastName['body']['key']); + $this->assertEquals($table['body']['columns'][2]['key'], $unneeded['body']['key']); + $this->assertCount(1, $table['body']['indexes']); + $this->assertEquals($table['body']['indexes'][0]['key'], $index['body']['key']); + + // Delete attribute + $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/columns/' . $unneededId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(204, $attribute['headers']['status-code']); + + sleep(2); + + // Check document to ensure cache is purged on schema change + $row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/rows/' . $row['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertNotContains($unneededId, $row['body']); + + $table = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), []); + + $this->assertEquals(200, $table['headers']['status-code']); + $this->assertIsArray($table['body']['columns']); + $this->assertCount(2, $table['body']['columns']); + $this->assertEquals($table['body']['columns'][0]['key'], $firstName['body']['key']); + $this->assertEquals($table['body']['columns'][1]['key'], $lastName['body']['key']); + + return [ + 'tableId' => $actors['body']['$id'], + 'key' => $index['body']['key'], + 'databaseId' => $databaseId + ]; + } + + /** + * @depends testDeleteAttribute + */ + public function testDeleteIndex($data): array + { + $databaseId = $data['databaseId']; + $index = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/indexes/' . $data['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(204, $index['headers']['status-code']); + + // Wait for database worker to finish deleting index + sleep(2); + + $table = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['tableId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), []); + + $this->assertCount(0, $table['body']['indexes']); + + return $data; + } + + /** + * @depends testDeleteIndex + */ + public function testDeleteIndexOnDeleteAttribute($data) + { + $databaseId = $data['databaseId']; + $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'attribute1', + 'size' => 16, + 'required' => true, + ]); + + $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'attribute2', + 'size' => 16, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute1['headers']['status-code']); + $this->assertEquals(202, $attribute2['headers']['status-code']); + $this->assertEquals('attribute1', $attribute1['body']['key']); + $this->assertEquals('attribute2', $attribute2['body']['key']); + + sleep(2); + + $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'index1', + 'type' => 'key', + 'columns' => ['attribute1', 'attribute2'], + 'orders' => ['ASC', 'ASC'], + ]); + + $index2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'index2', + 'type' => 'key', + 'columns' => ['attribute2'], + ]); + + $this->assertEquals(202, $index1['headers']['status-code']); + $this->assertEquals(202, $index2['headers']['status-code']); + $this->assertEquals('index1', $index1['body']['key']); + $this->assertEquals('index2', $index2['body']['key']); + + sleep(2); + + // Expected behavior: deleting attribute2 will cause index2 to be dropped, and index1 rebuilt with a single key + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/' . $attribute2['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(204, $deleted['headers']['status-code']); + + // wait for database worker to complete + sleep(2); + + $table = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['tableId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $table['headers']['status-code']); + $this->assertIsArray($table['body']['indexes']); + $this->assertCount(1, $table['body']['indexes']); + $this->assertEquals($index1['body']['key'], $table['body']['indexes'][0]['key']); + $this->assertIsArray($table['body']['indexes'][0]['columns']); + $this->assertCount(1, $table['body']['indexes'][0]['columns']); + $this->assertEquals($attribute1['body']['key'], $table['body']['indexes'][0]['columns'][0]); + + // Delete attribute + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/' . $attribute1['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(204, $deleted['headers']['status-code']); + + return $data; + } + + public function testCleanupDuplicateIndexOnDeleteAttribute() + { + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'invalidDocumentDatabase', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); + + $databaseId = $database['body']['$id']; + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCleanupDuplicateIndexOnDeleteAttribute', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + $this->assertNotEmpty($table['body']['$id']); + + $tableId = $table['body']['$id']; + + $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'attribute1', + 'size' => 16, + 'required' => true, + ]); + + $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'attribute2', + 'size' => 16, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute1['headers']['status-code']); + $this->assertEquals(202, $attribute2['headers']['status-code']); + $this->assertEquals('attribute1', $attribute1['body']['key']); + $this->assertEquals('attribute2', $attribute2['body']['key']); + + sleep(2); + + $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'index1', + 'type' => 'key', + 'columns' => ['attribute1', 'attribute2'], + 'orders' => ['ASC', 'ASC'], + ]); + + $index2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'index2', + 'type' => 'key', + 'columns' => ['attribute2'], + ]); + + $this->assertEquals(202, $index1['headers']['status-code']); + $this->assertEquals(202, $index2['headers']['status-code']); + $this->assertEquals('index1', $index1['body']['key']); + $this->assertEquals('index2', $index2['body']['key']); + + sleep(2); + + // Expected behavior: deleting attribute1 would cause index1 to be a duplicate of index2 and automatically removed + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $attribute1['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(204, $deleted['headers']['status-code']); + + // wait for database worker to complete + sleep(2); + + $table = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $table['headers']['status-code']); + $this->assertIsArray($table['body']['indexes']); + $this->assertCount(1, $table['body']['indexes']); + $this->assertEquals($index2['body']['key'], $table['body']['indexes'][0]['key']); + $this->assertIsArray($table['body']['indexes'][0]['columns']); + $this->assertCount(1, $table['body']['indexes'][0]['columns']); + $this->assertEquals($attribute2['body']['key'], $table['body']['indexes'][0]['columns'][0]); + + // Delete attribute + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $attribute2['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(204, $deleted['headers']['status-code']); + } + + /** + * @depends testDeleteIndexOnDeleteAttribute + */ + public function testDeleteCollection($data) + { + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + // Add Documents to the collection + $row1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'firstName' => 'Tom', + 'lastName' => 'Holland', + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ], + ]); + + $row2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'firstName' => 'Samuel', + 'lastName' => 'Jackson', + ], + 'permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ], + ]); + + $this->assertEquals(201, $row1['headers']['status-code']); + $this->assertIsArray($row1['body']['$permissions']); + $this->assertCount(3, $row1['body']['$permissions']); + $this->assertEquals($row1['body']['firstName'], 'Tom'); + $this->assertEquals($row1['body']['lastName'], 'Holland'); + + $this->assertEquals(201, $row2['headers']['status-code']); + $this->assertIsArray($row2['body']['$permissions']); + $this->assertCount(3, $row2['body']['$permissions']); + $this->assertEquals($row2['body']['firstName'], 'Samuel'); + $this->assertEquals($row2['body']['lastName'], 'Jackson'); + + // Delete the actors collection + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], $this->getHeaders())); + + $this->assertEquals(204, $response['headers']['status-code']); + $this->assertEquals($response['body'], ""); + + // Try to get the collection and check if it has been deleted + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + } + + /** + * @throws Exception + */ + public function testDeleteCollectionDeletesRelatedAttributes(): void + { + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'databaseId' => ID::unique(), + 'name' => 'TestDeleteCollectionDeletesRelatedAttributes', + ]); + + $databaseId = $database['body']['$id']; + + $table1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Collection1', + 'documentSecurity' => false, + 'permissions' => [], + ]); + + $table2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Collection2', + 'documentSecurity' => false, + 'permissions' => [], + ]); + + $table1 = $table1['body']['$id']; + $table2 = $table2['body']['$id']; + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1 . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'relatedTableId' => $table2, + 'type' => Database::RELATION_MANY_TO_ONE, + 'twoWay' => false, + 'key' => 'collection2' + ]); + + sleep(2); + + $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $table2, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $this->getHeaders())); + + sleep(2); + + $columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1 . '/columns', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $this->getHeaders())); + + $this->assertEquals(0, $columns['body']['total']); + } + + public function testAttributeRowWidthLimit() + { + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'invalidDocumentDatabase', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); + + $databaseId = $database['body']['$id']; + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::custom('attributeRowWidthLimit'), + 'name' => 'attributeRowWidthLimit', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + $this->assertEquals($table['body']['name'], 'attributeRowWidthLimit'); + + $tableId = $table['body']['$id']; + + // Add wide string attributes to approach row width limit + for ($i = 0; $i < 15; $i++) { + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => "attribute{$i}", + 'size' => 1024, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + } + + sleep(5); + + $tooWide = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'tooWide', + 'size' => 1024, + 'required' => true, + ]); + + $this->assertEquals(400, $tooWide['headers']['status-code']); + $this->assertEquals('column_limit_exceeded', $tooWide['body']['type']); + } + + public function testIndexLimitException() + { + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'invalidDocumentDatabase', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); + + $databaseId = $database['body']['$id']; + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::custom('testLimitException'), + 'name' => 'testLimitException', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + $this->assertEquals('testLimitException', $table['body']['name']); + + $tableId = $table['body']['$id']; + + // add unique attributes for indexing + for ($i = 0; $i < 64; $i++) { + // $this->assertEquals(true, static::getDatabase()->createAttribute('indexLimit', "test{$i}", Database::VAR_STRING, 16, true)); + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => "attribute{$i}", + 'size' => 64, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + } + + sleep(10); + + $table = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $table['headers']['status-code']); + $this->assertEquals($table['body']['name'], 'testLimitException'); + $this->assertIsArray($table['body']['columns']); + $this->assertIsArray($table['body']['indexes']); + $this->assertCount(64, $table['body']['columns']); + $this->assertCount(0, $table['body']['indexes']); + + foreach ($table['body']['columns'] as $attribute) { + $this->assertEquals('available', $attribute['status'], 'attribute: ' . $attribute['key']); + } + + // Test indexLimit = 64 + // MariaDB, MySQL, and MongoDB create 6 indexes per new collection + // Add up to the limit, then check if the next index throws IndexLimitException + for ($i = 0; $i < 58; $i++) { + $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => "key_attribute{$i}", + 'type' => 'key', + 'columns' => ["attribute{$i}"], + ]); + + $this->assertEquals(202, $index['headers']['status-code']); + $this->assertEquals("key_attribute{$i}", $index['body']['key']); + } + + sleep(5); + + $table = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $table['headers']['status-code']); + $this->assertEquals($table['body']['name'], 'testLimitException'); + $this->assertIsArray($table['body']['columns']); + $this->assertIsArray($table['body']['indexes']); + $this->assertCount(64, $table['body']['columns']); + $this->assertCount(58, $table['body']['indexes']); + + $tooMany = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'tooMany', + 'type' => 'key', + 'columns' => ['attribute61'], + ]); + + $this->assertEquals(400, $tooMany['headers']['status-code']); + $this->assertEquals('Index limit exceeded', $tooMany['body']['message']); + + $table = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(204, $table['headers']['status-code']); + } + + public function testAttributeUpdate(): array + { + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'updateAttributes', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + + $databaseId = $database['body']['$id']; + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::custom('updateAttributes'), + 'name' => 'updateAttributes' + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + + $tableId = $table['body']['$id']; + + /** + * Create String Attribute + */ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'string', + 'size' => 1024, + 'required' => false + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + + /** + * Create Email Attribute + */ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'email', + 'required' => false + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + + /** + * Create IP Attribute + */ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'ip', + 'required' => false + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + + /** + * Create URL Attribute + */ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'url', + 'required' => false + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + + /** + * Create Integer Attribute + */ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'integer', + 'required' => false + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + + /** + * Create Float Attribute + */ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'float', + 'required' => false + ]); + + /** + * Create Boolean Attribute + */ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'boolean', + 'required' => false + ]); + + /** + * Create Datetime Attribute + */ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'datetime', + 'required' => false + ]); + + /** + * Create Enum Attribute + */ + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'enum', + 'required' => false, + 'elements' => ['lorem', 'ipsum'] + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + + sleep(5); + + return [ + 'databaseId' => $databaseId, + 'tableId' => $tableId + ]; + } + + /** + * @depends testAttributeUpdate + */ + public function testAttributeUpdateString(array $data) + { + $key = 'string'; + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'lorem' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals('lorem', $new['body']['default']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($attribute); + $this->assertFalse($attribute['required']); + $this->assertEquals('lorem', $attribute['default']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => null + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertNull($new['body']['default']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'ipsum' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals('ipsum', $new['body']['default']); + + /** + * Test against failure + */ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => 'i am no boolean', + 'default' => 'dolor' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 123 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'default' => 'ipsum' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + 'default' => 'ipsum' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + } + + /** + * @depends testAttributeUpdate + */ + public function testAttributeUpdateEmail(array $data) + { + $key = 'email'; + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'torsten@appwrite.io' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals('torsten@appwrite.io', $new['body']['default']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($attribute); + $this->assertFalse($attribute['required']); + $this->assertEquals('torsten@appwrite.io', $attribute['default']); + + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => null + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertNull($new['body']['default']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'eldad@appwrite.io' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals('eldad@appwrite.io', $new['body']['default']); + + /** + * Test against failure + */ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => 'no boolean', + 'default' => 'torsten@appwrite.io' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'i am no email' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'default' => 'ipsum' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + 'default' => 'torsten@appwrite.io' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + } + + /** + * @depends testAttributeUpdate + */ + public function testAttributeUpdateIp(array $data) + { + $key = 'ip'; + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => '127.0.0.1' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals('127.0.0.1', $new['body']['default']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($attribute); + $this->assertFalse($attribute['required']); + $this->assertEquals('127.0.0.1', $attribute['default']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => null + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertNull($new['body']['default']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => '192.168.0.1' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals('192.168.0.1', $new['body']['default']); + + /** + * Test against failure + */ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => 'no boolean', + 'default' => '127.0.0.1' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'i am no ip' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'default' => '127.0.0.1' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + 'default' => '127.0.0.1' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + } + + /** + * @depends testAttributeUpdate + */ + public function testAttributeUpdateUrl(array $data) + { + $key = 'url'; + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'http://appwrite.io' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals('http://appwrite.io', $new['body']['default']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($attribute); + $this->assertFalse($attribute['required']); + $this->assertEquals('http://appwrite.io', $attribute['default']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => null + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertNull($new['body']['default']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'https://appwrite.io' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals('https://appwrite.io', $new['body']['default']); + + /** + * Test against failure + */ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => 'no boolean', + 'default' => 'https://appwrite.io' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'i am no url' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'default' => 'https://appwrite.io' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + 'default' => 'https://appwrite.io' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + } + + /** + * @depends testAttributeUpdate + */ + public function testAttributeUpdateInteger(array $data) + { + $key = 'integer'; + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 123, + 'min' => 0, + 'max' => 1000 + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals(123, $new['body']['default']); + $this->assertEquals(0, $new['body']['min']); + $this->assertEquals(1000, $new['body']['max']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($attribute); + $this->assertFalse($attribute['required']); + $this->assertEquals(123, $attribute['default']); + $this->assertEquals(0, $attribute['min']); + $this->assertEquals(1000, $attribute['max']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => null, + 'min' => 0, + 'max' => 1000 + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertNull($new['body']['default']); + $this->assertEquals(0, $new['body']['min']); + $this->assertEquals(1000, $new['body']['max']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 456, + 'min' => 100, + 'max' => 2000 + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals(456, $new['body']['default']); + $this->assertEquals(100, $new['body']['min']); + $this->assertEquals(2000, $new['body']['max']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 100, + 'min' => 0, + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 10, + 'max' => 100, + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + /** + * Test against failure + */ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => 'no boolean', + 'default' => 123, + 'min' => 0, + 'max' => 500 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'i am no integer', + 'min' => 0, + 'max' => 500 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 100, + 'min' => 'i am no integer', + 'max' => 500 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 100, + 'min' => 0, + 'max' => 'i am no integer' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'min' => 0, + 'max' => 100, + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'default' => 50, + 'min' => 0, + 'max' => 100, + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + 'default' => 50, + 'min' => 0, + 'max' => 100 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 50, + 'min' => 55, + 'max' => 100 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 105, + 'min' => 50, + 'max' => 100 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 50, + 'min' => 200, + 'max' => 100 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + } + + /** + * @depends testAttributeUpdate + */ + public function testAttributeUpdateFloat(array $data) + { + $key = 'float'; + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 123.456, + 'min' => 0.0, + 'max' => 1000.0 + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals(123.456, $new['body']['default']); + $this->assertEquals(0, $new['body']['min']); + $this->assertEquals(1000, $new['body']['max']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($attribute); + $this->assertFalse($attribute['required']); + $this->assertEquals(123.456, $attribute['default']); + $this->assertEquals(0, $attribute['min']); + $this->assertEquals(1000, $attribute['max']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => null, + 'min' => 0.0, + 'max' => 1000.0 + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertNull($new['body']['default']); + $this->assertEquals(0, $new['body']['min']); + $this->assertEquals(1000, $new['body']['max']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 456.789, + 'min' => 123.456, + 'max' => 2000.0 + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals(456.789, $new['body']['default']); + $this->assertEquals(123.456, $new['body']['min']); + $this->assertEquals(2000, $new['body']['max']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 123.456, + 'min' => 0.0, + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 23.456, + 'max' => 100.0, + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + /** + * Test against failure + */ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => 'no boolean', + 'default' => 123.456, + 'min' => 0.0, + 'max' => 1000.0 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'i am no integer', + 'min' => 0.0, + 'max' => 500.0 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 123.456, + 'min' => 'i am no integer', + 'max' => 500.0 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 123.456, + 'min' => 0.0, + 'max' => 'i am no integer' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'min' => 0.0, + 'max' => 100.0, + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'default' => 123.456, + 'min' => 0.0, + 'max' => 100.0, + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + 'default' => 123.456, + 'min' => 0.0, + 'max' => 100.0 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 123.456, + 'min' => 200.0, + 'max' => 300.0 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 123.456, + 'min' => 0.0, + 'max' => 100.0 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 50.0, + 'min' => 200.0, + 'max' => 100.0 + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + } + + /** + * @depends testAttributeUpdate + */ + public function testAttributeUpdateBoolean(array $data) + { + $key = 'boolean'; + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => true + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals(true, $new['body']['default']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($attribute); + $this->assertFalse($attribute['required']); + $this->assertEquals(true, $attribute['default']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => null + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertNull($new['body']['default']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => false + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals(false, $new['body']['default']); + + /** + * Test against failure + */ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => 'no boolean', + 'default' => true + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'i am no boolean' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'default' => false + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + 'default' => true + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + } + + /** + * @depends testAttributeUpdate + */ + public function testAttributeUpdateDatetime(array $data) + { + $key = 'datetime'; + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => '1975-06-12 14:12:55+02:00' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals('1975-06-12 14:12:55+02:00', $new['body']['default']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($attribute); + $this->assertFalse($attribute['required']); + $this->assertEquals('1975-06-12 14:12:55+02:00', $attribute['default']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => null + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertNull($new['body']['default']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => '1965-06-12 14:12:55+02:00' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals('1965-06-12 14:12:55+02:00', $new['body']['default']); + + /** + * Test against failure + */ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => 'no boolean', + 'default' => '1975-06-12 14:12:55+02:00' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'i am no datetime' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'default' => '1975-06-12 14:12:55+02:00' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + 'default' => '1975-06-12 14:12:55+02:00' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + } + + /** + * @depends testAttributeUpdate + */ + public function testAttributeUpdateEnum(array $data) + { + $key = 'enum'; + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'elements' => ['lorem', 'ipsum', 'dolor'], + 'required' => false, + 'default' => 'lorem' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals('lorem', $new['body']['default']); + $this->assertCount(3, $new['body']['elements']); + $this->assertContains('lorem', $new['body']['elements']); + $this->assertContains('ipsum', $new['body']['elements']); + $this->assertContains('dolor', $new['body']['elements']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($attribute); + $this->assertFalse($attribute['required']); + $this->assertEquals('lorem', $attribute['default']); + $this->assertCount(3, $attribute['elements']); + $this->assertContains('lorem', $attribute['elements']); + $this->assertContains('ipsum', $attribute['elements']); + $this->assertContains('dolor', $attribute['elements']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'elements' => ['lorem', 'ipsum', 'dolor'], + 'required' => false, + 'default' => null + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertNull($new['body']['default']); + $this->assertCount(3, $new['body']['elements']); + $this->assertContains('lorem', $new['body']['elements']); + $this->assertContains('ipsum', $new['body']['elements']); + $this->assertContains('dolor', $new['body']['elements']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'elements' => ['ipsum', 'dolor'], + 'required' => false, + 'default' => 'dolor' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertFalse($new['body']['required']); + $this->assertEquals('dolor', $new['body']['default']); + $this->assertCount(2, $new['body']['elements']); + $this->assertContains('ipsum', $new['body']['elements']); + $this->assertContains('dolor', $new['body']['elements']); + + /** + * Test against failure + */ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'elements' => [], + 'required' => false, + 'default' => 'lorem' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'elements' => ['ipsum', 'dolor'], + 'required' => false, + 'default' => 'lorem' + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_VALUE_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => 'no boolean', + 'default' => 'lorem', + 'elements' => ['lorem', 'ipsum', 'dolor'], + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 123, + 'elements' => ['lorem', 'ipsum', 'dolor'], + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'lorem', + 'elements' => 'i am no array', + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'lorem', + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + 'elements' => ['lorem', 'ipsum', 'dolor'], + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'default' => 'lorem', + 'elements' => ['lorem', 'ipsum', 'dolor'], + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => true, + 'default' => 'lorem', + 'elements' => ['lorem', 'ipsum', 'dolor'], + ]); + + $this->assertEquals(400, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_DEFAULT_UNSUPPORTED, $update['body']['type']); + } + + /** + * @depends testAttributeUpdate + */ + public function testAttributeUpdateStringResize(array $data) + { + $key = 'string'; + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + $row = $this->client->call( + Client::METHOD_POST, + '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), + [ + 'rowId' => 'unique()', + 'data' => [ + 'string' => 'string' + ], + "permissions" => ["read(\"any\")"] + ] + ); + + // Test Resize Up + $attribute = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'size' => 2048, + 'default' => '', + 'required' => false + ]); + + $this->assertEquals(200, $attribute['headers']['status-code']); + $this->assertEquals(2048, $attribute['body']['size']); + + // Test create new document with new size + $newDoc = $this->client->call( + Client::METHOD_POST, + '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), + [ + 'rowId' => 'unique()', + 'data' => [ + 'string' => str_repeat('a', 2048) + ], + "permissions" => ["read(\"any\")"] + ] + ); + + $this->assertEquals(201, $newDoc['headers']['status-code']); + $this->assertEquals(2048, strlen($newDoc['body']['string'])); + + // Test update document with new size + $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'string' => str_repeat('a', 2048) + ] + ]); + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals(2048, strlen($row['body']['string'])); + + // Test Exception on resize down with data that is too large + $attribute = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'size' => 10, + 'default' => '', + 'required' => false + ]); + + $this->assertEquals(400, $attribute['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_INVALID_RESIZE, $attribute['body']['type']); + + // original documents to original size, remove new document + $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'string' => 'string' + ] + ]); + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals('string', $row['body']['string']); + + $deleteDoc = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $newDoc['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(204, $deleteDoc['headers']['status-code']); + + + // Test Resize Down + $attribute = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'size' => 10, + 'default' => '', + 'required' => false + ]); + + $this->assertEquals(200, $attribute['headers']['status-code']); + $this->assertEquals(10, $attribute['body']['size']); + + // Test create new document with new size + $newDoc = $this->client->call( + Client::METHOD_POST, + '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), + [ + 'rowId' => 'unique()', + 'data' => [ + 'string' => str_repeat('a', 10) + ], + "permissions" => ["read(\"any\")"] + ] + ); + + $this->assertEquals(201, $newDoc['headers']['status-code']); + $this->assertEquals(10, strlen($newDoc['body']['string'])); + + // Test update document with new size + $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'string' => str_repeat('a', 10) + ] + ]); + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals(10, strlen($row['body']['string'])); + + // Try create document with string that is too large + $newDoc = $this->client->call( + Client::METHOD_POST, + '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), + [ + 'rowId' => 'unique()', + 'data' => [ + 'string' => str_repeat('a', 11) + ], + "permissions" => ["read(\"any\")"] + ] + ); + + $this->assertEquals(400, $newDoc['headers']['status-code']); + $this->assertEquals(AppwriteException::ROW_INVALID_STRUCTURE, $newDoc['body']['type']); + } + + /** + * @depends testAttributeUpdate + */ + public function testAttributeUpdateNotFound(array $data) + { + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + $columns = [ + 'string' => [ + 'required' => false, + 'default' => 'ipsum' + ], + 'email' => [ + 'required' => false, + 'default' => 'eldad@appwrite.io' + ], + 'ip' => [ + 'required' => false, + 'default' => '127.0.0.1' + ], + 'url' => [ + 'required' => false, + 'default' => 'https://appwrite.io' + ], + 'integer' => [ + 'required' => false, + 'default' => 5, + 'min' => 0, + 'max' => 10 + ], + 'float' => [ + 'required' => false, + 'default' => 5.5, + 'min' => 0.0, + 'max' => 10.0 + ], + 'datetime' => [ + 'required' => false, + 'default' => '1975-06-12 14:12:55+02:00' + ], + 'enum' => [ + 'elements' => ['lorem', 'ipsum', 'dolor'], + 'required' => false, + 'default' => 'lorem' + ] + ]; + + foreach ($columns as $key => $payload) { + /** + * Check if Database exists + */ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/i_dont_exist/tables/' . $tableId . '/columns/' . $key . '/unknown_' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), $payload); + + $this->assertEquals(404, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::DATABASE_NOT_FOUND, $update['body']['type']); + + /** + * Check if Collection exists + */ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/i_dont_exist/columns/' . $key . '/unknown_' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), $payload); + + $this->assertEquals(404, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::TABLE_NOT_FOUND, $update['body']['type']); + + /** + * Check if Attribute exists + */ + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key . '/unknown_' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), $payload); + + $this->assertEquals(404, $update['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_NOT_FOUND, $update['body']['type']); + } + } + + /** + * @depends testAttributeUpdate + */ + public function testAttributeRename(array $data) + { + $key = 'string'; + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + + // Create document to test against + $row = $this->client->call( + Client::METHOD_POST, + '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), + [ + 'rowId' => 'unique()', + 'data' => [ + 'string' => 'string' + ], + "permissions" => ["read(\"any\")"] + ] + ); + + $this->assertEquals(201, $row['headers']['status-code']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 'lorum', + 'newKey' => 'new_string', + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $key = 'new_string'; + + $new = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals('new_string', $new['body']['key']); + + $doc1 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertArrayHasKey('new_string', $doc1['body']); + $this->assertEquals('string', $doc1['body']['new_string']); + $this->assertArrayNotHasKey('string', $doc1['body']); + + // Try and create a new document with the new attribute + $doc2 = $this->client->call( + Client::METHOD_POST, + '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), + [ + 'rowId' => 'unique()', + 'data' => [ + 'new_string' => 'string' + ], + "permissions" => ["read(\"any\")"] + ] + ); + + $this->assertEquals(201, $doc2['headers']['status-code']); + $this->assertArrayHasKey('new_string', $doc2['body']); + $this->assertEquals('string', $doc2['body']['new_string']); + + // Expect fail, try and create a new document with the old attribute + $doc3 = $this->client->call( + Client::METHOD_POST, + '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), + [ + 'rowId' => 'unique()', + 'data' => [ + 'string' => 'string' + ], + "permissions" => ["read(\"any\")"] + ] + ); + + $this->assertEquals(400, $doc3['headers']['status-code']); + } + + public function createRelationshipCollections() + { + // Prepare the database with collections and relationships + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => 'database1', + 'name' => 'Test Database' + ]); + + $databaseId = $database['body']['$id']; + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'collection1', + 'name' => 'level1', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'collection2', + 'name' => 'level2', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ]); + + \sleep(2); + } + + public function cleanupRelationshipCollection() + { + $this->client->call(Client::METHOD_DELETE, '/databases/database1', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + \sleep(2); + } + + public function testAttributeRenameRelationshipOneToMany() + { + $databaseId = 'database1'; + $table1Id = 'collection1'; + $table2Id = 'collection2'; + + $this->createRelationshipCollections(); + + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table2Id, + 'type' => 'oneToMany', + 'twoWay' => true, + 'onDelete' => 'cascade', + 'key' => 'level2', + 'twoWayKey' => 'level1' + ]); + + \sleep(3); + + $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $table1RelationAttribute = $table1Attributes['body']['columns'][0]; + + $this->assertEquals($relation['body']['side'], $table1RelationAttribute['side']); + $this->assertEquals($relation['body']['twoWayKey'], $table1RelationAttribute['twoWayKey']); + $this->assertEquals($relation['body']['relatedTable'], $table1RelationAttribute['relatedTable']); + + // Create a document for checking later + $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'unique()', + 'data' => [ + 'level2' => [[ + '$id' => 'unique()', + '$permissions' => ["read(\"any\")"] + ]], + ], + "permissions" => ["read(\"any\")"] + ]); + + $this->assertEquals(201, $originalDocument['headers']['status-code']); + + // Rename the attribute + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/level2' . '/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'newKey' => 'new_level_2' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + // Check the document's key has been renamed + $newDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows/' . $originalDocument['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertArrayHasKey('new_level_2', $newDocument['body']); + $this->assertEquals(1, count($newDocument['body']['new_level_2'])); + $this->assertArrayNotHasKey('level2', $newDocument['body']); + + // Check level2 document has been renamed + $level2Document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id . '/rows/' . $newDocument['body']['new_level_2'][0]['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertArrayHasKey('level1', $level2Document['body']); + $this->assertNotEmpty($level2Document['body']['level1']); + + // Check if attribute was renamed on the parent's side + $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $this->assertEquals(200, $table1Attributes['headers']['status-code']); + $this->assertEquals(1, count($table1Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $table1Attributes['body']['columns'][0]['key']); + + // Check if attribute was renamed on the child's side + $table2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $this->assertEquals(200, $table2Attributes['headers']['status-code']); + $this->assertEquals(1, count($table2Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $table2Attributes['body']['columns'][0]['twoWayKey']); + + $this->cleanupRelationshipCollection(); + } + + public function testAttributeRenameRelationshipOneToOne() + { + $databaseId = 'database1'; + $table1Id = 'collection1'; + $table2Id = 'collection2'; + + $this->createRelationshipCollections(); + + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table2Id, + 'type' => 'oneToOne', + 'twoWay' => true, + 'onDelete' => 'cascade', + 'key' => 'level2', + 'twoWayKey' => 'level1' + ]); + + \sleep(3); + + $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $table1RelationAttribute = $table1Attributes['body']['columns'][0]; + + $this->assertEquals($relation['body']['side'], $table1RelationAttribute['side']); + $this->assertEquals($relation['body']['twoWayKey'], $table1RelationAttribute['twoWayKey']); + $this->assertEquals($relation['body']['relatedTable'], $table1RelationAttribute['relatedTable']); + + // Create a document for checking later + $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'unique()', + 'data' => [ + 'level2' => [ + '$id' => 'unique()', + '$permissions' => ["read(\"any\")"] + ], + ], + "permissions" => ["read(\"any\")"] + ]); + + $this->assertEquals(201, $originalDocument['headers']['status-code']); + + // Rename the attribute + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/level2' . '/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'newKey' => 'new_level_2' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + // Check the document's key has been renamed + $newDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows/' . $originalDocument['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertArrayHasKey('new_level_2', $newDocument['body']); + $this->assertNotEmpty($newDocument['body']['new_level_2']); + $this->assertArrayNotHasKey('level2', $newDocument['body']); + + // Check level2 document has been renamed + $level2Document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id . '/rows/' . $newDocument['body']['new_level_2']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertArrayHasKey('level1', $level2Document['body']); + $this->assertNotEmpty($level2Document['body']['level1']); + + // Check if attribute was renamed on the parent's side + $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $this->assertEquals(200, $table1Attributes['headers']['status-code']); + $this->assertEquals(1, count($table1Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $table1Attributes['body']['columns'][0]['key']); + + // Check if attribute was renamed on the child's side + $table2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $this->assertEquals(200, $table2Attributes['headers']['status-code']); + $this->assertEquals(1, count($table2Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $table2Attributes['body']['columns'][0]['twoWayKey']); + + $this->cleanupRelationshipCollection(); + } + + public function testAttributeRenameRelationshipManyToOne() + { + $databaseId = 'database1'; + $table1Id = 'collection1'; + $table2Id = 'collection2'; + + $this->createRelationshipCollections(); + + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table2Id, + 'type' => 'manyToOne', + 'twoWay' => true, + 'onDelete' => 'cascade', + 'key' => 'level2', + 'twoWayKey' => 'level1' + ]); + + \sleep(3); + + $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $table1RelationAttribute = $table1Attributes['body']['columns'][0]; + + $this->assertEquals($relation['body']['side'], $table1RelationAttribute['side']); + $this->assertEquals($relation['body']['twoWayKey'], $table1RelationAttribute['twoWayKey']); + $this->assertEquals($relation['body']['relatedTable'], $table1RelationAttribute['relatedTable']); + + // Create a document for checking later + $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'unique()', + 'data' => [ + 'level2' => [ + '$id' => 'unique()', + '$permissions' => ["read(\"any\")"] + ], + ], + "permissions" => ["read(\"any\")"] + ]); + + $this->assertEquals(201, $originalDocument['headers']['status-code']); + + // Rename the attribute + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/level2' . '/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'newKey' => 'new_level_2' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + // Check the document's key has been renamed + $newDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows/' . $originalDocument['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertArrayHasKey('new_level_2', $newDocument['body']); + $this->assertNotEmpty($newDocument['body']['new_level_2']); + $this->assertArrayNotHasKey('level2', $newDocument['body']); + + // Check level2 document has been renamed + $level2Document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id . '/rows/' . $newDocument['body']['new_level_2']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertArrayHasKey('level1', $level2Document['body']); + $this->assertNotEmpty($level2Document['body']['level1']); + + // Check if attribute was renamed on the parent's side + $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $this->assertEquals(200, $table1Attributes['headers']['status-code']); + $this->assertEquals(1, count($table1Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $table1Attributes['body']['columns'][0]['key']); + + // Check if attribute was renamed on the child's side + $table2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $this->assertEquals(200, $table2Attributes['headers']['status-code']); + $this->assertEquals(1, count($table2Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $table2Attributes['body']['columns'][0]['twoWayKey']); + + $this->cleanupRelationshipCollection(); + } + + public function testAttributeRenameRelationshipManyToMany() + { + $databaseId = 'database1'; + $table1Id = 'collection1'; + $table2Id = 'collection2'; + + $this->createRelationshipCollections(); + + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedTableId' => $table2Id, + 'type' => 'manyToOne', + 'twoWay' => true, + 'onDelete' => 'cascade', + 'key' => 'level2', + 'twoWayKey' => 'level1' + ]); + + \sleep(3); + + $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $table1RelationAttribute = $table1Attributes['body']['columns'][0]; + + $this->assertEquals($relation['body']['side'], $table1RelationAttribute['side']); + $this->assertEquals($relation['body']['twoWayKey'], $table1RelationAttribute['twoWayKey']); + $this->assertEquals($relation['body']['relatedTable'], $table1RelationAttribute['relatedTable']); + + // Create a document for checking later + $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'unique()', + 'data' => [ + 'level2' => [ + '$id' => 'unique()', + '$permissions' => ["read(\"any\")"] + ], + ], + "permissions" => ["read(\"any\")"] + ]); + + $this->assertEquals(201, $originalDocument['headers']['status-code']); + + // Rename the attribute + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/level2' . '/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'newKey' => 'new_level_2' + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + // Check the document's key has been renamed + $newDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows/' . $originalDocument['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertArrayHasKey('new_level_2', $newDocument['body']); + $this->assertNotEmpty($newDocument['body']['new_level_2']); + $this->assertArrayNotHasKey('level2', $newDocument['body']); + + // Check level2 document has been renamed + $level2Document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id . '/rows/' . $newDocument['body']['new_level_2']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertArrayHasKey('level1', $level2Document['body']); + $this->assertNotEmpty($level2Document['body']['level1']); + + // Check if attribute was renamed on the parent's side + $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $this->assertEquals(200, $table1Attributes['headers']['status-code']); + $this->assertEquals(1, count($table1Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $table1Attributes['body']['columns'][0]['key']); + + // Check if attribute was renamed on the child's side + $table2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + + $this->assertEquals(200, $table2Attributes['headers']['status-code']); + $this->assertEquals(1, count($table2Attributes['body']['columns'])); + $this->assertEquals('new_level_2', $table2Attributes['body']['columns'][0]['twoWayKey']); + + $this->cleanupRelationshipCollection(); + } +} diff --git a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsGuestTest.php new file mode 100644 index 0000000000..fa04ba04aa --- /dev/null +++ b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsGuestTest.php @@ -0,0 +1,278 @@ +client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'InvalidDocumentDatabase', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('InvalidDocumentDatabase', $database['body']['name']); + + $databaseId = $database['body']['$id']; + $publicMovies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', $this->getServerHeader(), [ + 'tableId' => ID::unique(), + 'name' => 'Movies', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + $privateMovies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', $this->getServerHeader(), [ + 'tableId' => ID::unique(), + 'name' => 'Movies', + 'permissions' => [], + 'documentSecurity' => true, + ]); + + $publicCollection = ['id' => $publicMovies['body']['$id']]; + $privateCollection = ['id' => $privateMovies['body']['$id']]; + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $publicCollection['id'] . '/columns/string', $this->getServerHeader(), [ + 'key' => 'title', + 'size' => 256, + 'required' => true, + ]); + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $privateCollection['id'] . '/columns/string', $this->getServerHeader(), [ + 'key' => 'title', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + return [ + 'databaseId' => $databaseId, + 'publicCollectionId' => $publicCollection['id'], + 'privateCollectionId' => $privateCollection['id'], + ]; + } + + public function permissionsProvider(): array + { + return [ + [[Permission::read(Role::any())]], + [[Permission::read(Role::users())]], + [[Permission::update(Role::any()), Permission::delete(Role::any())]], + [[Permission::read(Role::any()), Permission::update(Role::any()), Permission::delete(Role::any())]], + [[Permission::read(Role::users()), Permission::update(Role::users()), Permission::delete(Role::users())]], + [[Permission::read(Role::any()), Permission::update(Role::users()), Permission::delete(Role::users())]], + ]; + } + + /** + * @dataProvider permissionsProvider + */ + public function testReadDocuments($permissions) + { + $data = $this->createCollection(); + $publicCollectionId = $data['publicCollectionId']; + $privateCollectionId = $data['privateCollectionId']; + $databaseId = $data['databaseId']; + + $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $publicCollectionId . '/rows', $this->getServerHeader(), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Lorem', + ], + 'permissions' => $permissions, + ]); + $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $privateCollectionId . '/rows', $this->getServerHeader(), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Lorem', + ], + 'permissions' => $permissions, + ]); + + $this->assertEquals(201, $publicResponse['headers']['status-code']); + $this->assertEquals(201, $privateResponse['headers']['status-code']); + + $roles = Authorization::getRoles(); + Authorization::cleanRoles(); + + $publicDocuments = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $publicCollectionId . '/rows', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]); + $privateDocuments = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $privateCollectionId . '/rows', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]); + + $this->assertEquals(1, $publicDocuments['body']['total']); + $this->assertEquals($permissions, $publicDocuments['body']['rows'][0]['$permissions']); + + if (\in_array(Permission::read(Role::any()), $permissions)) { + $this->assertEquals(1, $privateDocuments['body']['total']); + $this->assertEquals($permissions, $privateDocuments['body']['rows'][0]['$permissions']); + } else { + $this->assertEquals(0, $privateDocuments['body']['total']); + } + + foreach ($roles as $role) { + Authorization::setRole($role); + } + } + + public function testWriteDocument() + { + $data = $this->createCollection(); + $publicCollectionId = $data['publicCollectionId']; + $privateCollectionId = $data['privateCollectionId']; + $databaseId = $data['databaseId']; + + $roles = Authorization::getRoles(); + Authorization::cleanRoles(); + + $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $publicCollectionId . '/rows', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Lorem', + ] + ]); + + $publicDocumentId = $publicResponse['body']['$id']; + $this->assertEquals(201, $publicResponse['headers']['status-code']); + + $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $privateCollectionId . '/rows', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Lorem', + ], + ]); + + $this->assertEquals(401, $privateResponse['headers']['status-code']); + + // Create a document in private collection with API key so we can test that update and delete are also not allowed + $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $privateCollectionId . '/rows', $this->getServerHeader(), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Lorem', + ], + ]); + + $this->assertEquals(201, $privateResponse['headers']['status-code']); + $privateDocumentId = $privateResponse['body']['$id']; + + $publicDocument = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $publicCollectionId . '/rows/' . $publicDocumentId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'data' => [ + 'title' => 'Thor: Ragnarok', + ], + ]); + + $this->assertEquals(200, $publicDocument['headers']['status-code']); + $this->assertEquals('Thor: Ragnarok', $publicDocument['body']['title']); + + $privateDocument = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $privateCollectionId . '/rows/' . $privateDocumentId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'data' => [ + 'title' => 'Thor: Ragnarok', + ], + ]); + + $this->assertEquals(401, $privateDocument['headers']['status-code']); + + $publicDocument = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $publicCollectionId . '/rows/' . $publicDocumentId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]); + + $this->assertEquals(204, $publicDocument['headers']['status-code']); + + $privateDocument = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $privateCollectionId . '/rows/' . $privateDocumentId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]); + + $this->assertEquals(401, $privateDocument['headers']['status-code']); + + foreach ($roles as $role) { + Authorization::setRole($role); + } + } + + public function testWriteDocumentWithPermissions() + { + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'GuestPermissionsWrite', + ]); + $this->assertEquals(201, $database['headers']['status-code']); + $this->assertEquals('GuestPermissionsWrite', $database['body']['name']); + + $databaseId = $database['body']['$id']; + $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', $this->getServerHeader(), [ + 'tableId' => ID::unique(), + 'name' => 'Movies', + 'permissions' => [ + Permission::create(Role::any()), + ], + 'documentSecurity' => true + ]); + + $moviesId = $movies['body']['$id']; + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $moviesId . '/columns/string', $this->getServerHeader(), [ + 'key' => 'title', + 'size' => 256, + 'required' => true, + ]); + + sleep(1); + + $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $moviesId . '/rows', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Thor: Ragnarok', + ], + 'permissions' => [ + Permission::read(Role::any()), + ] + ]); + + $this->assertEquals(201, $row['headers']['status-code']); + $this->assertEquals('Thor: Ragnarok', $row['body']['title']); + } +} diff --git a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php new file mode 100644 index 0000000000..8da1d9e1ed --- /dev/null +++ b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php @@ -0,0 +1,271 @@ + $this->createUser('user1', 'lorem@ipsum.com'), + 'user2' => $this->createUser('user2', 'dolor@ipsum.com'), + ]; + } + + public function permissionsProvider(): array + { + return [ + [ + 'permissions' => [Permission::read(Role::any())], + 'any' => 1, + 'users' => 1, + 'doconly' => 1, + ], + [ + 'permissions' => [Permission::read(Role::users())], + 'any' => 2, + 'users' => 2, + 'doconly' => 2, + ], + [ + 'permissions' => [Permission::read(Role::user(ID::custom('random')))], + 'any' => 3, + 'users' => 3, + 'doconly' => 2, + ], + [ + 'permissions' => [Permission::read(Role::user(ID::custom('lorem'))), Permission::update(Role::user('lorem')), Permission::delete(Role::user('lorem'))], + 'any' => 4, + 'users' => 4, + 'doconly' => 2, + ], + [ + 'permissions' => [Permission::read(Role::user(ID::custom('dolor'))), Permission::update(Role::user('dolor')), Permission::delete(Role::user('dolor'))], + 'any' => 5, + 'users' => 5, + 'doconly' => 2, + ], + [ + 'permissions' => [Permission::read(Role::user(ID::custom('dolor'))), Permission::read(Role::user('lorem')), Permission::update(Role::user('dolor')), Permission::delete(Role::user('dolor'))], + 'any' => 6, + 'users' => 6, + 'doconly' => 2, + ], + [ + 'permissions' => [Permission::update(Role::any()), Permission::delete(Role::any())], + 'any' => 7, + 'users' => 7, + 'doconly' => 2, + ], + [ + 'permissions' => [Permission::read(Role::any()), Permission::update(Role::any()), Permission::delete(Role::any())], + 'any' => 8, + 'users' => 8, + 'doconly' => 3, + ], + [ + 'permissions' => [Permission::read(Role::any()), Permission::update(Role::users()), Permission::delete(Role::users())], + 'any' => 9, + 'users' => 9, + 'doconly' => 4, + ], + [ + 'permissions' => [Permission::read(Role::user(ID::custom('user1')))], + 'any' => 10, + 'users' => 10, + 'doconly' => 5, + ], + [ + 'permissions' => [Permission::read(Role::user(ID::custom('user1'))), Permission::read(Role::user(ID::custom('user1')))], + 'any' => 11, + 'users' => 11, + 'doconly' => 6, + ], + [ + 'permissions' => [Permission::read(Role::users()), Permission::update(Role::users()), Permission::delete(Role::users())], + 'any' => 12, + 'users' => 12, + 'doconly' => 7, + ], + ]; + } + + /** + * Setup database + * + * Data providers lose object state so explicitly pass [$users, $tables] to each iteration + * + * @return array + * @throws \Exception + */ + public function testSetupDatabase(): array + { + $this->createUsers(); + + $db = $this->client->call(Client::METHOD_POST, '/databases', $this->getServerHeader(), [ + 'databaseId' => ID::unique(), + 'name' => 'Test Database', + ]); + $this->assertEquals(201, $db['headers']['status-code']); + + $databaseId = $db['body']['$id']; + + $public = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', $this->getServerHeader(), [ + 'tableId' => ID::unique(), + 'name' => 'Movies', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'documentSecurity' => true, + ]); + $this->assertEquals(201, $public['headers']['status-code']); + $this->collections = ['public' => $public['body']['$id']]; + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $this->collections['public'] . '/columns/string', $this->getServerHeader(), [ + 'key' => 'title', + 'size' => 256, + 'required' => true, + ]); + $this->assertEquals(202, $response['headers']['status-code']); + + $private = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', $this->getServerHeader(), [ + 'tableId' => ID::unique(), + 'name' => 'Private Movies', + 'permissions' => [ + Permission::read(Role::users()), + Permission::create(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + 'documentSecurity' => true, + ]); + $this->assertEquals(201, $private['headers']['status-code']); + $this->collections['private'] = $private['body']['$id']; + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $this->collections['private'] . '/columns/string', $this->getServerHeader(), [ + 'key' => 'title', + 'size' => 256, + 'required' => true, + ]); + $this->assertEquals(202, $response['headers']['status-code']); + + $doconly = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', $this->getServerHeader(), [ + 'tableId' => ID::unique(), + 'name' => 'Document Only Movies', + 'permissions' => [], + 'documentSecurity' => true, + ]); + $this->assertEquals(201, $private['headers']['status-code']); + $this->collections['doconly'] = $doconly['body']['$id']; + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $this->collections['doconly'] . '/columns/string', $this->getServerHeader(), [ + 'key' => 'title', + 'size' => 256, + 'required' => true, + ]); + $this->assertEquals(202, $response['headers']['status-code']); + + sleep(2); + + return [ + 'users' => $this->users, + 'tables' => $this->collections, + 'databaseId' => $databaseId + ]; + } + + /** + * Data provider params are passed before test dependencies + * @dataProvider permissionsProvider + * @depends testSetupDatabase + */ + public function testReadDocuments($permissions, $anyCount, $usersCount, $docOnlyCount, $data) + { + $users = $data['users']; + $tables = $data['tables']; + $databaseId = $data['databaseId']; + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tables['public'] . '/rows', $this->getServerHeader(), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Lorem', + ], + 'permissions' => $permissions + ]); + $this->assertEquals(201, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tables['private'] . '/rows', $this->getServerHeader(), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Lorem', + ], + 'permissions' => $permissions + ]); + $this->assertEquals(201, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tables['doconly'] . '/rows', $this->getServerHeader(), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Lorem', + ], + 'permissions' => $permissions + ]); + $this->assertEquals(201, $response['headers']['status-code']); + + /** + * Check "any" permission collection + */ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tables['public'] . '/rows', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users['user1']['session'], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals($anyCount, $rows['body']['total']); + + /** + * Check "users" permission collection + */ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tables['private'] . '/rows', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users['user1']['session'], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals($usersCount, $rows['body']['total']); + + /** + * Check "user:user1" document only permission collection + */ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tables['doconly'] . '/rows', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users['user1']['session'], + ]); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals($docOnlyCount, $rows['body']['total']); + } +} diff --git a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsScope.php b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsScope.php new file mode 100644 index 0000000000..a2bc227c8f --- /dev/null +++ b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsScope.php @@ -0,0 +1,87 @@ +client->call(Client::METHOD_POST, '/account', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-dev-key' => $this->getProject()['devKey'] ?? '', + ], [ + 'userId' => $id, + 'email' => $email, + 'password' => $password + ]); + + $this->assertEquals(201, $user['headers']['status-code']); + + $session = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'email' => $email, + 'password' => $password, + ]); + + $session = $session['cookies']['a_session_' . $this->getProject()['$id']]; + + $user = [ + '$id' => $user['body']['$id'], + 'email' => $user['body']['email'], + 'session' => $session, + ]; + $this->users[$id] = $user; + + return $user; + } + + public function getCreatedUser(string $id): array + { + return $this->users[$id] ?? []; + } + + public function createTeam(string $id, string $name): array + { + $team = $this->client->call(Client::METHOD_POST, '/teams', $this->getServerHeader(), [ + 'teamId' => $id, + 'name' => $name + ]); + $this->teams[$id] = $team['body']; + + return $team['body']; + } + + public function addToTeam(string $user, string $team, array $roles = []): array + { + $membership = $this->client->call(Client::METHOD_POST, '/teams/' . $team . '/memberships', $this->getServerHeader(), [ + 'teamId' => $team, + 'email' => $this->getCreatedUser($user)['email'], + 'roles' => $roles, + 'url' => 'http://localhost:5000/join-us#title' + ]); + + return [ + 'user' => $membership['body']['userId'], + 'membership' => $membership['body']['$id'] + ]; + } + + public function getServerHeader(): array + { + return [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]; + } +} diff --git a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsTeamTest.php b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsTeamTest.php new file mode 100644 index 0000000000..c62583f76c --- /dev/null +++ b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsTeamTest.php @@ -0,0 +1,208 @@ + $this->createTeam('team1', 'Team 1'), + 'team2' => $this->createTeam('team2', 'Team 2'), + ]; + } + + public function createUsers(): array + { + return [ + 'user1' => $this->createUser('user1', 'lorem@ipsum.com'), + 'user2' => $this->createUser('user2', 'dolor@ipsum.com'), + 'user3' => $this->createUser('user3', 'sit@ipsum.com'), + ]; + } + + public function createCollections($teams) + { + $db = $this->client->call(Client::METHOD_POST, '/databases', $this->getServerHeader(), [ + 'databaseId' => $this->databaseId, + 'name' => 'Test Database', + ]); + $this->assertEquals(201, $db['headers']['status-code']); + + $table1 = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables', $this->getServerHeader(), [ + 'tableId' => ID::custom('collection1'), + 'name' => 'Collection 1', + 'permissions' => [ + Permission::read(Role::team($teams['team1']['$id'])), + Permission::create(Role::team($teams['team1']['$id'], 'admin')), + Permission::update(Role::team($teams['team1']['$id'], 'admin')), + Permission::delete(Role::team($teams['team1']['$id'], 'admin')), + ], + ]); + + $this->collections['collection1'] = $table1['body']['$id']; + + $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $this->collections['collection1'] . '/columns/string', $this->getServerHeader(), [ + 'key' => 'title', + 'size' => 256, + 'required' => true, + ]); + + $table2 = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables', $this->getServerHeader(), [ + 'tableId' => ID::custom('collection2'), + 'name' => 'Collection 2', + 'permissions' => [ + Permission::read(Role::team($teams['team2']['$id'])), + Permission::create(Role::team($teams['team2']['$id'], 'owner')), + Permission::update(Role::team($teams['team2']['$id'], 'owner')), + Permission::delete(Role::team($teams['team2']['$id'], 'owner')), + ] + ]); + + $this->collections['collection2'] = $table2['body']['$id']; + + $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $this->collections['collection2'] . '/columns/string', $this->getServerHeader(), [ + 'key' => 'title', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + return $this->collections; + } + + /* + * $success = can $user read from $table + * [$user, $table, $success] + */ + public function readDocumentsProvider(): array + { + return [ + ['user1', 'collection1', true], + ['user2', 'collection1', false], + ['user3', 'collection1', true], + ['user1', 'collection2', false], + ['user2', 'collection2', true], + ['user3', 'collection2', true], + ]; + } + + /* + * $success = can $user write to $table + * [$user, $table, $success] + */ + public function writeDocumentsProvider(): array + { + return [ + ['user1', 'collection1', true], + ['user2', 'collection1', false], + ['user3', 'collection1', false], + ['user1', 'collection2', false], + ['user2', 'collection2', true], + ['user3', 'collection2', false], + ]; + } + + /** + * Setup database + * + * Data providers lose object state + * so explicitly pass $users to each iteration + * @return array $users + */ + public function testSetupDatabase(): array + { + $this->createUsers(); + $this->createTeams(); + + $this->addToTeam('user1', 'team1', ['admin']); + $this->addToTeam('user2', 'team2', ['owner']); + + // user3 in both teams but with no roles + $this->addToTeam('user3', 'team1'); + $this->addToTeam('user3', 'team2'); + + $this->createCollections($this->teams); + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $this->collections['collection1'] . '/rows', $this->getServerHeader(), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Lorem', + ], + ]); + $this->assertEquals(201, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $this->collections['collection2'] . '/rows', $this->getServerHeader(), [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Ipsum', + ], + ]); + $this->assertEquals(201, $response['headers']['status-code']); + + return $this->users; + } + + /** + * Data provider params are passed before test dependencies + * @depends testSetupDatabase + * @dataProvider readDocumentsProvider + */ + public function testReadDocuments($user, $table, $success, $users) + { + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $this->databaseId . '/tables/' . $table . '/rows', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users[$user]['session'], + ]); + + if ($success) { + $this->assertCount(1, $rows['body']['rows']); + } else { + $this->assertEquals(401, $rows['headers']['status-code']); + } + } + + /** + * @depends testSetupDatabase + * @dataProvider writeDocumentsProvider + */ + public function testWriteDocuments($user, $table, $success, $users) + { + $rows = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $table . '/rows', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $users[$user]['session'], + ], [ + 'rowId' => ID::unique(), + 'data' => [ + 'title' => 'Ipsum', + ], + ]); + + if ($success) { + $this->assertEquals(201, $rows['headers']['status-code']); + } else { + // 401 if user is a part of team, 404 otherwise + $this->assertContains($rows['headers']['status-code'], [401, 404]); + } + } +} From 241779e0463fea3b5de80debb48ed3b79fb24c8c Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 17:34:41 +0530 Subject: [PATCH 108/343] add: table api tests to abuse. --- tests/e2e/General/AbuseTest.php | 136 ++++++++++++++++++++++++++++---- 1 file changed, 119 insertions(+), 17 deletions(-) diff --git a/tests/e2e/General/AbuseTest.php b/tests/e2e/General/AbuseTest.php index 2ef351f43e..217f9f93ed 100644 --- a/tests/e2e/General/AbuseTest.php +++ b/tests/e2e/General/AbuseTest.php @@ -26,17 +26,115 @@ class AbuseTest extends Scope } } - public function testAbuseCreateDocument() + public function testAbuseCreateDocumentCollectionsAPI() { - $data = $this->createCollection(); + $data = $this->createCollectionOrTable(); $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $max = 120; for ($i = 0; $i <= $max + 1; $i++) { $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'documentId' => ID::unique(), + 'data' => [ + 'title' => 'The Hulk ' . $i, + ], + ]); + + if ($i < $max) { + $this->assertEquals(201, $response['headers']['status-code']); + } else { + $this->assertEquals(429, $response['headers']['status-code']); + } + } + } + + public function testAbuseUpdateDocumentCollectionsAPI() + { + $data = $this->createCollectionOrTable(); + $databaseId = $data['databaseId']; + $collectionId = $data['collectionId']; + $max = 120; + + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'documentId' => ID::unique(), + 'data' => [ + 'title' => 'The Hulk', + ], + ]); + + $documentId = $document['body']['$id']; + + for ($i = 0; $i <= $max + 1; $i++) { + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'data' => [ + 'title' => 'The Hulk ' . $i, + ], + ]); + + if ($i < $max) { + $this->assertEquals(200, $response['headers']['status-code']); + } else { + $this->assertEquals(429, $response['headers']['status-code']); + } + } + } + + public function testAbuseDeleteDocumentCollectionsAPI() + { + $data = $this->createCollectionOrTable(); + $databaseId = $data['databaseId']; + $collectionId = $data['collectionId']; + $max = 60; + + for ($i = 0; $i <= $max + 1; $i++) { + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'documentId' => ID::unique(), + 'data' => [ + 'title' => 'The Hulk', + ], + ]); + + $documentId = $document['body']['$id']; + + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]); + + if ($i < $max) { + $this->assertEquals(204, $response['headers']['status-code']); + } else { + $this->assertEquals(429, $response['headers']['status-code']); + } + } + } + + public function testAbuseCreateDocumentTablesAPI() + { + $data = $this->createCollectionOrTable(false); + $databaseId = $data['databaseId']; + $collectionId = $data['collectionId']; + $max = 120; + + for ($i = 0; $i <= $max + 1; $i++) { + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $collectionId . '/rows', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], [ 'rowId' => ID::unique(), 'data' => [ @@ -52,14 +150,14 @@ class AbuseTest extends Scope } } - public function testAbuseUpdateDocument() + public function testAbuseUpdateDocumentTablesAPI() { - $data = $this->createCollection(); + $data = $this->createCollectionOrTable(false); $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $max = 120; - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $collectionId . '/rows', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -90,15 +188,15 @@ class AbuseTest extends Scope } } - public function testAbuseDeleteDocument() + public function testAbuseDeleteDocumentTablesAPI() { - $data = $this->createCollection(); + $data = $this->createCollectionOrTable(false); $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $max = 60; for ($i = 0; $i <= $max + 1; $i++) { - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [ + $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $collectionId . '/rows', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -111,7 +209,7 @@ class AbuseTest extends Scope $documentId = $document['body']['$id']; - $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $collectionId . '/rows/' . $documentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -211,7 +309,7 @@ class AbuseTest extends Scope } } - private function createCollection(): array + private function createCollectionOrTable(bool $isCollection = true): array { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -227,12 +325,16 @@ class AbuseTest extends Scope $databaseId = $database['body']['$id']; - $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', [ + $endpoint = $isCollection ? 'collections' : 'tables'; + $idParam = $isCollection ? 'collectionId' : 'tableId'; + $attributePath = $isCollection ? 'attributes' : 'columns'; + + $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . "/$endpoint", [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ - 'tableId' => ID::unique(), + $idParam => ID::unique(), 'name' => 'Movies', 'permissions' => [ Permission::read(Role::any()), @@ -244,7 +346,7 @@ class AbuseTest extends Scope $collectionId = $movies['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', [ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . "/$endpoint/" . $collectionId . "/$attributePath/string", [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -258,7 +360,7 @@ class AbuseTest extends Scope return [ 'databaseId' => $databaseId, - 'tableId' => $collectionId, + 'collectionId' => $collectionId, ]; } From d5e94a57be176ffa9dfe3e7fe551c2c9f9c90797 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 17:38:02 +0530 Subject: [PATCH 109/343] revert: graphql tests for collections api. --- tests/e2e/Services/GraphQL/AbuseTest.php | 20 +- tests/e2e/Services/GraphQL/AuthTest.php | 59 ++- tests/e2e/Services/GraphQL/Base.php | 348 +++++++++--------- .../Services/GraphQL/DatabaseClientTest.php | 68 ++-- .../Services/GraphQL/DatabaseServerTest.php | 287 +++++++-------- 5 files changed, 390 insertions(+), 392 deletions(-) diff --git a/tests/e2e/Services/GraphQL/AbuseTest.php b/tests/e2e/Services/GraphQL/AbuseTest.php index 10b8421b04..ea97492c2b 100644 --- a/tests/e2e/Services/GraphQL/AbuseTest.php +++ b/tests/e2e/Services/GraphQL/AbuseTest.php @@ -30,9 +30,9 @@ class AbuseTest extends Scope { $data = $this->createCollection(); $databaseId = $data['databaseId']; - $collectionId = $data['tableId']; + $collectionId = $data['collectionId']; $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_ROW); + $query = $this->getQuery(self::$CREATE_DOCUMENT); $max = 120; for ($i = 0; $i <= $max + 1; $i++) { @@ -40,8 +40,8 @@ class AbuseTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $databaseId, - 'tableId' => $collectionId, - 'rowId' => ID::unique(), + 'collectionId' => $collectionId, + 'documentId' => ID::unique(), 'data' => [ 'name' => 'John Doe', ], @@ -73,7 +73,7 @@ class AbuseTest extends Scope 'password' => 'password', 'databaseId' => 'database', 'databaseName' => 'database', - 'tableId' => 'collection', + 'collectionId' => 'collection', 'collectionName' => 'collection', 'collectionPermissions' => [ Permission::read(Role::users()), @@ -133,12 +133,12 @@ class AbuseTest extends Scope $databaseId = $response['body']['data']['databasesCreate']['_id']; - $query = $this->getQuery(self::$CREATE_TABLE); + $query = $this->getQuery(self::$CREATE_COLLECTION); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $databaseId, - 'tableId' => 'actors', + 'collectionId' => 'actors', 'name' => 'Actors', 'documentSecurity' => false, 'permissions' => [ @@ -156,12 +156,12 @@ class AbuseTest extends Scope $collectionId = $response['body']['data']['databasesCreateCollection']['_id']; - $query = $this->getQuery(self::$CREATE_STRING_COLUMN); + $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $databaseId, - 'tableId' => $collectionId, + 'collectionId' => $collectionId, 'key' => 'name', 'size' => 256, 'required' => true, @@ -178,7 +178,7 @@ class AbuseTest extends Scope return [ 'databaseId' => $databaseId, - 'tableId' => $collectionId, + 'collectionId' => $collectionId, ]; } } diff --git a/tests/e2e/Services/GraphQL/AuthTest.php b/tests/e2e/Services/GraphQL/AuthTest.php index 48a2f475e6..ecce29f2b3 100644 --- a/tests/e2e/Services/GraphQL/AuthTest.php +++ b/tests/e2e/Services/GraphQL/AuthTest.php @@ -23,7 +23,7 @@ class AuthTest extends Scope private string $token2; private array $database; - private array $table; + private array $collection; public function setUp(): void { @@ -101,13 +101,13 @@ class AuthTest extends Scope ], $gqlPayload); // Create collection - $query = $this->getQuery(self::$CREATE_TABLE); + $query = $this->getQuery(self::$CREATE_COLLECTION); $userId = $this->account1['body']['data']['accountCreate']['_id']; $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'tableId' => ID::unique(), + 'collectionId' => ID::unique(), 'name' => 'Actors', 'documentSecurity' => true, 'permissions' => [ @@ -115,19 +115,19 @@ class AuthTest extends Scope ] ] ]; - $this->table = $this->client->call(Client::METHOD_POST, '/graphql', [ + $this->collection = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $this->getProject()['apiKey'], ], $gqlPayload); // Create string attribute - $query = $this->getQuery(self::$CREATE_STRING_COLUMN); + $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], 'key' => 'name', 'size' => 256, 'required' => true, @@ -147,14 +147,14 @@ class AuthTest extends Scope $projectId = $this->getProject()['$id']; // Create document as account 1 - $query = $this->getQuery(self::$CREATE_ROW); + $query = $this->getQuery(self::$CREATE_DOCUMENT); $userId = $this->account1['body']['data']['accountCreate']['_id']; $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], - 'rowId' => ID::unique(), + 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], + 'documentId' => ID::unique(), 'data' => [ 'name' => 'John Doe', ], @@ -165,41 +165,40 @@ class AuthTest extends Scope ] ] ]; - - $row = $this->client->call(Client::METHOD_POST, '/graphql', [ + $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); // Try to read as account 1 - $query = $this->getQuery(self::$GET_ROW); + $query = $this->getQuery(self::$GET_DOCUMENT); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], - 'rowId' => $row['body']['data']['databasesCreateRow']['_id'], + 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], + 'documentId' => $document['body']['data']['databasesCreateDocument']['_id'], ] ]; - $row = $this->client->call(Client::METHOD_POST, '/graphql', [ + $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); - $this->assertIsArray($row['body']['data']['databasesGetRow']); - $this->assertArrayNotHasKey('errors', $row['body']); + $this->assertIsArray($document['body']['data']['databasesGetDocument']); + $this->assertArrayNotHasKey('errors', $document['body']); // Try to read as account 2 - $row = $this->client->call(Client::METHOD_POST, '/graphql', [ + $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'cookie' => 'a_session_' . $projectId . '=' . $this->token2, ], $gqlPayload); - $this->assertArrayHasKey('errors', $row['body']); - $this->assertEquals('Document with the requested ID could not be found.', $row['body']['errors'][0]['message']); + $this->assertArrayHasKey('errors', $document['body']); + $this->assertEquals('Document with the requested ID could not be found.', $document['body']['errors'][0]['message']); } public function testValidAuth() @@ -207,14 +206,14 @@ class AuthTest extends Scope $projectId = $this->getProject()['$id']; // Create document as account 1 - $query = $this->getQuery(self::$CREATE_ROW); + $query = $this->getQuery(self::$CREATE_DOCUMENT); $userId = $this->account1['body']['data']['accountCreate']['_id']; $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], - 'rowId' => ID::unique(), + 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], + 'documentId' => ID::unique(), 'data' => [ 'name' => 'John Doe', ], @@ -225,29 +224,29 @@ class AuthTest extends Scope ], ] ]; - $row = $this->client->call(Client::METHOD_POST, '/graphql', [ + $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); // Try to delete as account 1 - $query = $this->getQuery(self::$DELETE_ROW); + $query = $this->getQuery(self::$DELETE_DOCUMENT); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], - 'rowId' => $row['body']['data']['databasesCreateRow']['_id'], + 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], + 'documentId' => $document['body']['data']['databasesCreateDocument']['_id'], ] ]; - $row = $this->client->call(Client::METHOD_POST, '/graphql', [ + $document = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); - $this->assertIsNotArray($row['body']); - $this->assertEquals(204, $row['headers']['status-code']); + $this->assertIsNotArray($document['body']); + $this->assertEquals(204, $document['headers']['status-code']); } } diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 22112d2e12..121d40156e 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -13,49 +13,49 @@ trait Base public static string $GET_DATABASE = 'get_database'; public static string $UPDATE_DATABASE = 'update_database'; public static string $DELETE_DATABASE = 'delete_database'; - // Tables - public static string $CREATE_TABLE = 'create_table'; - public static string $GET_TABLE = 'get_table'; - public static string $GET_TABLES = 'list_tables'; - public static string $UPDATE_TABLE = 'update_table'; - public static string $DELETE_TABLE = 'delete_table'; - // Columns - public static string $CREATE_STRING_COLUMN = 'create_string_column'; - public static string $CREATE_INTEGER_COLUMN = 'create_integer_column'; - public static string $CREATE_FLOAT_COLUMN = 'create_float_column'; - public static string $CREATE_BOOLEAN_COLUMN = 'create_boolean_column'; - public static string $CREATE_URL_COLUMN = 'create_url_column'; - public static string $CREATE_EMAIL_COLUMN = 'create_email_column'; - public static string $CREATE_IP_COLUMN = 'create_ip_column'; - public static string $CREATE_ENUM_COLUMN = 'create_enum_column'; - public static string $CREATE_DATETIME_COLUMN = 'create_datetime_column'; + // Collections + public static string $CREATE_COLLECTION = 'create_collection'; + public static string $GET_COLLECTION = 'get_collection'; + public static string $GET_COLLECTIONS = 'list_collections'; + public static string $UPDATE_COLLECTION = 'update_collection'; + public static string $DELETE_COLLECTION = 'delete_collection'; + // Attributes + public static string $CREATE_STRING_ATTRIBUTE = 'create_string_attribute'; + public static string $CREATE_INTEGER_ATTRIBUTE = 'create_integer_attribute'; + public static string $CREATE_FLOAT_ATTRIBUTE = 'create_float_attribute'; + public static string $CREATE_BOOLEAN_ATTRIBUTE = 'create_boolean_attribute'; + public static string $CREATE_URL_ATTRIBUTE = 'create_url_attribute'; + public static string $CREATE_EMAIL_ATTRIBUTE = 'create_email_attribute'; + public static string $CREATE_IP_ATTRIBUTE = 'create_ip_attribute'; + public static string $CREATE_ENUM_ATTRIBUTE = 'create_enum_attribute'; + public static string $CREATE_DATETIME_ATTRIBUTE = 'create_datetime_attribute'; - public static string $CREATE_RELATIONSHIP_COLUMN = 'create_relationship_column'; - public static string $UPDATE_STRING_COLUMN = 'update_string_column'; - public static string $UPDATE_INTEGER_COLUMN = 'update_integer_column'; - public static string $UPDATE_FLOAT_COLUMN = 'update_float_column'; - public static string $UPDATE_BOOLEAN_COLUMN = 'update_boolean_column'; - public static string $UPDATE_URL_COLUMN = 'update_url_column'; - public static string $UPDATE_EMAIL_COLUMN = 'update_email_column'; - public static string $UPDATE_IP_COLUMN = 'update_ip_column'; - public static string $UPDATE_ENUM_COLUMN = 'update_enum_column'; - public static string $UPDATE_DATETIME_COLUMN = 'update_datetime_column'; + public static string $CREATE_RELATIONSHIP_ATTRIBUTE = 'create_relationship_attribute'; + public static string $UPDATE_STRING_ATTRIBUTE = 'update_string_attribute'; + public static string $UPDATE_INTEGER_ATTRIBUTE = 'update_integer_attribute'; + public static string $UPDATE_FLOAT_ATTRIBUTE = 'update_float_attribute'; + public static string $UPDATE_BOOLEAN_ATTRIBUTE = 'update_boolean_attribute'; + public static string $UPDATE_URL_ATTRIBUTE = 'update_url_attribute'; + public static string $UPDATE_EMAIL_ATTRIBUTE = 'update_email_attribute'; + public static string $UPDATE_IP_ATTRIBUTE = 'update_ip_attribute'; + public static string $UPDATE_ENUM_ATTRIBUTE = 'update_enum_attribute'; + public static string $UPDATE_DATETIME_ATTRIBUTE = 'update_datetime_attribute'; - public static string $UPDATE_RELATIONSHIP_COLUMN = 'update_relationship_column'; - public static string $GET_COLUMNS = 'get_columns'; - public static string $GET_COLUMN = 'get_column'; - public static string $DELETE_COLUMN = 'delete_column'; + public static string $UPDATE_RELATIONSHIP_ATTRIBUTE = 'update_relationship_attribute'; + public static string $GET_ATTRIBUTES = 'get_attributes'; + public static string $GET_ATTRIBUTE = 'get_attribute'; + public static string $DELETE_ATTRIBUTE = 'delete_attribute'; // Indexes public static string $CREATE_INDEX = 'create_index'; public static string $GET_INDEXES = 'get_indexes'; public static string $GET_INDEX = 'get_index'; public static string $DELETE_INDEX = 'delete_index'; // Documents - public static string $CREATE_ROW = 'create_row_rest'; - public static string $GET_ROWS = 'list_rows'; - public static string $GET_ROW = 'get_row'; - public static string $UPDATE_ROW = 'update_row'; - public static string $DELETE_ROW = 'delete_row'; + public static string $CREATE_DOCUMENT = 'create_document_rest'; + public static string $GET_DOCUMENTS = 'list_documents'; + public static string $GET_DOCUMENT = 'get_document'; + public static string $UPDATE_DOCUMENT = 'update_document'; + public static string $DELETE_DOCUMENT = 'delete_document'; // Custom Entities public static string $CREATE_CUSTOM_ENTITY = 'create_custom_entity'; @@ -258,9 +258,9 @@ trait Base public static string $COMPLEX_QUERY = 'complex_query'; // Fragments - public static string $FRAGMENT_COLUMNS = ' - fragment columnProperties on Columns { - ... on ColumnString { + public static string $FRAGMENT_ATTRIBUTES = ' + fragment attributeProperties on Attributes { + ... on AttributeString { key required array @@ -268,7 +268,7 @@ trait Base default size } - ... on ColumnInteger { + ... on AttributeInteger { key required array @@ -277,7 +277,7 @@ trait Base intMin: min intMax: max } - ... on ColumnFloat { + ... on AttributeFloat { key required array @@ -286,35 +286,35 @@ trait Base floatMin: min floatMax: max } - ... on ColumnBoolean { + ... on AttributeBoolean { key required array status boolDefault:default } - ... on ColumnUrl { + ... on AttributeUrl { key required array status default } - ... on ColumnEmail { + ... on AttributeEmail { key required array status default } - ... on ColumnIp { + ... on AttributeIp { key required array status default } - ... on ColumnEnum { + ... on AttributeEnum { key required array @@ -322,7 +322,7 @@ trait Base default elements } - ... on ColumnDatetime { + ... on AttributeDatetime { key required array @@ -393,20 +393,20 @@ trait Base status } }'; - case self::$GET_TABLE: - return 'query getTable($databaseId: String!, $tableId: String!) { - databasesGetTable(databaseId: $databaseId, tableId: $tableId) { + case self::$GET_COLLECTION: + return 'query getCollection($databaseId: String!, $collectionId: String!) { + databasesGetCollection(databaseId: $databaseId, collectionId: $collectionId) { _id _permissions documentSecurity name } }'; - case self::$GET_TABLES: - return 'query listTables($databaseId: String!) { - databasesListTables(databaseId: $databaseId) { + case self::$GET_COLLECTIONS: + return 'query listCollections($databaseId: String!) { + databasesListCollections(databaseId: $databaseId) { total - tables { + collections { _id _permissions documentSecurity @@ -414,42 +414,42 @@ trait Base } } }'; - case self::$CREATE_TABLE: - return 'mutation createTable($databaseId: String!, $tableId: String!, $name: String!, $documentSecurity: Boolean!, $permissions: [String!]!) { - databasesCreateTable(databaseId: $databaseId, tableId: $tableId, name: $name, documentSecurity: $documentSecurity, permissions: $permissions) { + case self::$CREATE_COLLECTION: + return 'mutation createCollection($databaseId: String!, $collectionId: String!, $name: String!, $documentSecurity: Boolean!, $permissions: [String!]!) { + databasesCreateCollection(databaseId: $databaseId, collectionId: $collectionId, name: $name, documentSecurity: $documentSecurity, permissions: $permissions) { _id _permissions documentSecurity name } }'; - case self::$UPDATE_TABLE: - return 'mutation updateTable($databaseId: String!, $tableId: String!, $name: String!, $documentSecurity: Boolean!, $permissions: [String!], $enabled: Boolean){ - databasesUpdateTable(databaseId: $databaseId, tableId: $tableId, name: $name, documentSecurity: $documentSecurity, permissions: $permissions, enabled: $enabled) { + case self::$UPDATE_COLLECTION: + return 'mutation updateCollection($databaseId: String!, $collectionId: String!, $name: String!, $documentSecurity: Boolean!, $permissions: [String!], $enabled: Boolean){ + databasesUpdateCollection(databaseId: $databaseId, collectionId: $collectionId, name: $name, documentSecurity: $documentSecurity, permissions: $permissions, enabled: $enabled) { _id _permissions documentSecurity name } }'; - case self::$DELETE_TABLE: - return 'mutation deleteTable($databaseId: String!, $tableId: String!){ - databasesDeleteTable(databaseId: $databaseId, tableId: $tableId) { + case self::$DELETE_COLLECTION: + return 'mutation deleteCollection($databaseId: String!, $collectionId: String!){ + databasesDeleteCollection(databaseId: $databaseId, collectionId: $collectionId) { status } }'; - case self::$CREATE_STRING_COLUMN: - return 'mutation createStringColumn($databaseId: String!, $tableId: String!, $key: String!, $size: Int!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateStringColumn(databaseId: $databaseId, tableId: $tableId, key: $key, size: $size, required: $required, default: $default, array: $array) { + case self::$CREATE_STRING_ATTRIBUTE: + return 'mutation createStringAttribute($databaseId: String!, $collectionId: String!, $key: String!, $size: Int!, $required: Boolean!, $default: String, $array: Boolean){ + databasesCreateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, size: $size, required: $required, default: $default, array: $array) { key required default array } }'; - case self::$CREATE_INTEGER_COLUMN: - return 'mutation createIntegerColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $min: Int, $max: Int, $default: Int, $array: Boolean){ - databasesCreateIntegerColumn(databaseId: $databaseId, tableId: $tableId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { + case self::$CREATE_INTEGER_ATTRIBUTE: + return 'mutation createIntegerAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Int, $max: Int, $default: Int, $array: Boolean){ + databasesCreateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { key required min @@ -458,9 +458,9 @@ trait Base array } }'; - case self::$CREATE_FLOAT_COLUMN: - return 'mutation createFloatColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $min: Float, $max: Float, $default: Float, $array: Boolean){ - databasesCreateFloatColumn(databaseId: $databaseId, tableId: $tableId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { + case self::$CREATE_FLOAT_ATTRIBUTE: + return 'mutation createFloatAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Float, $max: Float, $default: Float, $array: Boolean){ + databasesCreateFloatAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { key required min @@ -469,45 +469,45 @@ trait Base array } }'; - case self::$CREATE_BOOLEAN_COLUMN: - return 'mutation createBooleanColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: Boolean, $array: Boolean){ - databasesCreateBooleanColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { + case self::$CREATE_BOOLEAN_ATTRIBUTE: + return 'mutation createBooleanAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: Boolean, $array: Boolean){ + databasesCreateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default array } }'; - case self::$CREATE_URL_COLUMN: - return 'mutation createUrlColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateUrlColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { + case self::$CREATE_URL_ATTRIBUTE: + return 'mutation createUrlAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ + databasesCreateUrlAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default array } }'; - case self::$CREATE_EMAIL_COLUMN: - return 'mutation createEmailColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateEmailColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { + case self::$CREATE_EMAIL_ATTRIBUTE: + return 'mutation createEmailAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ + databasesCreateEmailAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default array } }'; - case self::$CREATE_IP_COLUMN: - return 'mutation createIpColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateIpColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { + case self::$CREATE_IP_ATTRIBUTE: + return 'mutation createIpAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ + databasesCreateIpAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default array } }'; - case self::$CREATE_ENUM_COLUMN: - return 'mutation createEnumColumn($databaseId: String!, $tableId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateEnumColumn(databaseId: $databaseId, tableId: $tableId, key: $key, elements: $elements, required: $required, default: $default, array: $array) { + case self::$CREATE_ENUM_ATTRIBUTE: + return 'mutation createEnumAttribute($databaseId: String!, $collectionId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String, $array: Boolean){ + databasesCreateEnumAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, elements: $elements, required: $required, default: $default, array: $array) { key elements required @@ -515,19 +515,19 @@ trait Base array } }'; - case self::$CREATE_DATETIME_COLUMN: - return 'mutation createDatetimeColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateDatetimeColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { + case self::$CREATE_DATETIME_ATTRIBUTE: + return 'mutation createDatetimeAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ + databasesCreateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default array } }'; - case self::$CREATE_RELATIONSHIP_COLUMN: - return 'mutation createRelationshipColumn($databaseId: String!, $tableId: String!, $relatedTableId: String!, $type: String!, $twoWay: Boolean, $key: String, $twoWayKey: String, $onDelete: String){ - databasesCreateRelationshipColumn(databaseId: $databaseId, tableId: $tableId, relatedTableId: $relatedTableId, type: $type, twoWay: $twoWay, key: $key, twoWayKey: $twoWayKey, onDelete: $onDelete) { - relatedTable + case self::$CREATE_RELATIONSHIP_ATTRIBUTE: + return 'mutation createRelationshipAttribute($databaseId: String!, $collectionId: String!, $relatedCollectionId: String!, $type: String!, $twoWay: Boolean, $key: String, $twoWayKey: String, $onDelete: String){ + databasesCreateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, relatedCollectionId: $relatedCollectionId, type: $type, twoWay: $twoWay, key: $key, twoWayKey: $twoWayKey, onDelete: $onDelete) { + relatedCollection relationType twoWay key @@ -535,78 +535,78 @@ trait Base onDelete } }'; - case self::$UPDATE_STRING_COLUMN: - return 'mutation updateStringColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateStringColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { + case self::$UPDATE_STRING_ATTRIBUTE: + return 'mutation updateStringAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ + databasesUpdateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; - case self::$UPDATE_INTEGER_COLUMN: - return 'mutation updateIntegerColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $min: Int!, $max: Int!, $default: Int){ - databasesUpdateIntegerColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, min: $min, max: $max, default: $default) { + case self::$UPDATE_INTEGER_ATTRIBUTE: + return 'mutation updateIntegerAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Int!, $max: Int!, $default: Int){ + databasesUpdateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, min: $min, max: $max, default: $default) { required min max default } }'; - case self::$UPDATE_FLOAT_COLUMN: - return 'mutation updateFloatColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $min: Float!, $max: Float!, $default: Float){ - databasesUpdateFloatColumn(databaseId: $databaseId, tableId: $tableId, key: $key, min: $min, max: $max, required: $required, default: $default) { + case self::$UPDATE_FLOAT_ATTRIBUTE: + return 'mutation updateFloatAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Float!, $max: Float!, $default: Float){ + databasesUpdateFloatAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default) { required min max default } }'; - case self::$UPDATE_BOOLEAN_COLUMN: - return 'mutation updateBooleanColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: Boolean){ - databasesUpdateBooleanColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { + case self::$UPDATE_BOOLEAN_ATTRIBUTE: + return 'mutation updateBooleanAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: Boolean){ + databasesUpdateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; - case self::$UPDATE_URL_COLUMN: - return 'mutation updateUrlColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateUrlColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { + case self::$UPDATE_URL_ATTRIBUTE: + return 'mutation updateUrlAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ + databasesUpdateUrlAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; - case self::$UPDATE_EMAIL_COLUMN: - return 'mutation updateEmailColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateEmailColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { + case self::$UPDATE_EMAIL_ATTRIBUTE: + return 'mutation updateEmailAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ + databasesUpdateEmailAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; - case self::$UPDATE_IP_COLUMN: - return 'mutation updateIpColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateIpColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { + case self::$UPDATE_IP_ATTRIBUTE: + return 'mutation updateIpAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ + databasesUpdateIpAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; - case self::$UPDATE_ENUM_COLUMN: - return 'mutation updateEnumColumn($databaseId: String!, $tableId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String){ - databasesUpdateEnumColumn(databaseId: $databaseId, tableId: $tableId, key: $key, elements: $elements, required: $required, default: $default) { + case self::$UPDATE_ENUM_ATTRIBUTE: + return 'mutation updateEnumAttribute($databaseId: String!, $collectionId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String){ + databasesUpdateEnumAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, elements: $elements, required: $required, default: $default) { elements required default } }'; - case self::$UPDATE_DATETIME_COLUMN: - return 'mutation updateDatetimeColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateDatetimeColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { + case self::$UPDATE_DATETIME_ATTRIBUTE: + return 'mutation updateDatetimeAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ + databasesUpdateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; - case self::$UPDATE_RELATIONSHIP_COLUMN: - return 'mutation updateRelationshipColumn($databaseId: String!, $tableId: String!, $key: String!, $onDelete: String){ - databasesUpdateRelationshipColumn(databaseId: $databaseId, tableId: $tableId, key: $key, onDelete: $onDelete) { - relatedTable + case self::$UPDATE_RELATIONSHIP_ATTRIBUTE: + return 'mutation updateRelationshipAttribute($databaseId: String!, $collectionId: String!, $key: String!, $onDelete: String){ + databasesUpdateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, onDelete: $onDelete) { + relatedCollection relationType twoWay key @@ -615,16 +615,16 @@ trait Base } }'; case self::$CREATE_INDEX: - return 'mutation createIndex($databaseId: String!, $tableId: String!, $key: String!, $type: String!, $columns: [String!]!, $orders: [String!]){ - databasesCreateIndex(databaseId: $databaseId, tableId: $tableId, key: $key, type: $type, columns: $columns, orders: $orders) { + return 'mutation createIndex($databaseId: String!, $collectionId: String!, $key: String!, $type: String!, $attributes: [String!]!, $orders: [String!]){ + databasesCreateIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key, type: $type, attributes: $attributes, orders: $orders) { key type status } }'; case self::$GET_INDEXES: - return 'query listIndexes($databaseId: String!, $tableId: String!) { - databasesListIndexes(databaseId: $databaseId, tableId: $tableId) { + return 'query listIndexes($databaseId: String!, $collectionId: String!) { + databasesListIndexes(databaseId: $databaseId, collectionId: $collectionId) { total indexes { key @@ -634,66 +634,66 @@ trait Base } }'; case self::$GET_INDEX: - return 'query getIndex($databaseId: String!, $tableId: String!, $key: String!) { - databasesGetIndex(databaseId: $databaseId, tableId: $tableId, key: $key) { + return 'query getIndex($databaseId: String!, $collectionId: String!, $key: String!) { + databasesGetIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key) { key type status } }'; case self::$DELETE_INDEX: - return 'mutation deleteIndex($databaseId: String!, $tableId: String!, $key: String!) { - databasesDeleteIndex(databaseId: $databaseId, tableId: $tableId, key: $key) { + return 'mutation deleteIndex($databaseId: String!, $collectionId: String!, $key: String!) { + databasesDeleteIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key) { status } }'; - case self::$GET_COLUMNS: - return 'query listColumns($databaseId: String!, $tableId: String!) { - databasesListColumns(databaseId: $databaseId, tableId: $tableId) { + case self::$GET_ATTRIBUTES: + return 'query listAttributes($databaseId: String!, $collectionId: String!) { + databasesListAttributes(databaseId: $databaseId, collectionId: $collectionId) { total - columns { - ...columnProperties + attributes { + ...attributeProperties } } - }' . PHP_EOL . self::$FRAGMENT_COLUMNS; - case self::$GET_COLUMN: - return 'query getColumn($databaseId: String!, $tableId: String!, $key: String!) { - databasesGetColumn(databaseId: $databaseId, tableId: $tableId, key: $key) { - ...columnProperties + }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; + case self::$GET_ATTRIBUTE: + return 'query getAttribute($databaseId: String!, $collectionId: String!, $key: String!) { + databasesGetAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { + ...attributeProperties } - }' . PHP_EOL . self::$FRAGMENT_COLUMNS; - case self::$DELETE_COLUMN: - return 'mutation deleteColumn($databaseId: String!, $tableId: String!, $key: String!) { - databasesDeleteColumn(databaseId: $databaseId, tableId: $tableId, key: $key) { + }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; + case self::$DELETE_ATTRIBUTE: + return 'mutation deleteAttribute($databaseId: String!, $collectionId: String!, $key: String!) { + databasesDeleteAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { status } }'; - case self::$GET_ROW: - return 'query getRow($databaseId: String!, $tableId: String!, $rowId: String!) { - databasesGetRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId) { + case self::$GET_DOCUMENT: + return 'query getDocument($databaseId: String!, $collectionId: String!, $documentId: String!) { + databasesGetDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { _id - _tableId + _collectionId _permissions data } }'; - case self::$GET_ROWS: - return 'query listRows($databaseId: String!, $tableId: String!){ - databasesListRows(databaseId: $databaseId, tableId: $tableId) { + case self::$GET_DOCUMENTS: + return 'query listDocuments($databaseId: String!, $collectionId: String!){ + databasesListDocuments(databaseId: $databaseId, collectionId: $collectionId) { total - rows { + documents { _id - _tableId + _collectionId _permissions data } } }'; - case self::$CREATE_ROW: - return 'mutation createRow($databaseId: String!, $tableId: String!, $rowId: String!, $data: Json!, $permissions: [String!]){ - databasesCreateRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId, data: $data, permissions: $permissions) { + case self::$CREATE_DOCUMENT: + return 'mutation createDocument($databaseId: String!, $collectionId: String!, $documentId: String!, $data: Json!, $permissions: [String!]){ + databasesCreateDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { _id - _tableId + _collectionId _permissions } }'; @@ -756,17 +756,17 @@ trait Base return 'mutation deleteCustomEntity($id: String!){ actorsDelete(id: $id) }'; - case self::$UPDATE_ROW: - return 'mutation updateRow($databaseId: String!, $tableId: String!, $rowId: String!, $data: Json!, $permissions: [String!]){ - databasesUpdateRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId, data: $data, permissions: $permissions) { + case self::$UPDATE_DOCUMENT: + return 'mutation updateDocument($databaseId: String!, $collectionId: String!, $documentId: String!, $data: Json!, $permissions: [String!]){ + databasesUpdateDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { _id - _tableId + _collectionId data } }'; - case self::$DELETE_ROW: - return 'mutation deleteRow($databaseId: String!, $tableId: String!, $rowId: String!){ - databasesDeleteRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId) { + case self::$DELETE_DOCUMENT: + return 'mutation deleteDocument($databaseId: String!, $collectionId: String!, $documentId: String!){ + databasesDeleteDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { status } }'; @@ -2246,12 +2246,12 @@ trait Base } }'; case self::$COMPLEX_QUERY: - return 'mutation complex($databaseId: String!, $databaseName: String!, $tableId: String!, $collectionName: String!, $documentSecurity: Boolean!, $collectionPermissions: [String!]!) { + return 'mutation complex($databaseId: String!, $databaseName: String!, $collectionId: String!, $collectionName: String!, $documentSecurity: Boolean!, $collectionPermissions: [String!]!) { databasesCreate(databaseId: $databaseId, name: $databaseName) { _id name } - databasesCreateTable(databaseId: $databaseId, tableId: $tableId, name: $collectionName, documentSecurity: $documentSecurity, permissions: $collectionPermissions) { + databasesCreateCollection(databaseId: $databaseId, collectionId: $collectionId, name: $collectionName, documentSecurity: $documentSecurity, permissions: $collectionPermissions) { _id _createdAt _updatedAt @@ -2259,8 +2259,8 @@ trait Base _databaseId name documentSecurity - columns { - ...columnProperties + attributes { + ...attributeProperties } indexes { key @@ -2268,7 +2268,7 @@ trait Base status } } - databasesCreateStringColumn(databaseId: $databaseId, tableId: $tableId, key: "name", size: 255, required: true) { + databasesCreateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "name", size: 255, required: true) { key type status @@ -2277,7 +2277,7 @@ trait Base default array } - databasesCreateIntegerColumn(databaseId: $databaseId, tableId: $tableId, key: "age", min: 0, max: 150, required: true) { + databasesCreateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "age", min: 0, max: 150, required: true) { key type status @@ -2287,7 +2287,7 @@ trait Base default array } - databasesCreateBooleanColumn(databaseId: $databaseId, tableId: $tableId, key: "alive", required: false, default: true) { + databasesCreateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "alive", required: false, default: true) { key type status @@ -2487,7 +2487,7 @@ trait Base data } } - }' . PHP_EOL . self::$FRAGMENT_COLUMNS; + }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; } throw new \InvalidArgumentException('Invalid query type'); diff --git a/tests/e2e/Services/GraphQL/DatabaseClientTest.php b/tests/e2e/Services/GraphQL/DatabaseClientTest.php index efd2430629..3853a3fc17 100644 --- a/tests/e2e/Services/GraphQL/DatabaseClientTest.php +++ b/tests/e2e/Services/GraphQL/DatabaseClientTest.php @@ -48,12 +48,12 @@ class DatabaseClientTest extends Scope public function testCreateCollection($database): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_TABLE); + $query = $this->getQuery(self::$CREATE_COLLECTION); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $database['_id'], - 'tableId' => 'actors', + 'collectionId' => 'actors', 'name' => 'Actors', 'documentSecurity' => false, 'permissions' => [ @@ -65,20 +65,20 @@ class DatabaseClientTest extends Scope ] ]; - $table = $this->client->call(Client::METHOD_POST, '/graphql', [ + $collection = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $this->getProject()['apiKey'], ], $gqlPayload); - $this->assertIsArray($table['body']['data']); - $this->assertArrayNotHasKey('errors', $table['body']); - $table = $table['body']['data']['databasesCreateTable']; - $this->assertEquals('Actors', $table['name']); + $this->assertIsArray($collection['body']['data']); + $this->assertArrayNotHasKey('errors', $collection['body']); + $collection = $collection['body']['data']['databasesCreateCollection']; + $this->assertEquals('Actors', $collection['name']); return [ 'database' => $database, - 'table' => $table, + 'collection' => $collection, ]; } @@ -88,12 +88,12 @@ class DatabaseClientTest extends Scope public function testCreateStringAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_STRING_COLUMN); + $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'name', 'size' => 256, 'required' => true, @@ -108,7 +108,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateStringColumn']); + $this->assertIsArray($attribute['body']['data']['databasesCreateStringAttribute']); return $data; } @@ -119,12 +119,12 @@ class DatabaseClientTest extends Scope public function testCreateIntegerAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_INTEGER_COLUMN); + $query = $this->getQuery(self::$CREATE_INTEGER_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'age', 'min' => 18, 'max' => 150, @@ -140,7 +140,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateIntegerColumn']); + $this->assertIsArray($attribute['body']['data']['databasesCreateIntegerAttribute']); return $data; } @@ -154,13 +154,13 @@ class DatabaseClientTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_ROW); + $query = $this->getQuery(self::$CREATE_DOCUMENT); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], - 'rowId' => ID::unique(), + 'collectionId' => $data['collection']['_id'], + 'documentId' => ID::unique(), 'data' => [ 'name' => 'John Doe', 'age' => 35, @@ -181,13 +181,13 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['databasesCreateRow']; + $document = $document['body']['data']['databasesCreateDocument']; $this->assertIsArray($document); return [ 'database' => $data['database'], - 'table' => $data['table'], - 'row' => $document, + 'collection' => $data['collection'], + 'document' => $document, ]; } @@ -198,12 +198,12 @@ class DatabaseClientTest extends Scope public function testGetDocuments($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_ROWS); + $query = $this->getQuery(self::$GET_DOCUMENTS); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], ] ]; @@ -214,7 +214,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $documents['body']); $this->assertIsArray($documents['body']['data']); - $this->assertIsArray($documents['body']['data']['databasesListRows']); + $this->assertIsArray($documents['body']['data']['databasesListDocuments']); } /** @@ -224,13 +224,13 @@ class DatabaseClientTest extends Scope public function testGetDocument($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_ROW); + $query = $this->getQuery(self::$GET_DOCUMENT); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], - 'rowId' => $data['row']['_id'], + 'collectionId' => $data['collection']['_id'], + 'documentId' => $data['document']['_id'], ] ]; @@ -241,7 +241,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $this->assertIsArray($document['body']['data']['databasesGetRow']); + $this->assertIsArray($document['body']['data']['databasesGetDocument']); } /** @@ -251,13 +251,13 @@ class DatabaseClientTest extends Scope public function testUpdateDocument($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_ROW); + $query = $this->getQuery(self::$UPDATE_DOCUMENT); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], - 'rowId' => $data['row']['_id'], + 'collectionId' => $data['collection']['_id'], + 'documentId' => $data['document']['_id'], 'data' => [ 'name' => 'New Document Name', ], @@ -271,7 +271,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['databasesUpdateRow']; + $document = $document['body']['data']['databasesUpdateDocument']; $this->assertIsArray($document); $this->assertStringContainsString('New Document Name', $document['data']); @@ -284,13 +284,13 @@ class DatabaseClientTest extends Scope public function testDeleteDocument($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$DELETE_ROW); + $query = $this->getQuery(self::$DELETE_DOCUMENT); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], - 'rowId' => $data['row']['_id'], + 'collectionId' => $data['collection']['_id'], + 'documentId' => $data['document']['_id'], ] ]; diff --git a/tests/e2e/Services/GraphQL/DatabaseServerTest.php b/tests/e2e/Services/GraphQL/DatabaseServerTest.php index 0ea86c03cf..87006a1bea 100644 --- a/tests/e2e/Services/GraphQL/DatabaseServerTest.php +++ b/tests/e2e/Services/GraphQL/DatabaseServerTest.php @@ -49,12 +49,12 @@ class DatabaseServerTest extends Scope public function testCreateCollection($database): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_TABLE); + $query = $this->getQuery(self::$CREATE_COLLECTION); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $database['_id'], - 'tableId' => 'actors', + 'collectionId' => 'actors', 'name' => 'Actors', 'documentSecurity' => false, 'permissions' => [ @@ -73,14 +73,14 @@ class DatabaseServerTest extends Scope $this->assertIsArray($collection['body']['data']); $this->assertArrayNotHasKey('errors', $collection['body']); - $collection = $collection['body']['data']['databasesCreateTable']; + $collection = $collection['body']['data']['databasesCreateCollection']; $this->assertEquals('Actors', $collection['name']); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $database['_id'], - 'tableId' => 'movies', + 'collectionId' => 'movies', 'name' => 'Movies', 'documentSecurity' => false, 'permissions' => [ @@ -92,20 +92,20 @@ class DatabaseServerTest extends Scope ] ]; - $table2 = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + $collection2 = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), $gqlPayload); - $this->assertIsArray($table2['body']['data']); - $this->assertArrayNotHasKey('errors', $table2['body']); - $table2 = $table2['body']['data']['databasesCreateTable']; - $this->assertEquals('Movies', $table2['name']); + $this->assertIsArray($collection2['body']['data']); + $this->assertArrayNotHasKey('errors', $collection2['body']); + $collection2 = $collection2['body']['data']['databasesCreateCollection']; + $this->assertEquals('Movies', $collection2['name']); return [ 'database' => $database, - 'table' => $collection, - 'table2' => $table2, + 'collection' => $collection, + 'collection2' => $collection2, ]; } @@ -116,12 +116,12 @@ class DatabaseServerTest extends Scope public function testCreateStringAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_STRING_COLUMN); + $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'name', 'size' => 256, 'required' => true, @@ -135,7 +135,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateStringColumn']); + $this->assertIsArray($attribute['body']['data']['databasesCreateStringAttribute']); return $data; } @@ -150,12 +150,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_STRING_COLUMN); + $query = $this->getQuery(self::$UPDATE_STRING_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'name', 'required' => false, 'default' => 'Default Value', @@ -168,9 +168,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateStringColumn']); - $this->assertFalse($attribute['body']['data']['databasesUpdateStringColumn']['required']); - $this->assertEquals('Default Value', $attribute['body']['data']['databasesUpdateStringColumn']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateStringAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateStringAttribute']['required']); + $this->assertEquals('Default Value', $attribute['body']['data']['databasesUpdateStringAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -183,12 +183,12 @@ class DatabaseServerTest extends Scope public function testCreateIntegerAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_INTEGER_COLUMN); + $query = $this->getQuery(self::$CREATE_INTEGER_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'age', 'min' => 18, 'max' => 150, @@ -203,7 +203,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateIntegerColumn']); + $this->assertIsArray($attribute['body']['data']['databasesCreateIntegerAttribute']); return $data; } @@ -218,12 +218,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_INTEGER_COLUMN); + $query = $this->getQuery(self::$UPDATE_INTEGER_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'age', 'required' => false, 'min' => 12, @@ -238,11 +238,11 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateIntegerColumn']); - $this->assertFalse($attribute['body']['data']['databasesUpdateIntegerColumn']['required']); - $this->assertEquals(12, $attribute['body']['data']['databasesUpdateIntegerColumn']['min']); - $this->assertEquals(160, $attribute['body']['data']['databasesUpdateIntegerColumn']['max']); - $this->assertEquals(50, $attribute['body']['data']['databasesUpdateIntegerColumn']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateIntegerAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateIntegerAttribute']['required']); + $this->assertEquals(12, $attribute['body']['data']['databasesUpdateIntegerAttribute']['min']); + $this->assertEquals(160, $attribute['body']['data']['databasesUpdateIntegerAttribute']['max']); + $this->assertEquals(50, $attribute['body']['data']['databasesUpdateIntegerAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -255,12 +255,12 @@ class DatabaseServerTest extends Scope public function testCreateBooleanAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_BOOLEAN_COLUMN); + $query = $this->getQuery(self::$CREATE_BOOLEAN_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'alive', 'required' => true, ] @@ -273,7 +273,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateBooleanColumn']); + $this->assertIsArray($attribute['body']['data']['databasesCreateBooleanAttribute']); return $data; } @@ -288,12 +288,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_BOOLEAN_COLUMN); + $query = $this->getQuery(self::$UPDATE_BOOLEAN_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'alive', 'required' => false, 'default' => true @@ -306,9 +306,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateBooleanColumn']); - $this->assertFalse($attribute['body']['data']['databasesUpdateBooleanColumn']['required']); - $this->assertTrue($attribute['body']['data']['databasesUpdateBooleanColumn']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateBooleanAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateBooleanAttribute']['required']); + $this->assertTrue($attribute['body']['data']['databasesUpdateBooleanAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -321,12 +321,12 @@ class DatabaseServerTest extends Scope public function testCreateFloatAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_FLOAT_COLUMN); + $query = $this->getQuery(self::$CREATE_FLOAT_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'salary', 'min' => 1000.0, 'max' => 999999.99, @@ -342,7 +342,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateFloatColumn']); + $this->assertIsArray($attribute['body']['data']['databasesCreateFloatAttribute']); return $data; } @@ -357,12 +357,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_FLOAT_COLUMN); + $query = $this->getQuery(self::$UPDATE_FLOAT_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'salary', 'required' => false, 'min' => 100.0, @@ -377,11 +377,11 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateFloatColumn']); - $this->assertFalse($attribute['body']['data']['databasesUpdateFloatColumn']['required']); - $this->assertEquals(100.0, $attribute['body']['data']['databasesUpdateFloatColumn']['min']); - $this->assertEquals(1000000.0, $attribute['body']['data']['databasesUpdateFloatColumn']['max']); - $this->assertEquals(2500.0, $attribute['body']['data']['databasesUpdateFloatColumn']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateFloatAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateFloatAttribute']['required']); + $this->assertEquals(100.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['min']); + $this->assertEquals(1000000.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['max']); + $this->assertEquals(2500.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -394,12 +394,12 @@ class DatabaseServerTest extends Scope public function testCreateEmailAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_EMAIL_COLUMN); + $query = $this->getQuery(self::$CREATE_EMAIL_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'email', 'required' => true, ] @@ -412,7 +412,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateEmailColumn']); + $this->assertIsArray($attribute['body']['data']['databasesCreateEmailAttribute']); return $data; } @@ -427,12 +427,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_EMAIL_COLUMN); + $query = $this->getQuery(self::$UPDATE_EMAIL_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'email', 'required' => false, 'default' => 'torsten@appwrite.io', @@ -445,9 +445,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateEmailColumn']); - $this->assertFalse($attribute['body']['data']['databasesUpdateEmailColumn']['required']); - $this->assertEquals('torsten@appwrite.io', $attribute['body']['data']['databasesUpdateEmailColumn']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateEmailAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateEmailAttribute']['required']); + $this->assertEquals('torsten@appwrite.io', $attribute['body']['data']['databasesUpdateEmailAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -460,12 +460,12 @@ class DatabaseServerTest extends Scope public function testCreateEnumAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_ENUM_COLUMN); + $query = $this->getQuery(self::$CREATE_ENUM_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'role', 'elements' => [ 'crew', @@ -483,7 +483,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateEnumColumn']); + $this->assertIsArray($attribute['body']['data']['databasesCreateEnumAttribute']); return $data; } @@ -499,12 +499,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_ENUM_COLUMN); + $query = $this->getQuery(self::$UPDATE_ENUM_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'role', 'required' => false, 'elements' => [ @@ -522,11 +522,11 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateEnumColumn']); - $this->assertFalse($attribute['body']['data']['databasesUpdateEnumColumn']['required']); - $this->assertEquals('tech', $attribute['body']['data']['databasesUpdateEnumColumn']['default']); - $this->assertContains('tech', $attribute['body']['data']['databasesUpdateEnumColumn']['elements']); - $this->assertNotContains('guest', $attribute['body']['data']['databasesUpdateEnumColumn']['elements']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateEnumAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateEnumAttribute']['required']); + $this->assertEquals('tech', $attribute['body']['data']['databasesUpdateEnumAttribute']['default']); + $this->assertContains('tech', $attribute['body']['data']['databasesUpdateEnumAttribute']['elements']); + $this->assertNotContains('guest', $attribute['body']['data']['databasesUpdateEnumAttribute']['elements']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -539,12 +539,12 @@ class DatabaseServerTest extends Scope public function testCreateDatetimeAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_DATETIME_COLUMN); + $query = $this->getQuery(self::$CREATE_DATETIME_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'dob', 'required' => true, ] @@ -557,7 +557,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateDatetimeColumn']); + $this->assertIsArray($attribute['body']['data']['databasesCreateDatetimeAttribute']); return $data; } @@ -572,12 +572,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_DATETIME_COLUMN); + $query = $this->getQuery(self::$UPDATE_DATETIME_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'dob', 'required' => false, 'default' => '2000-01-01T00:00:00Z' @@ -590,9 +590,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateDatetimeColumn']); - $this->assertFalse($attribute['body']['data']['databasesUpdateDatetimeColumn']['required']); - $this->assertEquals('2000-01-01T00:00:00Z', $attribute['body']['data']['databasesUpdateDatetimeColumn']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateDatetimeAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateDatetimeAttribute']['required']); + $this->assertEquals('2000-01-01T00:00:00Z', $attribute['body']['data']['databasesUpdateDatetimeAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -604,13 +604,13 @@ class DatabaseServerTest extends Scope public function testCreateRelationshipAttribute(array $data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_RELATIONSHIP_COLUMN); + $query = $this->getQuery(self::$CREATE_RELATIONSHIP_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table2']['_id'], // Movies - 'relatedTableId' => $data['table']['_id'], // Actors + 'collectionId' => $data['collection2']['_id'], // Movies + 'relatedCollectionId' => $data['collection']['_id'], // Actors 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => true, 'key' => 'actors', @@ -623,10 +623,9 @@ class DatabaseServerTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), $gqlPayload); - $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateRelationshipColumn']); + $this->assertIsArray($attribute['body']['data']['databasesCreateRelationshipAttribute']); return $data; } @@ -639,12 +638,12 @@ class DatabaseServerTest extends Scope sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_RELATIONSHIP_COLUMN); + $query = $this->getQuery(self::$UPDATE_RELATIONSHIP_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table2']['_id'], + 'collectionId' => $data['collection2']['_id'], 'key' => 'actors', 'onDelete' => Database::RELATION_MUTATE_CASCADE, ] @@ -657,7 +656,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateRelationshipColumn']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateRelationshipAttribute']); return $data; } @@ -669,12 +668,12 @@ class DatabaseServerTest extends Scope public function testCreateIPAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_IP_COLUMN); + $query = $this->getQuery(self::$CREATE_IP_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'ip', 'required' => false, 'default' => '::1', @@ -688,7 +687,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateIpColumn']); + $this->assertIsArray($attribute['body']['data']['databasesCreateIpAttribute']); return $data; } @@ -703,12 +702,12 @@ class DatabaseServerTest extends Scope sleep(3); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_IP_COLUMN); + $query = $this->getQuery(self::$UPDATE_IP_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'ip', 'required' => false, 'default' => '127.0.0.1' @@ -721,9 +720,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateIpColumn']); - $this->assertFalse($attribute['body']['data']['databasesUpdateIpColumn']['required']); - $this->assertEquals('127.0.0.1', $attribute['body']['data']['databasesUpdateIpColumn']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateIpAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateIpAttribute']['required']); + $this->assertEquals('127.0.0.1', $attribute['body']['data']['databasesUpdateIpAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -736,12 +735,12 @@ class DatabaseServerTest extends Scope public function testCreateURLAttribute($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_URL_COLUMN); + $query = $this->getQuery(self::$CREATE_URL_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'url', 'required' => false, 'default' => 'https://appwrite.io', @@ -755,7 +754,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateUrlColumn']); + $this->assertIsArray($attribute['body']['data']['databasesCreateUrlAttribute']); return $data; } @@ -770,12 +769,12 @@ class DatabaseServerTest extends Scope sleep(3); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_URL_COLUMN); + $query = $this->getQuery(self::$UPDATE_URL_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'url', 'required' => false, 'default' => 'https://cloud.appwrite.io' @@ -788,9 +787,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateUrlColumn']); - $this->assertFalse($attribute['body']['data']['databasesUpdateUrlColumn']['required']); - $this->assertEquals('https://cloud.appwrite.io', $attribute['body']['data']['databasesUpdateUrlColumn']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateUrlAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateUrlAttribute']['required']); + $this->assertEquals('https://cloud.appwrite.io', $attribute['body']['data']['databasesUpdateUrlAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); } @@ -807,10 +806,10 @@ class DatabaseServerTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'index', 'type' => 'key', - 'columns' => [ + 'attributes' => [ 'name', 'age', ], @@ -828,7 +827,7 @@ class DatabaseServerTest extends Scope return [ 'database' => $data['database'], - 'table' => $data['table'], + 'collection' => $data['collection'], 'index' => $index['body']['data']['databasesCreateIndex'], ]; } @@ -843,13 +842,13 @@ class DatabaseServerTest extends Scope public function testCreateDocument($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_ROW); + $query = $this->getQuery(self::$CREATE_DOCUMENT); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], - 'rowId' => ID::unique(), + 'collectionId' => $data['collection']['_id'], + 'documentId' => ID::unique(), 'data' => [ 'name' => 'John Doe', 'email' => 'example@appwrite.io', @@ -867,21 +866,21 @@ class DatabaseServerTest extends Scope ] ]; - $row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + $document = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), $gqlPayload); - $this->assertArrayNotHasKey('errors', $row['body']); - $this->assertIsArray($row['body']['data']); + $this->assertArrayNotHasKey('errors', $document['body']); + $this->assertIsArray($document['body']['data']); - $row = $row['body']['data']['databasesCreateRow']; - $this->assertIsArray($row); + $document = $document['body']['data']['databasesCreateDocument']; + $this->assertIsArray($document); return [ 'database' => $data['database'], - 'table' => $data['table'], - 'row' => $row, + 'collection' => $data['collection'], + 'document' => $document, ]; } @@ -975,7 +974,7 @@ class DatabaseServerTest extends Scope public function testGetCollections($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_TABLES); + $query = $this->getQuery(self::$GET_COLLECTIONS); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -990,7 +989,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $collections['body']); $this->assertIsArray($collections['body']['data']); - $this->assertIsArray($collections['body']['data']['databasesListTables']); + $this->assertIsArray($collections['body']['data']['databasesListCollections']); } /** @@ -1000,12 +999,12 @@ class DatabaseServerTest extends Scope public function testGetCollection($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_TABLE); + $query = $this->getQuery(self::$GET_COLLECTION); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], ] ]; @@ -1016,7 +1015,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $collection['body']); $this->assertIsArray($collection['body']['data']); - $this->assertIsArray($collection['body']['data']['databasesGetTable']); + $this->assertIsArray($collection['body']['data']['databasesGetCollection']); } /** @@ -1027,12 +1026,12 @@ class DatabaseServerTest extends Scope public function testGetAttributes($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_COLUMNS); + $query = $this->getQuery(self::$GET_ATTRIBUTES); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], ] ]; @@ -1043,7 +1042,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attributes['body']); $this->assertIsArray($attributes['body']['data']); - $this->assertIsArray($attributes['body']['data']['databasesListColumns']); + $this->assertIsArray($attributes['body']['data']['databasesListAttributes']); } /** @@ -1053,12 +1052,12 @@ class DatabaseServerTest extends Scope public function testGetAttribute($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_COLUMN); + $query = $this->getQuery(self::$GET_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'name', ] ]; @@ -1070,7 +1069,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesGetColumn']); + $this->assertIsArray($attribute['body']['data']['databasesGetAttribute']); } /** @@ -1085,7 +1084,7 @@ class DatabaseServerTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], ] ]; @@ -1111,7 +1110,7 @@ class DatabaseServerTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => $data['index']['key'], ] ]; @@ -1133,12 +1132,12 @@ class DatabaseServerTest extends Scope public function testGetDocuments($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_ROWS); + $query = $this->getQuery(self::$GET_DOCUMENTS); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], ] ]; @@ -1149,7 +1148,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $documents['body']); $this->assertIsArray($documents['body']['data']); - $this->assertIsArray($documents['body']['data']['databasesListRows']); + $this->assertIsArray($documents['body']['data']['databasesListDocuments']); } /** @@ -1159,13 +1158,13 @@ class DatabaseServerTest extends Scope public function testGetDocument($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_ROW); + $query = $this->getQuery(self::$GET_DOCUMENT); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], - 'rowId' => $data['row']['_id'], + 'collectionId' => $data['collection']['_id'], + 'documentId' => $data['document']['_id'], ] ]; @@ -1176,7 +1175,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $this->assertIsArray($document['body']['data']['databasesGetRow']); + $this->assertIsArray($document['body']['data']['databasesGetDocument']); } // /** @@ -1259,12 +1258,12 @@ class DatabaseServerTest extends Scope public function testUpdateCollection($data) { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_TABLE); + $query = $this->getQuery(self::$UPDATE_COLLECTION); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'name' => 'New Collection Name', 'documentSecurity' => false, ] @@ -1277,7 +1276,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $collection['body']); $this->assertIsArray($collection['body']['data']); - $this->assertIsArray($collection['body']['data']['databasesUpdateTable']); + $this->assertIsArray($collection['body']['data']['databasesUpdateCollection']); } /** @@ -1287,13 +1286,13 @@ class DatabaseServerTest extends Scope public function testUpdateDocument($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_ROW); + $query = $this->getQuery(self::$UPDATE_DOCUMENT); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], - 'rowId' => $data['row']['_id'], + 'collectionId' => $data['collection']['_id'], + 'documentId' => $data['document']['_id'], 'data' => [ 'name' => 'New Document Name', ], @@ -1307,7 +1306,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['databasesUpdateRow']; + $document = $document['body']['data']['databasesUpdateDocument']; $this->assertIsArray($document); $this->assertStringContainsString('New Document Name', $document['data']); } @@ -1347,13 +1346,13 @@ class DatabaseServerTest extends Scope public function testDeleteDocument($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$DELETE_ROW); + $query = $this->getQuery(self::$DELETE_DOCUMENT); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], - 'rowId' => $data['row']['_id'], + 'collectionId' => $data['collection']['_id'], + 'documentId' => $data['document']['_id'], ] ]; @@ -1397,12 +1396,12 @@ class DatabaseServerTest extends Scope public function testDeleteAttribute($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$DELETE_COLUMN); + $query = $this->getQuery(self::$DELETE_ATTRIBUTE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], 'key' => 'name', ] ]; @@ -1423,12 +1422,12 @@ class DatabaseServerTest extends Scope public function testDeleteCollection($data) { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$DELETE_TABLE); + $query = $this->getQuery(self::$DELETE_COLLECTION); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['table']['_id'], + 'collectionId' => $data['collection']['_id'], ] ]; From c542ba033f259e8f5c9ff06897666a37d8ba79a6 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 18:15:17 +0530 Subject: [PATCH 110/343] patch: graphql tests <> collections. --- tests/e2e/Services/GraphQL/AuthTest.php | 6 +- tests/e2e/Services/GraphQL/Base.php | 64 +++++------ .../Services/GraphQL/DatabaseClientTest.php | 12 +- .../Services/GraphQL/DatabaseServerTest.php | 108 +++++++++--------- 4 files changed, 95 insertions(+), 95 deletions(-) diff --git a/tests/e2e/Services/GraphQL/AuthTest.php b/tests/e2e/Services/GraphQL/AuthTest.php index ecce29f2b3..db56537999 100644 --- a/tests/e2e/Services/GraphQL/AuthTest.php +++ b/tests/e2e/Services/GraphQL/AuthTest.php @@ -178,7 +178,7 @@ class AuthTest extends Scope 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], - 'documentId' => $document['body']['data']['databasesCreateDocument']['_id'], + 'documentId' => $document['body']['data']['collectionsCreateDocument']['_id'], ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -187,7 +187,7 @@ class AuthTest extends Scope 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); - $this->assertIsArray($document['body']['data']['databasesGetDocument']); + $this->assertIsArray($document['body']['data']['collectionsGetDocument']); $this->assertArrayNotHasKey('errors', $document['body']); // Try to read as account 2 @@ -237,7 +237,7 @@ class AuthTest extends Scope 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], - 'documentId' => $document['body']['data']['databasesCreateDocument']['_id'], + 'documentId' => $document['body']['data']['collectionsCreateDocument']['_id'], ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', [ diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 121d40156e..f7ee14f7e1 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -440,7 +440,7 @@ trait Base }'; case self::$CREATE_STRING_ATTRIBUTE: return 'mutation createStringAttribute($databaseId: String!, $collectionId: String!, $key: String!, $size: Int!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, size: $size, required: $required, default: $default, array: $array) { + collectionsCreateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, size: $size, required: $required, default: $default, array: $array) { key required default @@ -449,7 +449,7 @@ trait Base }'; case self::$CREATE_INTEGER_ATTRIBUTE: return 'mutation createIntegerAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Int, $max: Int, $default: Int, $array: Boolean){ - databasesCreateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { + collectionsCreateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { key required min @@ -460,7 +460,7 @@ trait Base }'; case self::$CREATE_FLOAT_ATTRIBUTE: return 'mutation createFloatAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Float, $max: Float, $default: Float, $array: Boolean){ - databasesCreateFloatAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { + collectionsCreateFloatAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { key required min @@ -471,7 +471,7 @@ trait Base }'; case self::$CREATE_BOOLEAN_ATTRIBUTE: return 'mutation createBooleanAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: Boolean, $array: Boolean){ - databasesCreateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + collectionsCreateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default @@ -480,7 +480,7 @@ trait Base }'; case self::$CREATE_URL_ATTRIBUTE: return 'mutation createUrlAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateUrlAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + collectionsCreateUrlAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default @@ -489,7 +489,7 @@ trait Base }'; case self::$CREATE_EMAIL_ATTRIBUTE: return 'mutation createEmailAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateEmailAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + collectionsCreateEmailAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default @@ -498,7 +498,7 @@ trait Base }'; case self::$CREATE_IP_ATTRIBUTE: return 'mutation createIpAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateIpAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + collectionsCreateIpAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default @@ -507,7 +507,7 @@ trait Base }'; case self::$CREATE_ENUM_ATTRIBUTE: return 'mutation createEnumAttribute($databaseId: String!, $collectionId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateEnumAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, elements: $elements, required: $required, default: $default, array: $array) { + collectionsCreateEnumAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, elements: $elements, required: $required, default: $default, array: $array) { key elements required @@ -517,7 +517,7 @@ trait Base }'; case self::$CREATE_DATETIME_ATTRIBUTE: return 'mutation createDatetimeAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - databasesCreateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + collectionsCreateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default @@ -526,7 +526,7 @@ trait Base }'; case self::$CREATE_RELATIONSHIP_ATTRIBUTE: return 'mutation createRelationshipAttribute($databaseId: String!, $collectionId: String!, $relatedCollectionId: String!, $type: String!, $twoWay: Boolean, $key: String, $twoWayKey: String, $onDelete: String){ - databasesCreateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, relatedCollectionId: $relatedCollectionId, type: $type, twoWay: $twoWay, key: $key, twoWayKey: $twoWayKey, onDelete: $onDelete) { + collectionsCreateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, relatedCollectionId: $relatedCollectionId, type: $type, twoWay: $twoWay, key: $key, twoWayKey: $twoWayKey, onDelete: $onDelete) { relatedCollection relationType twoWay @@ -537,14 +537,14 @@ trait Base }'; case self::$UPDATE_STRING_ATTRIBUTE: return 'mutation updateStringAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + collectionsUpdateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; case self::$UPDATE_INTEGER_ATTRIBUTE: return 'mutation updateIntegerAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Int!, $max: Int!, $default: Int){ - databasesUpdateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, min: $min, max: $max, default: $default) { + collectionsUpdateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, min: $min, max: $max, default: $default) { required min max @@ -553,7 +553,7 @@ trait Base }'; case self::$UPDATE_FLOAT_ATTRIBUTE: return 'mutation updateFloatAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Float!, $max: Float!, $default: Float){ - databasesUpdateFloatAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default) { + collectionsUpdateFloatAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default) { required min max @@ -562,35 +562,35 @@ trait Base }'; case self::$UPDATE_BOOLEAN_ATTRIBUTE: return 'mutation updateBooleanAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: Boolean){ - databasesUpdateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + collectionsUpdateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; case self::$UPDATE_URL_ATTRIBUTE: return 'mutation updateUrlAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateUrlAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + collectionsUpdateUrlAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; case self::$UPDATE_EMAIL_ATTRIBUTE: return 'mutation updateEmailAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateEmailAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + collectionsUpdateEmailAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; case self::$UPDATE_IP_ATTRIBUTE: return 'mutation updateIpAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateIpAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + collectionsUpdateIpAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; case self::$UPDATE_ENUM_ATTRIBUTE: return 'mutation updateEnumAttribute($databaseId: String!, $collectionId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String){ - databasesUpdateEnumAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, elements: $elements, required: $required, default: $default) { + collectionsUpdateEnumAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, elements: $elements, required: $required, default: $default) { elements required default @@ -598,14 +598,14 @@ trait Base }'; case self::$UPDATE_DATETIME_ATTRIBUTE: return 'mutation updateDatetimeAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - databasesUpdateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + collectionsUpdateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; case self::$UPDATE_RELATIONSHIP_ATTRIBUTE: return 'mutation updateRelationshipAttribute($databaseId: String!, $collectionId: String!, $key: String!, $onDelete: String){ - databasesUpdateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, onDelete: $onDelete) { + collectionsUpdateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, onDelete: $onDelete) { relatedCollection relationType twoWay @@ -616,7 +616,7 @@ trait Base }'; case self::$CREATE_INDEX: return 'mutation createIndex($databaseId: String!, $collectionId: String!, $key: String!, $type: String!, $attributes: [String!]!, $orders: [String!]){ - databasesCreateIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key, type: $type, attributes: $attributes, orders: $orders) { + collectionsCreateIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key, type: $type, attributes: $attributes, orders: $orders) { key type status @@ -624,7 +624,7 @@ trait Base }'; case self::$GET_INDEXES: return 'query listIndexes($databaseId: String!, $collectionId: String!) { - databasesListIndexes(databaseId: $databaseId, collectionId: $collectionId) { + collectionsListIndexes(databaseId: $databaseId, collectionId: $collectionId) { total indexes { key @@ -635,7 +635,7 @@ trait Base }'; case self::$GET_INDEX: return 'query getIndex($databaseId: String!, $collectionId: String!, $key: String!) { - databasesGetIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key) { + collectionsGetIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key) { key type status @@ -643,13 +643,13 @@ trait Base }'; case self::$DELETE_INDEX: return 'mutation deleteIndex($databaseId: String!, $collectionId: String!, $key: String!) { - databasesDeleteIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key) { + collectionsDeleteIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key) { status } }'; case self::$GET_ATTRIBUTES: return 'query listAttributes($databaseId: String!, $collectionId: String!) { - databasesListAttributes(databaseId: $databaseId, collectionId: $collectionId) { + collectionsListAttributes(databaseId: $databaseId, collectionId: $collectionId) { total attributes { ...attributeProperties @@ -658,19 +658,19 @@ trait Base }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; case self::$GET_ATTRIBUTE: return 'query getAttribute($databaseId: String!, $collectionId: String!, $key: String!) { - databasesGetAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { + collectionsGetAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { ...attributeProperties } }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; case self::$DELETE_ATTRIBUTE: return 'mutation deleteAttribute($databaseId: String!, $collectionId: String!, $key: String!) { - databasesDeleteAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { + collectionsDeleteAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { status } }'; case self::$GET_DOCUMENT: return 'query getDocument($databaseId: String!, $collectionId: String!, $documentId: String!) { - databasesGetDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { + collectionsGetDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { _id _collectionId _permissions @@ -679,7 +679,7 @@ trait Base }'; case self::$GET_DOCUMENTS: return 'query listDocuments($databaseId: String!, $collectionId: String!){ - databasesListDocuments(databaseId: $databaseId, collectionId: $collectionId) { + collectionsListDocuments(databaseId: $databaseId, collectionId: $collectionId) { total documents { _id @@ -691,7 +691,7 @@ trait Base }'; case self::$CREATE_DOCUMENT: return 'mutation createDocument($databaseId: String!, $collectionId: String!, $documentId: String!, $data: Json!, $permissions: [String!]){ - databasesCreateDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { + collectionsCreateDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { _id _collectionId _permissions @@ -758,7 +758,7 @@ trait Base }'; case self::$UPDATE_DOCUMENT: return 'mutation updateDocument($databaseId: String!, $collectionId: String!, $documentId: String!, $data: Json!, $permissions: [String!]){ - databasesUpdateDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { + collectionsUpdateDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { _id _collectionId data @@ -766,7 +766,7 @@ trait Base }'; case self::$DELETE_DOCUMENT: return 'mutation deleteDocument($databaseId: String!, $collectionId: String!, $documentId: String!){ - databasesDeleteDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { + collectionsDeleteDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { status } }'; diff --git a/tests/e2e/Services/GraphQL/DatabaseClientTest.php b/tests/e2e/Services/GraphQL/DatabaseClientTest.php index 3853a3fc17..f3029d60b4 100644 --- a/tests/e2e/Services/GraphQL/DatabaseClientTest.php +++ b/tests/e2e/Services/GraphQL/DatabaseClientTest.php @@ -108,7 +108,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateStringAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsCreateStringAttribute']); return $data; } @@ -140,7 +140,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateIntegerAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsCreateIntegerAttribute']); return $data; } @@ -181,7 +181,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['databasesCreateDocument']; + $document = $document['body']['data']['collectionsCreateDocument']; $this->assertIsArray($document); return [ @@ -214,7 +214,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $documents['body']); $this->assertIsArray($documents['body']['data']); - $this->assertIsArray($documents['body']['data']['databasesListDocuments']); + $this->assertIsArray($documents['body']['data']['collectionsListDocuments']); } /** @@ -241,7 +241,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $this->assertIsArray($document['body']['data']['databasesGetDocument']); + $this->assertIsArray($document['body']['data']['collectionsGetDocument']); } /** @@ -271,7 +271,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['databasesUpdateDocument']; + $document = $document['body']['data']['collectionsUpdateDocument']; $this->assertIsArray($document); $this->assertStringContainsString('New Document Name', $document['data']); diff --git a/tests/e2e/Services/GraphQL/DatabaseServerTest.php b/tests/e2e/Services/GraphQL/DatabaseServerTest.php index 87006a1bea..cdd2f4d69a 100644 --- a/tests/e2e/Services/GraphQL/DatabaseServerTest.php +++ b/tests/e2e/Services/GraphQL/DatabaseServerTest.php @@ -135,7 +135,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateStringAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsCreateStringAttribute']); return $data; } @@ -168,9 +168,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateStringAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateStringAttribute']['required']); - $this->assertEquals('Default Value', $attribute['body']['data']['databasesUpdateStringAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['collectionsUpdateStringAttribute']); + $this->assertFalse($attribute['body']['data']['collectionsUpdateStringAttribute']['required']); + $this->assertEquals('Default Value', $attribute['body']['data']['collectionsUpdateStringAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -203,7 +203,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateIntegerAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsCreateIntegerAttribute']); return $data; } @@ -238,11 +238,11 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateIntegerAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateIntegerAttribute']['required']); - $this->assertEquals(12, $attribute['body']['data']['databasesUpdateIntegerAttribute']['min']); - $this->assertEquals(160, $attribute['body']['data']['databasesUpdateIntegerAttribute']['max']); - $this->assertEquals(50, $attribute['body']['data']['databasesUpdateIntegerAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['collectionsUpdateIntegerAttribute']); + $this->assertFalse($attribute['body']['data']['collectionsUpdateIntegerAttribute']['required']); + $this->assertEquals(12, $attribute['body']['data']['collectionsUpdateIntegerAttribute']['min']); + $this->assertEquals(160, $attribute['body']['data']['collectionsUpdateIntegerAttribute']['max']); + $this->assertEquals(50, $attribute['body']['data']['collectionsUpdateIntegerAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -273,7 +273,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateBooleanAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsCreateBooleanAttribute']); return $data; } @@ -306,9 +306,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateBooleanAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateBooleanAttribute']['required']); - $this->assertTrue($attribute['body']['data']['databasesUpdateBooleanAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['collectionsUpdateBooleanAttribute']); + $this->assertFalse($attribute['body']['data']['collectionsUpdateBooleanAttribute']['required']); + $this->assertTrue($attribute['body']['data']['collectionsUpdateBooleanAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -342,7 +342,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateFloatAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsCreateFloatAttribute']); return $data; } @@ -377,11 +377,11 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateFloatAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateFloatAttribute']['required']); - $this->assertEquals(100.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['min']); - $this->assertEquals(1000000.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['max']); - $this->assertEquals(2500.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['collectionsUpdateFloatAttribute']); + $this->assertFalse($attribute['body']['data']['collectionsUpdateFloatAttribute']['required']); + $this->assertEquals(100.0, $attribute['body']['data']['collectionsUpdateFloatAttribute']['min']); + $this->assertEquals(1000000.0, $attribute['body']['data']['collectionsUpdateFloatAttribute']['max']); + $this->assertEquals(2500.0, $attribute['body']['data']['collectionsUpdateFloatAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -412,7 +412,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateEmailAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsCreateEmailAttribute']); return $data; } @@ -445,9 +445,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateEmailAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateEmailAttribute']['required']); - $this->assertEquals('torsten@appwrite.io', $attribute['body']['data']['databasesUpdateEmailAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['collectionsUpdateEmailAttribute']); + $this->assertFalse($attribute['body']['data']['collectionsUpdateEmailAttribute']['required']); + $this->assertEquals('torsten@appwrite.io', $attribute['body']['data']['collectionsUpdateEmailAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -483,7 +483,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateEnumAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsCreateEnumAttribute']); return $data; } @@ -522,11 +522,11 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateEnumAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateEnumAttribute']['required']); - $this->assertEquals('tech', $attribute['body']['data']['databasesUpdateEnumAttribute']['default']); - $this->assertContains('tech', $attribute['body']['data']['databasesUpdateEnumAttribute']['elements']); - $this->assertNotContains('guest', $attribute['body']['data']['databasesUpdateEnumAttribute']['elements']); + $this->assertIsArray($attribute['body']['data']['collectionsUpdateEnumAttribute']); + $this->assertFalse($attribute['body']['data']['collectionsUpdateEnumAttribute']['required']); + $this->assertEquals('tech', $attribute['body']['data']['collectionsUpdateEnumAttribute']['default']); + $this->assertContains('tech', $attribute['body']['data']['collectionsUpdateEnumAttribute']['elements']); + $this->assertNotContains('guest', $attribute['body']['data']['collectionsUpdateEnumAttribute']['elements']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -557,7 +557,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateDatetimeAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsCreateDatetimeAttribute']); return $data; } @@ -590,9 +590,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateDatetimeAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateDatetimeAttribute']['required']); - $this->assertEquals('2000-01-01T00:00:00Z', $attribute['body']['data']['databasesUpdateDatetimeAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['collectionsUpdateDatetimeAttribute']); + $this->assertFalse($attribute['body']['data']['collectionsUpdateDatetimeAttribute']['required']); + $this->assertEquals('2000-01-01T00:00:00Z', $attribute['body']['data']['collectionsUpdateDatetimeAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -625,7 +625,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateRelationshipAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsCreateRelationshipAttribute']); return $data; } @@ -656,7 +656,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateRelationshipAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsUpdateRelationshipAttribute']); return $data; } @@ -687,7 +687,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateIpAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsCreateIpAttribute']); return $data; } @@ -720,9 +720,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateIpAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateIpAttribute']['required']); - $this->assertEquals('127.0.0.1', $attribute['body']['data']['databasesUpdateIpAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['collectionsUpdateIpAttribute']); + $this->assertFalse($attribute['body']['data']['collectionsUpdateIpAttribute']['required']); + $this->assertEquals('127.0.0.1', $attribute['body']['data']['collectionsUpdateIpAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -754,7 +754,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesCreateUrlAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsCreateUrlAttribute']); return $data; } @@ -787,9 +787,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesUpdateUrlAttribute']); - $this->assertFalse($attribute['body']['data']['databasesUpdateUrlAttribute']['required']); - $this->assertEquals('https://cloud.appwrite.io', $attribute['body']['data']['databasesUpdateUrlAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['collectionsUpdateUrlAttribute']); + $this->assertFalse($attribute['body']['data']['collectionsUpdateUrlAttribute']['required']); + $this->assertEquals('https://cloud.appwrite.io', $attribute['body']['data']['collectionsUpdateUrlAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); } @@ -823,12 +823,12 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $index['body']); $this->assertIsArray($index['body']['data']); - $this->assertIsArray($index['body']['data']['databasesCreateIndex']); + $this->assertIsArray($index['body']['data']['collectionsCreateIndex']); return [ 'database' => $data['database'], 'collection' => $data['collection'], - 'index' => $index['body']['data']['databasesCreateIndex'], + 'index' => $index['body']['data']['collectionsCreateIndex'], ]; } @@ -874,7 +874,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['databasesCreateDocument']; + $document = $document['body']['data']['collectionsCreateDocument']; $this->assertIsArray($document); return [ @@ -1042,7 +1042,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attributes['body']); $this->assertIsArray($attributes['body']['data']); - $this->assertIsArray($attributes['body']['data']['databasesListAttributes']); + $this->assertIsArray($attributes['body']['data']['collectionsListAttributes']); } /** @@ -1069,7 +1069,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['databasesGetAttribute']); + $this->assertIsArray($attribute['body']['data']['collectionsGetAttribute']); } /** @@ -1095,7 +1095,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $indices['body']); $this->assertIsArray($indices['body']['data']); - $this->assertIsArray($indices['body']['data']['databasesListIndexes']); + $this->assertIsArray($indices['body']['data']['collectionsListIndexes']); } /** @@ -1122,7 +1122,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $index['body']); $this->assertIsArray($index['body']['data']); - $this->assertIsArray($index['body']['data']['databasesGetIndex']); + $this->assertIsArray($index['body']['data']['collectionsGetIndex']); } /** @@ -1148,7 +1148,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $documents['body']); $this->assertIsArray($documents['body']['data']); - $this->assertIsArray($documents['body']['data']['databasesListDocuments']); + $this->assertIsArray($documents['body']['data']['collectionsListDocuments']); } /** @@ -1175,7 +1175,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $this->assertIsArray($document['body']['data']['databasesGetDocument']); + $this->assertIsArray($document['body']['data']['collectionsGetDocument']); } // /** @@ -1306,7 +1306,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['databasesUpdateDocument']; + $document = $document['body']['data']['collectionsUpdateDocument']; $this->assertIsArray($document); $this->assertStringContainsString('New Document Name', $document['data']); } From a067b77e90d737dfb2cc9644052e18b6cdfb5b55 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 9 May 2025 20:04:02 +0530 Subject: [PATCH 111/343] update: model; add|update: graphql tests [wip]. --- .../Http/Databases/Tables/Create.php | 2 +- .../Http/Databases/Tables/Update.php | 4 +- src/Appwrite/Utopia/Response/Model/Table.php | 8 +- .../Databases/Tables/DatabasesBase.php | 46 +- .../Tables/DatabasesConsoleClientTest.php | 4 +- .../Tables/DatabasesCustomClientTest.php | 28 +- .../Tables/DatabasesCustomServerTest.php | 24 +- .../Tables/DatabasesPermissionsGuestTest.php | 4 +- .../Tables/DatabasesPermissionsMemberTest.php | 6 +- tests/e2e/Services/GraphQL/Base.php | 450 ++++- .../GraphQL/{ => Collections}/AbuseTest.php | 5 +- .../GraphQL/{ => Collections}/AuthTest.php | 3 +- .../{ => Collections}/DatabaseClientTest.php | 3 +- .../{ => Collections}/DatabaseServerTest.php | 3 +- .../e2e/Services/GraphQL/Tables/AbuseTest.php | 185 +++ .../e2e/Services/GraphQL/Tables/AuthTest.php | 253 +++ .../GraphQL/Tables/DatabaseClientTest.php | 306 ++++ .../GraphQL/Tables/DatabaseServerTest.php | 1467 +++++++++++++++++ 18 files changed, 2732 insertions(+), 69 deletions(-) rename tests/e2e/Services/GraphQL/{ => Collections}/AbuseTest.php (97%) rename tests/e2e/Services/GraphQL/{ => Collections}/AuthTest.php (99%) rename tests/e2e/Services/GraphQL/{ => Collections}/DatabaseClientTest.php (99%) rename tests/e2e/Services/GraphQL/{ => Collections}/DatabaseServerTest.php (99%) create mode 100644 tests/e2e/Services/GraphQL/Tables/AbuseTest.php create mode 100644 tests/e2e/Services/GraphQL/Tables/AuthTest.php create mode 100644 tests/e2e/Services/GraphQL/Tables/DatabaseClientTest.php create mode 100644 tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php index 0ca46f66e0..fcd52d4854 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php @@ -62,7 +62,7 @@ class Create extends CollectionCreate ->param('tableId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Table name. Max length: 128 chars.') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) - ->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or table level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->param('rowSecurity', false, new Boolean(true), 'Enables configuring permissions for individual rows. A user needs one of row or table level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('enabled', true, new Boolean(), 'Is table enabled? When set to \'disabled\', users cannot access the table but Server SDKs with and API key can still read and write to the table. No data is lost when this is toggled.', true) ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php index 85024e4008..70ac9d7b7c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php @@ -61,8 +61,8 @@ class Update extends CollectionUpdate ->param('tableId', '', new UID(), 'Table ID.') ->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.') ->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('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) - ->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', true) + ->param('rowSecurity', false, new Boolean(true), 'Enables configuring permissions for individual rows. A user needs one of row or table level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->param('enabled', true, new Boolean(), 'Is table enabled? When set to \'disabled\', users cannot access the table but Server SDKs with and API key can still read and write to the table. No data is lost when this is toggled.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') diff --git a/src/Appwrite/Utopia/Response/Model/Table.php b/src/Appwrite/Utopia/Response/Model/Table.php index 1b890d9e60..722edcd4cf 100644 --- a/src/Appwrite/Utopia/Response/Model/Table.php +++ b/src/Appwrite/Utopia/Response/Model/Table.php @@ -54,9 +54,9 @@ class Table extends Model 'default' => true, 'example' => false, ]) - ->addRule('documentSecurity', [ + ->addRule('rowSecurity', [ 'type' => self::TYPE_BOOLEAN, - 'description' => 'Whether document-level permissions are enabled. [Learn more about permissions](https://appwrite.io/docs/permissions).', + 'description' => 'Whether row-level permissions are enabled. [Learn more about permissions](https://appwrite.io/docs/permissions).', 'default' => '', 'example' => true, ]) @@ -125,9 +125,13 @@ class Table extends Model $document->setAttribute('relatedTable', $related); } + $documentSecurity = $document->getAttribute('documentSecurity'); + $document->setAttribute('rowSecurity', $documentSecurity); + // remove anyways as they are already copied above. $document ->removeAttribute('attributes') + ->removeAttribute('documentSecurity') ->removeAttribute('relatedCollection'); return $document; diff --git a/tests/e2e/Services/Databases/Tables/DatabasesBase.php b/tests/e2e/Services/Databases/Tables/DatabasesBase.php index 5532bbac46..ef35d3c962 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesBase.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesBase.php @@ -52,7 +52,7 @@ trait DatabasesBase ]), [ 'tableId' => ID::unique(), 'name' => 'Movies', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), ], @@ -68,7 +68,7 @@ trait DatabasesBase ]), [ 'tableId' => ID::unique(), 'name' => 'Actors', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), ], @@ -136,7 +136,7 @@ trait DatabasesBase ]), [ 'name' => 'Movies', 'enabled' => false, - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -182,7 +182,7 @@ trait DatabasesBase ]), [ 'name' => 'Movies', 'enabled' => true, - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -418,7 +418,7 @@ trait DatabasesBase ]), [ 'tableId' => ID::unique(), 'name' => 'patch', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), ], @@ -489,7 +489,7 @@ trait DatabasesBase ]), [ 'tableId' => ID::unique(), 'name' => 'Players', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), ], @@ -542,7 +542,7 @@ trait DatabasesBase 'tableId' => ID::unique(), 'name' => 'Response Models', // 'permissions' missing on purpose to make sure it's optional - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $table['headers']['status-code']); @@ -2479,7 +2479,7 @@ trait DatabasesBase Permission::create(Role::any()), Permission::read(Role::any()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $table['headers']['status-code']); @@ -3146,7 +3146,7 @@ trait DatabasesBase ]), [ 'tableId' => ID::unique(), 'name' => 'enforceCollectionAndDocumentPermissions', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::read(Role::user($user)), Permission::create(Role::user($user)), @@ -3157,7 +3157,7 @@ trait DatabasesBase $this->assertEquals(201, $table['headers']['status-code']); $this->assertEquals($table['body']['name'], 'enforceCollectionAndDocumentPermissions'); - $this->assertEquals($table['body']['documentSecurity'], true); + $this->assertEquals($table['body']['rowSecurity'], true); $tableId = $table['body']['$id']; @@ -3349,7 +3349,7 @@ trait DatabasesBase $this->assertEquals(201, $table['headers']['status-code']); $this->assertEquals($table['body']['name'], 'enforceCollectionPermissions'); - $this->assertEquals($table['body']['documentSecurity'], false); + $this->assertEquals($table['body']['rowSecurity'], false); $tableId = $table['body']['$id']; @@ -3500,7 +3500,7 @@ trait DatabasesBase 'x-appwrite-key' => $this->getProject()['apiKey'] ], [ 'name' => $table['body']['name'], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $rowsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', [ @@ -3698,7 +3698,7 @@ trait DatabasesBase Permission::update(Role::user(ID::custom($this->getUser()['$id']))), Permission::delete(Role::user(ID::custom($this->getUser()['$id']))), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $movies['headers']['status-code']); @@ -3854,7 +3854,7 @@ trait DatabasesBase Permission::delete(Role::user($this->getUser()['$id'])), Permission::create(Role::user($this->getUser()['$id'])), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $person['headers']['status-code']); @@ -3871,7 +3871,7 @@ trait DatabasesBase Permission::update(Role::user($this->getUser()['$id'])), Permission::create(Role::user($this->getUser()['$id'])), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $library['headers']['status-code']); @@ -4238,7 +4238,7 @@ trait DatabasesBase ]), [ 'tableId' => ID::unique(), 'name' => 'Albums', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), @@ -4264,7 +4264,7 @@ trait DatabasesBase ]), [ 'tableId' => ID::unique(), 'name' => 'Artists', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), @@ -4382,7 +4382,7 @@ trait DatabasesBase ]), [ 'tableId' => ID::unique(), 'name' => 'Sports', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), @@ -4408,7 +4408,7 @@ trait DatabasesBase ]), [ 'tableId' => ID::unique(), 'name' => 'Players', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), @@ -4642,7 +4642,7 @@ trait DatabasesBase ]), [ 'tableId' => ID::unique(), 'name' => 'USA Presidents', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), ], @@ -4765,7 +4765,7 @@ trait DatabasesBase ]), [ 'tableId' => ID::unique(), 'name' => 'Collection1', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), @@ -4779,7 +4779,7 @@ trait DatabasesBase ]), [ 'tableId' => ID::unique(), 'name' => 'Collection2', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), @@ -4861,7 +4861,7 @@ trait DatabasesBase ]), [ 'tableId' => ID::unique(), 'name' => 'Slow Queries', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), ], diff --git a/tests/e2e/Services/Databases/Tables/DatabasesConsoleClientTest.php b/tests/e2e/Services/Databases/Tables/DatabasesConsoleClientTest.php index 48707d444b..087ece167f 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesConsoleClientTest.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesConsoleClientTest.php @@ -46,7 +46,7 @@ class DatabasesConsoleClientTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $movies['headers']['status-code']); @@ -77,7 +77,7 @@ class DatabasesConsoleClientTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); /** diff --git a/tests/e2e/Services/Databases/Tables/DatabasesCustomClientTest.php b/tests/e2e/Services/Databases/Tables/DatabasesCustomClientTest.php index ca8ae08ca0..6893588934 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesCustomClientTest.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesCustomClientTest.php @@ -42,7 +42,7 @@ class DatabasesCustomClientTest extends Scope ]), [ 'tableId' => ID::unique(), 'name' => 'Movies', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::write(Role::user($this->getUser()['$id'])), ], @@ -141,7 +141,7 @@ class DatabasesCustomClientTest extends Scope 'tableId' => ID::custom('permissionCheck'), 'name' => 'permissionCheck', 'permissions' => [], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -249,7 +249,7 @@ class DatabasesCustomClientTest extends Scope ]), [ 'tableId' => ID::unique(), 'name' => 'level1', - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), @@ -266,7 +266,7 @@ class DatabasesCustomClientTest extends Scope ]), [ 'tableId' => ID::unique(), 'name' => 'level2', - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), @@ -337,7 +337,7 @@ class DatabasesCustomClientTest extends Scope ]), [ 'tableId' => ID::unique(), 'name' => 'c1', - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), @@ -353,7 +353,7 @@ class DatabasesCustomClientTest extends Scope ]), [ 'tableId' => ID::unique(), 'name' => 'c2', - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), @@ -497,7 +497,7 @@ class DatabasesCustomClientTest extends Scope ]), [ 'tableId' => ID::custom('collection1'), 'name' => ID::custom('collection1'), - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::create(Role::user($userId)), Permission::read(Role::user($userId)), @@ -513,7 +513,7 @@ class DatabasesCustomClientTest extends Scope ]), [ 'tableId' => ID::custom('collection2'), 'name' => ID::custom('collection2'), - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::read(Role::user($userId)), ] @@ -526,7 +526,7 @@ class DatabasesCustomClientTest extends Scope ]), [ 'tableId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::create(Role::user($userId)), Permission::read(Role::user($userId)), @@ -541,7 +541,7 @@ class DatabasesCustomClientTest extends Scope ]), [ 'tableId' => ID::custom('collection4'), 'name' => ID::custom('collection4'), - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::read(Role::user($userId)), ] @@ -554,7 +554,7 @@ class DatabasesCustomClientTest extends Scope ]), [ 'tableId' => ID::custom('collection5'), 'name' => ID::custom('collection5'), - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::create(Role::user($userId)), Permission::read(Role::user($userId)), @@ -741,7 +741,7 @@ class DatabasesCustomClientTest extends Scope ]), [ 'tableId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::create(Role::user($userId)), Permission::read(Role::user($userId)), @@ -816,7 +816,7 @@ class DatabasesCustomClientTest extends Scope ]), [ 'tableId' => ID::custom('collection3'), 'name' => ID::custom('collection3'), - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::create(Role::user($userId)), Permission::read(Role::user($userId)), @@ -832,7 +832,7 @@ class DatabasesCustomClientTest extends Scope ]), [ 'tableId' => ID::custom('collection2'), 'name' => ID::custom('collection2'), - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::create(Role::user($userId)), Permission::update(Role::user($userId)), diff --git a/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php index dca8a16363..a92f1decf1 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php @@ -365,7 +365,7 @@ class DatabasesCustomServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $test2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ @@ -381,7 +381,7 @@ class DatabasesCustomServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $tables = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables', array_merge([ @@ -586,7 +586,7 @@ class DatabasesCustomServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(409, $response['headers']['status-code']); @@ -665,7 +665,7 @@ class DatabasesCustomServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $actors['headers']['status-code']); @@ -775,7 +775,7 @@ class DatabasesCustomServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $actors['headers']['status-code']); @@ -1058,7 +1058,7 @@ class DatabasesCustomServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $table['headers']['status-code']); @@ -1251,7 +1251,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'tableId' => ID::unique(), 'name' => 'Collection1', - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [], ]); @@ -1262,7 +1262,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'tableId' => ID::unique(), 'name' => 'Collection2', - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [], ]); @@ -1326,7 +1326,7 @@ class DatabasesCustomServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $table['headers']['status-code']); @@ -1392,7 +1392,7 @@ class DatabasesCustomServerTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $table['headers']['status-code']); @@ -3632,7 +3632,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'tableId' => 'collection1', 'name' => 'level1', - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), @@ -3648,7 +3648,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'tableId' => 'collection2', 'name' => 'level2', - 'documentSecurity' => false, + 'rowSecurity' => false, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), diff --git a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsGuestTest.php index fa04ba04aa..fde6041219 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsGuestTest.php @@ -45,7 +45,7 @@ class DatabasesPermissionsGuestTest extends Scope 'tableId' => ID::unique(), 'name' => 'Movies', 'permissions' => [], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $publicCollection = ['id' => $publicMovies['body']['$id']]; @@ -246,7 +246,7 @@ class DatabasesPermissionsGuestTest extends Scope 'permissions' => [ Permission::create(Role::any()), ], - 'documentSecurity' => true + 'rowSecurity' => true ]); $moviesId = $movies['body']['$id']; diff --git a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php index 8da1d9e1ed..7b0e9d8a64 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php @@ -133,7 +133,7 @@ class DatabasesPermissionsMemberTest extends Scope Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $public['headers']['status-code']); $this->collections = ['public' => $public['body']['$id']]; @@ -154,7 +154,7 @@ class DatabasesPermissionsMemberTest extends Scope Permission::update(Role::users()), Permission::delete(Role::users()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $private['headers']['status-code']); $this->collections['private'] = $private['body']['$id']; @@ -170,7 +170,7 @@ class DatabasesPermissionsMemberTest extends Scope 'tableId' => ID::unique(), 'name' => 'Document Only Movies', 'permissions' => [], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $private['headers']['status-code']); $this->collections['doconly'] = $doconly['body']['$id']; diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index f7ee14f7e1..65154e2f93 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -13,12 +13,21 @@ trait Base public static string $GET_DATABASE = 'get_database'; public static string $UPDATE_DATABASE = 'update_database'; public static string $DELETE_DATABASE = 'delete_database'; + // Collections public static string $CREATE_COLLECTION = 'create_collection'; public static string $GET_COLLECTION = 'get_collection'; public static string $GET_COLLECTIONS = 'list_collections'; public static string $UPDATE_COLLECTION = 'update_collection'; public static string $DELETE_COLLECTION = 'delete_collection'; + + // Tables + public static string $CREATE_TABLE = 'create_table'; + public static string $GET_TABLE = 'get_table'; + public static string $GET_TABLES = 'list_tables'; + public static string $UPDATE_TABLE = 'update_tables'; + public static string $DELETE_TABLE = 'delete_tables'; + // Attributes public static string $CREATE_STRING_ATTRIBUTE = 'create_string_attribute'; public static string $CREATE_INTEGER_ATTRIBUTE = 'create_integer_attribute'; @@ -45,11 +54,46 @@ trait Base public static string $GET_ATTRIBUTES = 'get_attributes'; public static string $GET_ATTRIBUTE = 'get_attribute'; public static string $DELETE_ATTRIBUTE = 'delete_attribute'; - // Indexes + + // Columns + public static string $CREATE_STRING_COLUMN = 'create_string_column'; + public static string $CREATE_INTEGER_COLUMN = 'create_integer_column'; + public static string $CREATE_FLOAT_COLUMN = 'create_float_column'; + public static string $CREATE_BOOLEAN_COLUMN = 'create_boolean_column'; + public static string $CREATE_URL_COLUMN = 'create_url_column'; + public static string $CREATE_EMAIL_COLUMN = 'create_email_column'; + public static string $CREATE_IP_COLUMN = 'create_ip_column'; + public static string $CREATE_ENUM_COLUMN = 'create_enum_column'; + public static string $CREATE_DATETIME_COLUMN = 'create_datetime_column'; + + public static string $CREATE_RELATIONSHIP_COLUMN = 'create_relationship_column'; + public static string $UPDATE_STRING_COLUMN = 'update_string_column'; + public static string $UPDATE_INTEGER_COLUMN = 'update_integer_column'; + public static string $UPDATE_FLOAT_COLUMN = 'update_float_column'; + public static string $UPDATE_BOOLEAN_COLUMN = 'update_boolean_column'; + public static string $UPDATE_URL_COLUMN = 'update_url_column'; + public static string $UPDATE_EMAIL_COLUMN = 'update_email_column'; + public static string $UPDATE_IP_COLUMN = 'update_ip_column'; + public static string $UPDATE_ENUM_COLUMN = 'update_enum_column'; + public static string $UPDATE_DATETIME_COLUMN = 'update_datetime_column'; + + public static string $UPDATE_RELATIONSHIP_COLUMN = 'update_relationship_column'; + public static string $GET_COLUMNS = 'get_columns'; + public static string $GET_COLUMN = 'get_column'; + public static string $DELETE_COLUMN = 'delete_column'; + + // Collection Indexes public static string $CREATE_INDEX = 'create_index'; public static string $GET_INDEXES = 'get_indexes'; public static string $GET_INDEX = 'get_index'; public static string $DELETE_INDEX = 'delete_index'; + + // Column Indexes + public static string $CREATE_COLUMN_INDEX = 'create_index'; + public static string $GET_COLUMN_INDEXES = 'get_indexes'; + public static string $GET_COLUMN_INDEX = 'get_index'; + public static string $DELETE_COLUMN_INDEX = 'delete_index'; + // Documents public static string $CREATE_DOCUMENT = 'create_document_rest'; public static string $GET_DOCUMENTS = 'list_documents'; @@ -57,6 +101,13 @@ trait Base public static string $UPDATE_DOCUMENT = 'update_document'; public static string $DELETE_DOCUMENT = 'delete_document'; + // Rows + public static string $CREATE_ROW = 'create_row_rest'; + public static string $GET_ROWS = 'list_rows'; + public static string $GET_ROW = 'get_row'; + public static string $UPDATE_ROW = 'update_row'; + public static string $DELETE_ROW = 'delete_row'; + // Custom Entities public static string $CREATE_CUSTOM_ENTITY = 'create_custom_entity'; public static string $GET_CUSTOM_ENTITIES = 'get_custom_entities'; @@ -257,7 +308,7 @@ trait Base // Complex queries public static string $COMPLEX_QUERY = 'complex_query'; - // Fragments + // Attribute Fragments public static string $FRAGMENT_ATTRIBUTES = ' fragment attributeProperties on Attributes { ... on AttributeString { @@ -332,6 +383,81 @@ trait Base } '; + // Column Fragments + public static string $FRAGMENT_COLUMNS = ' + fragment columnProperties on Columns { + ... on ColumnString { + key + required + array + status + default + size + } + ... on ColumnInteger { + key + required + array + status + intDefault: default + intMin: min + intMax: max + } + ... on ColumnFloat { + key + required + array + status + floatDefault: default + floatMin: min + floatMax: max + } + ... on ColumnBoolean { + key + required + array + status + boolDefault: default + } + ... on ColumnUrl { + key + required + array + status + default + } + ... on ColumnEmail { + key + required + array + status + default + } + ... on ColumnIp { + key + required + array + status + default + } + ... on ColumnEnum { + key + required + array + status + default + elements + } + ... on ColumnDatetime { + key + required + array + status + default + } + } + '; + public static string $FRAGMENT_HASH_OPTIONS = ' fragment options on HashOptions { ... on AlgoArgon2 { @@ -438,6 +564,51 @@ trait Base status } }'; + case self::$GET_TABLE: + return 'query getTable($databaseId: String!, $tableId: String!) { + databasesGetTable(databaseId: $databaseId, tableId: $tableId) { + _id + _permissions + rowSecurity + name + } + }'; + case self::$GET_TABLES: + return 'query listTables($databaseId: String!) { + databasesListTables(databaseId: $databaseId) { + total + tables { + _id + _permissions + rowSecurity + name + } + } + }'; + case self::$CREATE_TABLE: + return 'mutation createTable($databaseId: String!, $tableId: String!, $name: String!, $rowSecurity: Boolean!, $permissions: [String!]!) { + databasesCreateTable(databaseId: $databaseId, tableId: $tableId, name: $name, rowSecurity: $rowSecurity, permissions: $permissions) { + _id + _permissions + rowSecurity + name + } + }'; + case self::$UPDATE_TABLE: + return 'mutation updateTable($databaseId: String!, $tableId: String!, $name: String!, $rowSecurity: Boolean!, $permissions: [String!], $enabled: Boolean) { + databasesUpdateTable(databaseId: $databaseId, tableId: $tableId, name: $name, rowSecurity: $rowSecurity, permissions: $permissions, enabled: $enabled) { + _id + _permissions + rowSecurity + name + } + }'; + case self::$DELETE_TABLE: + return 'mutation deleteTable($databaseId: String!, $tableId: String!) { + databasesDeleteTable(databaseId: $databaseId, tableId: $tableId) { + status + } + }'; case self::$CREATE_STRING_ATTRIBUTE: return 'mutation createStringAttribute($databaseId: String!, $collectionId: String!, $key: String!, $size: Int!, $required: Boolean!, $default: String, $array: Boolean){ collectionsCreateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, size: $size, required: $required, default: $default, array: $array) { @@ -614,6 +785,182 @@ trait Base onDelete } }'; + case self::$CREATE_STRING_COLUMN: + return 'mutation createStringColumn($databaseId: String!, $tableId: String!, $key: String!, $size: Int!, $required: Boolean!, $default: String, $array: Boolean){ + tablesCreateStringColumn(databaseId: $databaseId, tableId: $tableId, key: $key, size: $size, required: $required, default: $default, array: $array) { + key + required + default + array + } + }'; + case self::$CREATE_INTEGER_COLUMN: + return 'mutation createIntegerColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $min: Int, $max: Int, $default: Int, $array: Boolean){ + tablesCreateIntegerColumn(databaseId: $databaseId, tableId: $tableId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { + key + required + min + max + default + array + } + }'; + case self::$CREATE_FLOAT_COLUMN: + return 'mutation createFloatColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $min: Float, $max: Float, $default: Float, $array: Boolean){ + tablesCreateFloatColumn(databaseId: $databaseId, tableId: $tableId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { + key + required + min + max + default + array + } + }'; + case self::$CREATE_BOOLEAN_COLUMN: + return 'mutation createBooleanColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: Boolean, $array: Boolean){ + tablesCreateBooleanColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { + key + required + default + array + } + }'; + case self::$CREATE_URL_COLUMN: + return 'mutation createUrlColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ + tablesCreateUrlColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { + key + required + default + array + } + }'; + case self::$CREATE_EMAIL_COLUMN: + return 'mutation createEmailColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ + tablesCreateEmailColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { + key + required + default + array + } + }'; + case self::$CREATE_IP_COLUMN: + return 'mutation createIpColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ + tablesCreateIpColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { + key + required + default + array + } + }'; + case self::$CREATE_ENUM_COLUMN: + return 'mutation createEnumColumn($databaseId: String!, $tableId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String, $array: Boolean){ + tablesCreateEnumColumn(databaseId: $databaseId, tableId: $tableId, key: $key, elements: $elements, required: $required, default: $default, array: $array) { + key + elements + required + default + array + } + }'; + case self::$CREATE_DATETIME_COLUMN: + return 'mutation createDatetimeColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ + tablesCreateDatetimeColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { + key + required + default + array + } + }'; + case self::$CREATE_RELATIONSHIP_COLUMN: + return 'mutation createRelationshipColumn($databaseId: String!, $tableId: String!, $relatedTableId: String!, $type: String!, $twoWay: Boolean, $key: String, $twoWayKey: String, $onDelete: String){ + tablesCreateRelationshipColumn(databaseId: $databaseId, tableId: $tableId, relatedTableId: $relatedTableId, type: $type, twoWay: $twoWay, key: $key, twoWayKey: $twoWayKey, onDelete: $onDelete) { + relatedTable + relationType + twoWay + key + twoWayKey + onDelete + } + }'; + case self::$UPDATE_STRING_COLUMN: + return 'mutation updateStringColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ + tablesUpdateStringColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { + required + default + } + }'; + case self::$UPDATE_INTEGER_COLUMN: + return 'mutation updateIntegerColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $min: Int!, $max: Int!, $default: Int){ + tablesUpdateIntegerColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, min: $min, max: $max, default: $default) { + required + min + max + default + } + }'; + case self::$UPDATE_FLOAT_COLUMN: + return 'mutation updateFloatColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $min: Float!, $max: Float!, $default: Float){ + tablesUpdateFloatColumn(databaseId: $databaseId, tableId: $tableId, key: $key, min: $min, max: $max, required: $required, default: $default) { + required + min + max + default + } + }'; + case self::$UPDATE_BOOLEAN_COLUMN: + return 'mutation updateBooleanColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: Boolean){ + tablesUpdateBooleanColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { + required + default + } + }'; + case self::$UPDATE_URL_COLUMN: + return 'mutation updateUrlColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ + tablesUpdateUrlColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { + required + default + } + }'; + case self::$UPDATE_EMAIL_COLUMN: + return 'mutation updateEmailColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ + tablesUpdateEmailColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { + required + default + } + }'; + case self::$UPDATE_IP_COLUMN: + return 'mutation updateIpColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ + tablesUpdateIpColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { + required + default + } + }'; + case self::$UPDATE_ENUM_COLUMN: + return 'mutation updateEnumColumn($databaseId: String!, $tableId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String){ + tablesUpdateEnumColumn(databaseId: $databaseId, tableId: $tableId, key: $key, elements: $elements, required: $required, default: $default) { + elements + required + default + } + }'; + case self::$UPDATE_DATETIME_COLUMN: + return 'mutation updateDatetimeColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){ + tablesUpdateDatetimeColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) { + required + default + } + }'; + case self::$UPDATE_RELATIONSHIP_COLUMN: + return 'mutation updateRelationshipColumn($databaseId: String!, $tableId: String!, $key: String!, $onDelete: String){ + tablesUpdateRelationshipColumn(databaseId: $databaseId, tableId: $tableId, key: $key, onDelete: $onDelete) { + relatedTable + relationType + twoWay + key + twoWayKey + onDelete + } + }'; case self::$CREATE_INDEX: return 'mutation createIndex($databaseId: String!, $collectionId: String!, $key: String!, $type: String!, $attributes: [String!]!, $orders: [String!]){ collectionsCreateIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key, type: $type, attributes: $attributes, orders: $orders) { @@ -647,6 +994,39 @@ trait Base status } }'; + case self::$CREATE_COLUMN_INDEX: + return 'mutation createIndex($databaseId: String!, $tableId: String!, $key: String!, $type: String!, $attributes: [String!]!, $orders: [String!]){ + tablesCreateIndex(databaseId: $databaseId, tableId: $tableId, key: $key, type: $type, attributes: $attributes, orders: $orders) { + key + type + status + } + }'; + case self::$GET_COLUMN_INDEXES: + return 'query listIndexes($databaseId: String!, $tableId: String!) { + tablesListIndexes(databaseId: $databaseId, tableId: $tableId) { + total + indexes { + key + type + status + } + } + }'; + case self::$GET_COLUMN_INDEX: + return 'query getIndex($databaseId: String!, $tableId: String!, $key: String!) { + tablesGetIndex(databaseId: $databaseId, tableId: $tableId, key: $key) { + key + type + status + } + }'; + case self::$DELETE_COLUMN_INDEX: + return 'mutation deleteIndex($databaseId: String!, $tableId: String!, $key: String!) { + tablesDeleteIndex(databaseId: $databaseId, tableId: $tableId, key: $key) { + status + } + }'; case self::$GET_ATTRIBUTES: return 'query listAttributes($databaseId: String!, $collectionId: String!) { collectionsListAttributes(databaseId: $databaseId, collectionId: $collectionId) { @@ -668,6 +1048,28 @@ trait Base status } }'; + case self::$GET_COLUMNS: + return 'query listColumns($databaseId: String!, $tableId: String!) { + tablesListColumns(databaseId: $databaseId, tableId: $tableId) { + total + columns { + ...columnProperties + } + } + }' . PHP_EOL . self::$FRAGMENT_COLUMNS; + case self::$GET_COLUMN: + return 'query getColumn($databaseId: String!, $tableId: String!, $key: String!) { + tablesGetColumn(databaseId: $databaseId, tableId: $tableId, key: $key) { + ...columnProperties + } + }' . PHP_EOL . self::$FRAGMENT_COLUMNS; + case self::$DELETE_COLUMN: + return 'mutation deleteColumn($databaseId: String!, $tableId: String!, $key: String!) { + tablesDeleteColumn(databaseId: $databaseId, tableId: $tableId, key: $key) { + status + } + }'; + case self::$GET_DOCUMENT: return 'query getDocument($databaseId: String!, $collectionId: String!, $documentId: String!) { collectionsGetDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { @@ -697,6 +1099,35 @@ trait Base _permissions } }'; + case self::$GET_ROW: + return 'query getRow($databaseId: String!, $tableId: String!, $rowId: String!) { + tablesGetRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId) { + _id + _tableId + _permissions + data + } + }'; + case self::$GET_ROWS: + return 'query listRows($databaseId: String!, $tableId: String!) { + tablesListRows(databaseId: $databaseId, tableId: $tableId) { + total + rows { + _id + _tableId + _permissions + data + } + } + }'; + case self::$CREATE_ROW: + return 'mutation createRow($databaseId: String!, $tableId: String!, $rowId: String!, $data: Json!, $permissions: [String!]) { + tablesCreateRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId, data: $data, permissions: $permissions) { + _id + _tableId + _permissions + } + }'; case self::$CREATE_CUSTOM_ENTITY: return 'mutation createActor($name: String!, $age: Int!, $alive: Boolean!, $salary: Float, $email: String!, $role: String!, $dob: String!, $ip: String, $url: String){ actorsCreate(name: $name, age: $age, alive: $alive, salary: $salary, email: $email, role: $role, dob: $dob, ip: $ip, url: $url) { @@ -770,7 +1201,20 @@ trait Base status } }'; - + case self::$UPDATE_ROW: + return 'mutation updateRow($databaseId: String!, $tableId: String!, $rowId: String!, $data: Json!, $permissions: [String!]) { + tablesUpdateRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId, data: $data, permissions: $permissions) { + _id + _tableId + data + } + }'; + case self::$DELETE_ROW: + return 'mutation deleteRow($databaseId: String!, $tableId: String!, $rowId: String!) { + tablesDeleteRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId) { + status + } + }'; case self::$GET_USER: return 'query getUser($userId : String!) { usersGet(userId : $userId) { diff --git a/tests/e2e/Services/GraphQL/AbuseTest.php b/tests/e2e/Services/GraphQL/Collections/AbuseTest.php similarity index 97% rename from tests/e2e/Services/GraphQL/AbuseTest.php rename to tests/e2e/Services/GraphQL/Collections/AbuseTest.php index ea97492c2b..a45bebd714 100644 --- a/tests/e2e/Services/GraphQL/AbuseTest.php +++ b/tests/e2e/Services/GraphQL/Collections/AbuseTest.php @@ -1,11 +1,12 @@ assertEquals('Too many queries.', $response['body']['message']); } - private function createCollection() + private function createCollection(): array { $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_DATABASE); diff --git a/tests/e2e/Services/GraphQL/AuthTest.php b/tests/e2e/Services/GraphQL/Collections/AuthTest.php similarity index 99% rename from tests/e2e/Services/GraphQL/AuthTest.php rename to tests/e2e/Services/GraphQL/Collections/AuthTest.php index db56537999..288987a719 100644 --- a/tests/e2e/Services/GraphQL/AuthTest.php +++ b/tests/e2e/Services/GraphQL/Collections/AuthTest.php @@ -1,11 +1,12 @@ markTestSkipped('Abuse is not enabled.'); + } + } + + public function testRateLimitEnforced() + { + $data = $this->createCollection(); + $databaseId = $data['databaseId']; + $tableId = $data['tableId']; + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_ROW); + $max = 120; + + for ($i = 0; $i <= $max + 1; $i++) { + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'rowId' => ID::unique(), + 'data' => [ + 'name' => 'John Doe', + ], + ], + ]; + + $response = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $gqlPayload); + + if ($i < $max) { + $this->assertArrayNotHasKey('errors', $response['body']); + } else { + $this->assertArrayHasKey('errors', $response['body']); + } + } + } + + public function testComplexQueryBlocked() + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$COMPLEX_QUERY); + $graphQLPayload = [ + 'query' => $query, + 'variables' => [ + 'userId' => 'user', + 'email' => 'user@appwrite.io', + 'password' => 'password', + 'databaseId' => 'database', + 'databaseName' => 'database', + 'tableId' => 'table', + 'collectionName' => 'table', + 'collectionPermissions' => [ + Permission::read(Role::users()), + Permission::create(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + 'rowSecurity' => false, + ], + ]; + + $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $graphQLPayload); + + $max = System::getEnv('_APP_GRAPHQL_MAX_QUERY_COMPLEXITY', 250); + + $this->assertEquals('Max query complexity should be ' . $max . ' but got 259.', $response['body']['errors'][0]['message']); + } + + public function testTooManyQueriesBlocked() + { + $projectId = $this->getProject()['$id']; + $maxQueries = System::getEnv('_APP_GRAPHQL_MAX_QUERIES', 10); + + $query = []; + for ($i = 0; $i <= $maxQueries + 1; $i++) { + $query[] = ['query' => $this->getQuery(self::$LIST_COUNTRIES)]; + } + + $response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $query); + + $this->assertEquals('Too many queries.', $response['body']['message']); + } + + private function createCollection(): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_DATABASE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => 'actors', + 'name' => 'AbuseDatabase', + ] + ]; + + $response = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $gqlPayload); + + $databaseId = $response['body']['data']['databasesCreate']['_id']; + + $query = $this->getQuery(self::$CREATE_TABLE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $databaseId, + 'tableId' => 'actors', + 'name' => 'Actors', + 'rowSecurity' => false, + 'permissions' => [ + Permission::read(Role::any()), + Permission::write(Role::any()), + ], + ] + ]; + + $response = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $gqlPayload); + + $tableId = $response['body']['data']['databasesCreateTable']['_id']; + + $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'key' => 'name', + 'size' => 256, + 'required' => true, + ] + ]; + + $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $gqlPayload); + + sleep(2); + + return [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + ]; + } +} diff --git a/tests/e2e/Services/GraphQL/Tables/AuthTest.php b/tests/e2e/Services/GraphQL/Tables/AuthTest.php new file mode 100644 index 0000000000..681607d599 --- /dev/null +++ b/tests/e2e/Services/GraphQL/Tables/AuthTest.php @@ -0,0 +1,253 @@ +getProject()['$id']; + $query = $this->getQuery(self::$CREATE_ACCOUNT); + + $email1 = 'test' . \rand() . '@test.com'; + $email2 = 'test' . \rand() . '@test.com'; + + // Create account 1 + $graphQLPayload = [ + 'query' => $query, + 'variables' => [ + 'userId' => ID::unique(), + 'name' => 'User Name', + 'email' => $email1, + 'password' => 'password', + ], + ]; + $this->account1 = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $graphQLPayload); + + // Create account 2 + $graphQLPayload['variables']['userId'] = ID::unique(); + $graphQLPayload['variables']['email'] = $email2; + + $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $graphQLPayload); + + // Create session 1 + $query = $this->getQuery(self::$CREATE_ACCOUNT_SESSION); + $graphQLPayload = [ + 'query' => $query, + 'variables' => [ + 'email' => $email1, + 'password' => 'password', + ] + ]; + $session1 = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $graphQLPayload); + + $this->token1 = $session1['cookies']['a_session_' . $projectId]; + + // Create session 2 + $graphQLPayload['variables']['email'] = $email2; + + $session2 = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $graphQLPayload); + + $this->token2 = $session2['cookies']['a_session_' . $projectId]; + + // Create database + $query = $this->getQuery(self::$CREATE_DATABASE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => ID::unique(), + 'name' => 'Actors', + ] + ]; + $this->database = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $gqlPayload); + + // Create table + $query = $this->getQuery(self::$CREATE_TABLE); + $userId = $this->account1['body']['data']['accountCreate']['_id']; + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], + 'tableId' => ID::unique(), + 'name' => 'Actors', + 'rowSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($userId)) + ] + ] + ]; + $this->table = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $gqlPayload); + + // Create string attribute + $query = $this->getQuery(self::$CREATE_STRING_COLUMN); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], + 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'key' => 'name', + 'size' => 256, + 'required' => true, + ] + ]; + $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $gqlPayload); + + sleep(1); + } + + public function testInvalidAuth() + { + $projectId = $this->getProject()['$id']; + + // Create row as account 1 + $query = $this->getQuery(self::$CREATE_ROW); + $userId = $this->account1['body']['data']['accountCreate']['_id']; + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], + 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'rowId' => ID::unique(), + 'data' => [ + 'name' => 'John Doe', + ], + 'permissions' => [ + Permission::read(Role::user($userId)), + Permission::update(Role::user($userId)), + Permission::delete(Role::user($userId)), + ] + ] + ]; + $row = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, + ], $gqlPayload); + + // Try to read as account 1 + $query = $this->getQuery(self::$GET_ROW); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], + 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'rowId' => $row['body']['data']['tablesCreateRow']['_id'], + ] + ]; + $row = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, + ], $gqlPayload); + + $this->assertIsArray($row['body']['data']['tablesGetRow']); + $this->assertArrayNotHasKey('errors', $row['body']); + + // Try to read as account 2 + $row = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'cookie' => 'a_session_' . $projectId . '=' . $this->token2, + ], $gqlPayload); + + $this->assertArrayHasKey('errors', $row['body']); + $this->assertEquals('Row with the requested ID could not be found.', $row['body']['errors'][0]['message']); + } + + public function testValidAuth() + { + $projectId = $this->getProject()['$id']; + + // Create row as account 1 + $query = $this->getQuery(self::$CREATE_ROW); + $userId = $this->account1['body']['data']['accountCreate']['_id']; + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], + 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'rowId' => ID::unique(), + 'data' => [ + 'name' => 'John Doe', + ], + 'permissions' => [ + Permission::read(Role::user($userId)), + Permission::update(Role::user($userId)), + Permission::delete(Role::user($userId)), + ], + ] + ]; + $row = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, + ], $gqlPayload); + + // Try to delete as account 1 + $query = $this->getQuery(self::$DELETE_ROW); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], + 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'rowId' => $row['body']['data']['tablesCreateRow']['_id'], + ] + ]; + $row = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, + ], $gqlPayload); + + $this->assertIsNotArray($row['body']); + $this->assertEquals(204, $row['headers']['status-code']); + } +} diff --git a/tests/e2e/Services/GraphQL/Tables/DatabaseClientTest.php b/tests/e2e/Services/GraphQL/Tables/DatabaseClientTest.php new file mode 100644 index 0000000000..3296f2d622 --- /dev/null +++ b/tests/e2e/Services/GraphQL/Tables/DatabaseClientTest.php @@ -0,0 +1,306 @@ +getProject()['$id']; + $query = $this->getQuery(self::$CREATE_DATABASE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => ID::unique(), + 'name' => 'Actors', + ] + ]; + + $database = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $gqlPayload); + + $this->assertIsArray($database['body']['data']); + $this->assertArrayNotHasKey('errors', $database['body']); + $database = $database['body']['data']['databasesCreate']; + $this->assertEquals('Actors', $database['name']); + + return $database; + } + + /** + * @depends testCreateDatabase + */ + public function testCreateTable($database): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_TABLE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $database['_id'], + 'tableId' => 'actors', + 'name' => 'Actors', + 'rowSecurity' => false, + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + ] + ]; + + $table = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $gqlPayload); + + $this->assertIsArray($table['body']['data']); + $this->assertArrayNotHasKey('errors', $table['body']); + $table = $table['body']['data']['databasesCreateTable']; + $this->assertEquals('Actors', $table['name']); + + return [ + 'table' => $table, + 'database' => $database, + ]; + } + + /** + * @depends testCreateTable + */ + public function testCreateStringColumn($data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_STRING_COLUMN); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'name', + 'size' => 256, + 'required' => true, + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['tablesCreateStringColumn']); + + return $data; + } + + /** + * @depends testCreateTable + */ + public function testCreateIntegerColumn($data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_INTEGER_COLUMN); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'age', + 'min' => 18, + 'max' => 150, + 'required' => true, + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['tablesCreateIntegerColumn']); + + return $data; + } + + /** + * @depends testCreateStringColumn + * @depends testCreateIntegerColumn + */ + public function testCreateRow($data): array + { + sleep(1); + + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_ROW); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => ID::unique(), + 'data' => [ + 'name' => 'John Doe', + 'age' => 35, + ], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ] + ]; + + $row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $row['body']); + $this->assertIsArray($row['body']['data']); + + $row = $row['body']['data']['tablesCreateRow']; + $this->assertIsArray($row); + + return [ + 'database' => $data['database'], + 'table' => $data['table'], + 'row' => $row, + ]; + } + + /** + * @depends testCreateTable + * @throws \Exception + */ + public function testGetRows($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$GET_ROWS); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + ] + ]; + + $rows = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $rows['body']); + $this->assertIsArray($rows['body']['data']); + $this->assertIsArray($rows['body']['data']['tablesListRows']); + } + + /** + * @depends testCreateRow + * @throws \Exception + */ + public function testGetDocument($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$GET_ROW); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => $data['row']['_id'], + ] + ]; + + $row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $row['body']); + $this->assertIsArray($row['body']['data']); + $this->assertIsArray($row['body']['data']['tablesGetRow']); + } + + /** + * @depends testCreateRow + * @throws \Exception + */ + public function testUpdateRow($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_ROW); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => $data['row']['_id'], + 'data' => [ + 'name' => 'New Row Name', + ], + ] + ]; + + $row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $row['body']); + $this->assertIsArray($row['body']['data']); + $row = $row['body']['data']['tablesUpdateRow']; + $this->assertIsArray($row); + + $this->assertStringContainsString('New Row Name', $row['data']); + } + + /** + * @depends testCreateRow + * @throws \Exception + */ + public function testDeleteRow($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$DELETE_ROW); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => $data['row']['_id'], + ] + ]; + + $row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsNotArray($row['body']); + $this->assertEquals(204, $row['headers']['status-code']); + } +} diff --git a/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php b/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php new file mode 100644 index 0000000000..d5980a4096 --- /dev/null +++ b/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php @@ -0,0 +1,1467 @@ +getProject()['$id']; + $query = $this->getQuery(self::$CREATE_DATABASE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => 'actors', + 'name' => 'Actors', + ] + ]; + + $database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsArray($database['body']['data']); + $this->assertArrayNotHasKey('errors', $database['body']); + $database = $database['body']['data']['databasesCreate']; + $this->assertEquals('Actors', $database['name']); + + return $database; + } + + /** + * @depends testCreateDatabase + */ + public function testCreateCollection($database): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_COLLECTION); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $database['_id'], + 'tableId' => 'actors', + 'name' => 'Actors', + 'rowSecurity' => false, + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + ] + ]; + + $table = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsArray($table['body']['data']); + $this->assertArrayNotHasKey('errors', $table['body']); + $table = $table['body']['data']['databasesCreateCollection']; + $this->assertEquals('Actors', $table['name']); + + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $database['_id'], + 'tableId' => 'movies', + 'name' => 'Movies', + 'rowSecurity' => false, + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + ] + ]; + + $table2 = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsArray($table2['body']['data']); + $this->assertArrayNotHasKey('errors', $table2['body']); + $table2 = $table2['body']['data']['databasesCreateCollection']; + $this->assertEquals('Movies', $table2['name']); + + return [ + 'database' => $database, + 'table' => $table, + 'collection2' => $table2, + ]; + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testCreateStringAttribute($data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'name', + 'size' => 256, + 'required' => true, + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsCreateStringAttribute']); + + return $data; + } + + /** + * @depends testCreateStringAttribute + * @throws Exception + */ + public function testUpdateStringAttribute($data): array + { + // Wait for attributes to be available + sleep(1); + + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_STRING_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'name', + 'required' => false, + 'default' => 'Default Value', + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsUpdateStringAttribute']); + $this->assertFalse($column['body']['data']['collectionsUpdateStringAttribute']['required']); + $this->assertEquals('Default Value', $column['body']['data']['collectionsUpdateStringAttribute']['default']); + $this->assertEquals(200, $column['headers']['status-code']); + + return $data; + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testCreateIntegerAttribute($data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_INTEGER_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'age', + 'min' => 18, + 'max' => 150, + 'required' => true, + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsCreateIntegerAttribute']); + + return $data; + } + + /** + * @depends testCreateIntegerAttribute + * @throws Exception + */ + public function testUpdateIntegerAttribute($data): array + { + // Wait for attributes to be available + sleep(1); + + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_INTEGER_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'age', + 'required' => false, + 'min' => 12, + 'max' => 160, + 'default' => 50 + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsUpdateIntegerAttribute']); + $this->assertFalse($column['body']['data']['collectionsUpdateIntegerAttribute']['required']); + $this->assertEquals(12, $column['body']['data']['collectionsUpdateIntegerAttribute']['min']); + $this->assertEquals(160, $column['body']['data']['collectionsUpdateIntegerAttribute']['max']); + $this->assertEquals(50, $column['body']['data']['collectionsUpdateIntegerAttribute']['default']); + $this->assertEquals(200, $column['headers']['status-code']); + + return $data; + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testCreateBooleanAttribute($data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_BOOLEAN_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'alive', + 'required' => true, + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsCreateBooleanAttribute']); + + return $data; + } + + /** + * @depends testCreateBooleanAttribute + * @throws Exception + */ + public function testUpdateBooleanAttribute($data): array + { + // Wait for attributes to be available + sleep(1); + + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_BOOLEAN_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'alive', + 'required' => false, + 'default' => true + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsUpdateBooleanAttribute']); + $this->assertFalse($column['body']['data']['collectionsUpdateBooleanAttribute']['required']); + $this->assertTrue($column['body']['data']['collectionsUpdateBooleanAttribute']['default']); + $this->assertEquals(200, $column['headers']['status-code']); + + return $data; + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testCreateFloatAttribute($data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_FLOAT_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'salary', + 'min' => 1000.0, + 'max' => 999999.99, + 'default' => 1000.0, + 'required' => false, + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsCreateFloatAttribute']); + + return $data; + } + + /** + * @depends testCreateFloatAttribute + * @throws Exception + */ + public function testUpdateFloatAttribute($data): array + { + // Wait for attributes to be available + sleep(1); + + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_FLOAT_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'salary', + 'required' => false, + 'min' => 100.0, + 'max' => 1000000.0, + 'default' => 2500.0 + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsUpdateFloatAttribute']); + $this->assertFalse($column['body']['data']['collectionsUpdateFloatAttribute']['required']); + $this->assertEquals(100.0, $column['body']['data']['collectionsUpdateFloatAttribute']['min']); + $this->assertEquals(1000000.0, $column['body']['data']['collectionsUpdateFloatAttribute']['max']); + $this->assertEquals(2500.0, $column['body']['data']['collectionsUpdateFloatAttribute']['default']); + $this->assertEquals(200, $column['headers']['status-code']); + + return $data; + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testCreateEmailAttribute($data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_EMAIL_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'email', + 'required' => true, + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsCreateEmailAttribute']); + + return $data; + } + + /** + * @depends testCreateEmailAttribute + * @throws Exception + */ + public function testUpdateEmailAttribute($data): array + { + // Wait for attributes to be available + sleep(1); + + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_EMAIL_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'email', + 'required' => false, + 'default' => 'torsten@appwrite.io', + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsUpdateEmailAttribute']); + $this->assertFalse($column['body']['data']['collectionsUpdateEmailAttribute']['required']); + $this->assertEquals('torsten@appwrite.io', $column['body']['data']['collectionsUpdateEmailAttribute']['default']); + $this->assertEquals(200, $column['headers']['status-code']); + + return $data; + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testCreateEnumAttribute($data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_ENUM_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'role', + 'elements' => [ + 'crew', + 'actor', + 'guest', + ], + 'required' => true, + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsCreateEnumAttribute']); + + return $data; + } + + + /** + * @depends testCreateEnumAttribute + * @throws Exception + */ + public function testUpdateEnumAttribute($data): array + { + // Wait for attributes to be available + sleep(1); + + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_ENUM_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'role', + 'required' => false, + 'elements' => [ + 'crew', + 'tech', + 'actor' + ], + 'default' => 'tech' + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsUpdateEnumAttribute']); + $this->assertFalse($column['body']['data']['collectionsUpdateEnumAttribute']['required']); + $this->assertEquals('tech', $column['body']['data']['collectionsUpdateEnumAttribute']['default']); + $this->assertContains('tech', $column['body']['data']['collectionsUpdateEnumAttribute']['elements']); + $this->assertNotContains('guest', $column['body']['data']['collectionsUpdateEnumAttribute']['elements']); + $this->assertEquals(200, $column['headers']['status-code']); + + return $data; + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testCreateDatetimeAttribute($data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_DATETIME_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'dob', + 'required' => true, + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsCreateDatetimeAttribute']); + + return $data; + } + + /** + * @depends testCreateDatetimeAttribute + * @throws Exception + */ + public function testUpdateDatetimeAttribute($data): array + { + // Wait for attributes to be available + sleep(1); + + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_DATETIME_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'dob', + 'required' => false, + 'default' => '2000-01-01T00:00:00Z' + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsUpdateDatetimeAttribute']); + $this->assertFalse($column['body']['data']['collectionsUpdateDatetimeAttribute']['required']); + $this->assertEquals('2000-01-01T00:00:00Z', $column['body']['data']['collectionsUpdateDatetimeAttribute']['default']); + $this->assertEquals(200, $column['headers']['status-code']); + + return $data; + } + + /** + * @depends testCreateCollection + */ + public function testCreateRelationshipAttribute(array $data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_RELATIONSHIP_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['collection2']['_id'], // Movies + 'relatedCollectionId' => $data['table']['_id'], // Actors + 'type' => Database::RELATION_ONE_TO_MANY, + 'twoWay' => true, + 'key' => 'actors', + 'twoWayKey' => 'movie' + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsCreateRelationshipAttribute']); + + return $data; + } + + /** + * @depends testCreateRelationshipAttribute + */ + public function testUpdateRelationshipAttribute(array $data): array + { + sleep(1); + + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_RELATIONSHIP_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['collection2']['_id'], + 'key' => 'actors', + 'onDelete' => Database::RELATION_MUTATE_CASCADE, + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsUpdateRelationshipAttribute']); + + return $data; + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testCreateIPAttribute($data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_IP_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'ip', + 'required' => false, + 'default' => '::1', + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsCreateIpAttribute']); + + return $data; + } + + /** + * @depends testCreateIPAttribute + * @throws Exception + */ + public function testUpdateIPAttribute($data): array + { + // Wait for attributes to be available + sleep(3); + + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_IP_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'ip', + 'required' => false, + 'default' => '127.0.0.1' + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsUpdateIpAttribute']); + $this->assertFalse($column['body']['data']['collectionsUpdateIpAttribute']['required']); + $this->assertEquals('127.0.0.1', $column['body']['data']['collectionsUpdateIpAttribute']['default']); + $this->assertEquals(200, $column['headers']['status-code']); + + return $data; + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testCreateURLAttribute($data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_URL_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'url', + 'required' => false, + 'default' => 'https://appwrite.io', + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsCreateUrlAttribute']); + + return $data; + } + + /** + * @depends testCreateURLAttribute + * @throws Exception + */ + public function testUpdateURLAttribute($data): void + { + // Wait for attributes to be available + sleep(3); + + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_URL_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'url', + 'required' => false, + 'default' => 'https://cloud.appwrite.io' + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsUpdateUrlAttribute']); + $this->assertFalse($column['body']['data']['collectionsUpdateUrlAttribute']['required']); + $this->assertEquals('https://cloud.appwrite.io', $column['body']['data']['collectionsUpdateUrlAttribute']['default']); + $this->assertEquals(200, $column['headers']['status-code']); + } + + /** + * @depends testUpdateStringAttribute + * @depends testUpdateIntegerAttribute + * @throws Exception + */ + public function testCreateIndex($data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_INDEX); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'index', + 'type' => 'key', + 'attributes' => [ + 'name', + 'age', + ], + ] + ]; + + $index = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $index['body']); + $this->assertIsArray($index['body']['data']); + $this->assertIsArray($index['body']['data']['collectionsCreateIndex']); + + return [ + 'database' => $data['database'], + 'table' => $data['table'], + 'index' => $index['body']['data']['collectionsCreateIndex'], + ]; + } + + /** + * @depends testUpdateStringAttribute + * @depends testUpdateIntegerAttribute + * @depends testUpdateBooleanAttribute + * @depends testUpdateEnumAttribute + * @throws Exception + */ + public function testCreateDocument($data): array + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$CREATE_DOCUMENT); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => ID::unique(), + 'data' => [ + 'name' => 'John Doe', + 'email' => 'example@appwrite.io', + 'age' => 30, + 'alive' => true, + 'salary' => 9999.9, + 'role' => 'crew', + 'dob' => '2000-01-01T00:00:00Z', + ], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ] + ]; + + $row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $row['body']); + $this->assertIsArray($row['body']['data']); + + $row = $row['body']['data']['collectionsCreateDocument']; + $this->assertIsArray($row); + + return [ + 'database' => $data['database'], + 'table' => $data['table'], + 'row' => $row, + ]; + } + + // /** + // * @depends testCreateStringAttribute + // * @depends testCreateIntegerAttribute + // * @depends testCreateBooleanAttribute + // * @depends testCreateFloatAttribute + // * @depends testCreateEmailAttribute + // * @depends testCreateEnumAttribute + // * @depends testCreateDatetimeAttribute + // * @throws Exception + // */ + // public function testCreateCustomEntity(): array + // { + // $projectId = $this->getProject()['$id']; + // $query = $this->getQuery(self::$CREATE_CUSTOM_ENTITY); + // $gqlPayload = [ + // 'query' => $query, + // 'variables' => [ + // 'name' => 'John Doe', + // 'age' => 35, + // 'alive' => true, + // 'salary' => 9999.9, + // 'email' => 'johndoe@appwrite.io', + // 'role' => 'crew', + // 'dob' => '2000-01-01T00:00:00Z', + // ] + // ]; + // + // $actor = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + // 'content-type' => 'application/json', + // 'x-appwrite-project' => $projectId, + // ], $this->getHeaders()), $gqlPayload); + // + // $this->assertArrayNotHasKey('errors', $actor['body']); + // $this->assertIsArray($actor['body']['data']); + // $actor = $actor['body']['data']['actorsCreate']; + // $this->assertIsArray($actor); + // + // return $actor; + // } + + public function testGetDatabases(): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$GET_DATABASES); + $gqlPayload = [ + 'query' => $query, + ]; + + $databases = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $databases['body']); + $this->assertIsArray($databases['body']['data']); + $this->assertIsArray($databases['body']['data']['databasesList']); + } + + /** + * @depends testCreateDatabase + * @throws Exception + */ + public function testGetDatabase($database): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$GET_DATABASE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $database['_id'], + ] + ]; + + $database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $database['body']); + $this->assertIsArray($database['body']['data']); + $this->assertIsArray($database['body']['data']['databasesGet']); + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testGetCollections($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$GET_COLLECTIONS); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + ] + ]; + + $tables = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $tables['body']); + $this->assertIsArray($tables['body']['data']); + $this->assertIsArray($tables['body']['data']['databasesListCollections']); + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testGetCollection($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$GET_COLLECTION); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + ] + ]; + + $table = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $table['body']); + $this->assertIsArray($table['body']['data']); + $this->assertIsArray($table['body']['data']['databasesGetCollection']); + } + + /** + * @depends testUpdateStringAttribute + * @depends testUpdateIntegerAttribute + * @throws Exception + */ + public function testGetAttributes($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$GET_ATTRIBUTES); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + ] + ]; + + $columns = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $columns['body']); + $this->assertIsArray($columns['body']['data']); + $this->assertIsArray($columns['body']['data']['collectionsListAttributes']); + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testGetAttribute($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$GET_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'name', + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $column['body']); + $this->assertIsArray($column['body']['data']); + $this->assertIsArray($column['body']['data']['collectionsGetAttribute']); + } + + /** + * @depends testCreateIndex + * @throws Exception + */ + public function testGetIndexes($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$GET_INDEXES); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + ] + ]; + + $indices = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $indices['body']); + $this->assertIsArray($indices['body']['data']); + $this->assertIsArray($indices['body']['data']['collectionsListIndexes']); + } + + /** + * @depends testCreateIndex + * @throws Exception + */ + public function testGetIndex($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$GET_INDEX); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => $data['index']['key'], + ] + ]; + + $index = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $index['body']); + $this->assertIsArray($index['body']['data']); + $this->assertIsArray($index['body']['data']['collectionsGetIndex']); + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testGetDocuments($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$GET_DOCUMENTS); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + ] + ]; + + $rows = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $rows['body']); + $this->assertIsArray($rows['body']['data']); + $this->assertIsArray($rows['body']['data']['collectionsListDocuments']); + } + + /** + * @depends testCreateDocument + * @throws Exception + */ + public function testGetDocument($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$GET_DOCUMENT); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => $data['row']['_id'], + ] + ]; + + $row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $row['body']); + $this->assertIsArray($row['body']['data']); + $this->assertIsArray($row['body']['data']['collectionsGetDocument']); + } + + // /** + // * @depends testCreateCustomEntity + // * @throws Exception + // */ + // public function testGetCustomEntities($data) + // { + // $projectId = $this->getProject()['$id']; + // $query = $this->getQuery(self::$GET_CUSTOM_ENTITIES); + // $gqlPayload = [ + // 'query' => $query, + // ]; + // + // $customEntities = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + // 'content-type' => 'application/json', + // 'x-appwrite-project' => $projectId, + // ], $this->getHeaders()), $gqlPayload); + // + // $this->assertArrayNotHasKey('errors', $customEntities['body']); + // $this->assertIsArray($customEntities['body']['data']); + // $this->assertIsArray($customEntities['body']['data']['actorsList']); + // } + // + // /** + // * @depends testCreateCustomEntity + // * @throws Exception + // */ + // public function testGetCustomEntity($data) + // { + // $projectId = $this->getProject()['$id']; + // $query = $this->getQuery(self::$GET_CUSTOM_ENTITY); + // $gqlPayload = [ + // 'query' => $query, + // 'variables' => [ + // 'id' => $data['id'], + // ] + // ]; + // + // $entity = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + // 'content-type' => 'application/json', + // 'x-appwrite-project' => $projectId, + // ], $this->getHeaders()), $gqlPayload); + // + // $this->assertArrayNotHasKey('errors', $entity['body']); + // $this->assertIsArray($entity['body']['data']); + // $this->assertIsArray($entity['body']['data']['actorsGet']); + // } + + /** + * @depends testCreateDatabase + * @throws Exception + */ + public function testUpdateDatabase($database) + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_DATABASE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $database['_id'], + 'name' => 'New Database Name', + ] + ]; + + $database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $database['body']); + $this->assertIsArray($database['body']['data']); + $this->assertIsArray($database['body']['data']['databasesUpdate']); + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testUpdateCollection($data) + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_COLLECTION); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'name' => 'New Collection Name', + 'rowSecurity' => false, + ] + ]; + + $table = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $table['body']); + $this->assertIsArray($table['body']['data']); + $this->assertIsArray($table['body']['data']['databasesUpdateCollection']); + } + + /** + * @depends testCreateDocument + * @throws Exception + */ + public function testUpdateDocument($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$UPDATE_DOCUMENT); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => $data['row']['_id'], + 'data' => [ + 'name' => 'New Document Name', + ], + ] + ]; + + $row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertArrayNotHasKey('errors', $row['body']); + $this->assertIsArray($row['body']['data']); + $row = $row['body']['data']['collectionsUpdateDocument']; + $this->assertIsArray($row); + $this->assertStringContainsString('New Document Name', $row['data']); + } + + // /** + // * @depends testCreateCustomEntity + // * @throws Exception + // */ + // public function testUpdateCustomEntity(array $data) + // { + // $projectId = $this->getProject()['$id']; + // $query = $this->getQuery(self::$UPDATE_CUSTOM_ENTITY); + // $gqlPayload = [ + // 'query' => $query, + // 'variables' => [ + // 'id' => $data['id'], + // 'name' => 'New Custom Entity Name', + // ] + // ]; + // + // $entity = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + // 'content-type' => 'application/json', + // 'x-appwrite-project' => $projectId, + // ], $this->getHeaders()), $gqlPayload); + // + // $this->assertArrayNotHasKey('errors', $entity['body']); + // $this->assertIsArray($entity['body']['data']); + // $entity = $entity['body']['data']['actorsUpdate']; + // $this->assertIsArray($entity); + // $this->assertStringContainsString('New Custom Entity Name', $entity['name']); + // } + + /** + * @depends testCreateDocument + * @throws Exception + */ + public function testDeleteDocument($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$DELETE_DOCUMENT); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'rowId' => $data['row']['_id'], + ] + ]; + + $row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsNotArray($row['body']); + $this->assertEquals(204, $row['headers']['status-code']); + } + + // /** + // * @depends testCreateCustomEntity + // * @throws Exception + // */ + // public function testDeleteCustomEntity(array $data) + // { + // $projectId = $this->getProject()['$id']; + // $query = $this->getQuery(self::$DELETE_CUSTOM_ENTITY); + // $gqlPayload = [ + // 'query' => $query, + // 'variables' => [ + // 'id' => $data['id'], + // ] + // ]; + // + // $entity = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + // 'content-type' => 'application/json', + // 'x-appwrite-project' => $projectId, + // ], $this->getHeaders()), $gqlPayload); + // + // $this->assertIsNotArray($entity['body']); + // $this->assertEquals(204, $entity['headers']['status-code']); + // } + + /** + * @depends testUpdateStringAttribute + * @throws Exception + */ + public function testDeleteAttribute($data): void + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$DELETE_ATTRIBUTE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + 'key' => 'name', + ] + ]; + + $column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsNotArray($column['body']); + $this->assertEquals(204, $column['headers']['status-code']); + } + + /** + * @depends testCreateCollection + * @throws Exception + */ + public function testDeleteCollection($data) + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$DELETE_COLLECTION); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['database']['_id'], + 'tableId' => $data['table']['_id'], + ] + ]; + + $table = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsNotArray($table['body']); + $this->assertEquals(204, $table['headers']['status-code']); + } + + /** + * @depends testCreateDatabase + * @throws Exception + */ + public function testDeleteDatabase($database) + { + $projectId = $this->getProject()['$id']; + $query = $this->getQuery(self::$DELETE_DATABASE); + $gqlPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $database['_id'], + ] + ]; + + $database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), $gqlPayload); + + $this->assertIsNotArray($database['body']); + $this->assertEquals(204, $database['headers']['status-code']); + } +} From d1ae06550fe317109672d50888d39bd460be042e Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 10:09:43 +0530 Subject: [PATCH 112/343] update: realtime events logic. --- src/Appwrite/Event/Realtime.php | 70 +++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/src/Appwrite/Event/Realtime.php b/src/Appwrite/Event/Realtime.php index f45b6548d8..016006ae73 100644 --- a/src/Appwrite/Event/Realtime.php +++ b/src/Appwrite/Event/Realtime.php @@ -72,32 +72,11 @@ class Realtime extends Event return false; } - $allEvents = Event::generateEvents($this->getEvent(), $this->getParams()); - $firstEvent = $allEvents[0]; // most verbose event pattern + $events = Event::generateEvents($this->getEvent(), $this->getParams()); + $firstEvent = $events[0]; // most verbose event pattern // generate and merge all collection and tables api events. - if (str_contains($this->getEvent(), 'databases.') && str_contains($firstEvent, 'collections')) { - $tableEventMap = [ - 'collections' => 'tables', 'attributes' => 'columns', - 'attributeId' => 'columnId', 'documents' => 'rows', 'documentId' => 'rowId', - ]; - - // replace params! - $tableEvent = str_replace( - array_keys($tableEventMap), - array_values($tableEventMap), - $this->getEvent() - ); - - // generate new events - $tableEvents = Event::generateEvents($tableEvent, $this->getParams()); - - // merge all of the api events - $allEvents = array_merge($allEvents, $tableEvents); - - // remove duplicates - $allEvents = array_values(array_unique($allEvents)); - } + $events = $this->mirrorCollectionEvents($firstEvent, $events); $payload = new Document($this->getPayload()); @@ -124,7 +103,7 @@ class Realtime extends Event $this->realtime->send( projectId: $projectId, payload: $this->getRealtimePayload(), - events: $allEvents, + events: $events, channels: $target['channels'], roles: $target['roles'], options: [ @@ -136,4 +115,45 @@ class Realtime extends Event return true; } + + /** + * Adds `table` events for `collection` events. + * + * Example: + * + * `databases.*.collections.*.documents.*.update` →\ + * `[databases.*.collections.*.documents.*.update, databases.*.tables.*.rows.*.update]` + */ + private function mirrorCollectionEvents(string $firstEvent, array $events): array + { + $tableEventMap = [ + 'documents' => 'rows', + 'collections' => 'tables', + 'attributes' => 'columns', + ]; + + if ( + str_contains($this->getEvent(), 'databases.') && + str_contains($firstEvent, 'collections') + ) { + $pairedEvents = []; + + foreach ($events as $event) { + $pairedEvents[] = $event; + + if (str_contains($event, 'collections')) { + $tableSideEvent = str_replace( + array_keys($tableEventMap), + array_values($tableEventMap), + $event + ); + $pairedEvents[] = $tableSideEvent; + } + } + + $events = $pairedEvents; + } + + return $events; + } } From 02af05b409e0e4dbdeb51d9b0ed86cc462ebde42 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 10:10:03 +0530 Subject: [PATCH 113/343] fix: endpoint in abuse test. --- tests/e2e/General/AbuseTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/General/AbuseTest.php b/tests/e2e/General/AbuseTest.php index 217f9f93ed..cfd12b0e9f 100644 --- a/tests/e2e/General/AbuseTest.php +++ b/tests/e2e/General/AbuseTest.php @@ -157,7 +157,7 @@ class AbuseTest extends Scope $collectionId = $data['collectionId']; $max = 120; - $document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $collectionId . '/rows', [ + $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $collectionId . '/rows', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -168,10 +168,10 @@ class AbuseTest extends Scope ], ]); - $documentId = $document['body']['$id']; + $rowId = $row['body']['$id']; for ($i = 0; $i <= $max + 1; $i++) { - $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, [ + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $collectionId . '/rows/' . $rowId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ From 594f8595aea8d701913f4dc2a748304c5b39b007 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 10:10:23 +0530 Subject: [PATCH 114/343] update: database server test for graphql <> tables api. --- .../GraphQL/Tables/DatabaseServerTest.php | 380 +++++++++--------- 1 file changed, 190 insertions(+), 190 deletions(-) diff --git a/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php b/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php index d5980a4096..4f711148e3 100644 --- a/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php +++ b/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php @@ -47,10 +47,10 @@ class DatabaseServerTest extends Scope /** * @depends testCreateDatabase */ - public function testCreateCollection($database): array + public function testCreateTable($database): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_COLLECTION); + $query = $this->getQuery(self::$CREATE_TABLE); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -74,7 +74,7 @@ class DatabaseServerTest extends Scope $this->assertIsArray($table['body']['data']); $this->assertArrayNotHasKey('errors', $table['body']); - $table = $table['body']['data']['databasesCreateCollection']; + $table = $table['body']['data']['databasesCreateTable']; $this->assertEquals('Actors', $table['name']); $gqlPayload = [ @@ -100,24 +100,24 @@ class DatabaseServerTest extends Scope $this->assertIsArray($table2['body']['data']); $this->assertArrayNotHasKey('errors', $table2['body']); - $table2 = $table2['body']['data']['databasesCreateCollection']; + $table2 = $table2['body']['data']['databasesCreateTable']; $this->assertEquals('Movies', $table2['name']); return [ 'database' => $database, 'table' => $table, - 'collection2' => $table2, + 'table2' => $table2, ]; } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testCreateStringAttribute($data): array + public function testCreateStringColumn($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_STRING_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -136,22 +136,22 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $column['body']); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsCreateStringAttribute']); + $this->assertIsArray($column['body']['data']['tablesCreateStringColumn']); return $data; } /** - * @depends testCreateStringAttribute + * @depends testCreateStringColumn * @throws Exception */ - public function testUpdateStringAttribute($data): array + public function testUpdateStringColumn($data): array { - // Wait for attributes to be available + // Wait for columns to be available sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_STRING_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_STRING_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -169,22 +169,22 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsUpdateStringAttribute']); - $this->assertFalse($column['body']['data']['collectionsUpdateStringAttribute']['required']); - $this->assertEquals('Default Value', $column['body']['data']['collectionsUpdateStringAttribute']['default']); + $this->assertIsArray($column['body']['data']['tablesUpdateStringColumn']); + $this->assertFalse($column['body']['data']['tablesUpdateStringColumn']['required']); + $this->assertEquals('Default Value', $column['body']['data']['tablesUpdateStringColumn']['default']); $this->assertEquals(200, $column['headers']['status-code']); return $data; } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testCreateIntegerAttribute($data): array + public function testCreateIntegerColumn($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_INTEGER_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_INTEGER_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -204,22 +204,22 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $column['body']); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsCreateIntegerAttribute']); + $this->assertIsArray($column['body']['data']['tablesCreateIntegerColumn']); return $data; } /** - * @depends testCreateIntegerAttribute + * @depends testCreateIntegerColumn * @throws Exception */ - public function testUpdateIntegerAttribute($data): array + public function testUpdateIntegerColumn($data): array { - // Wait for attributes to be available + // Wait for columns to be available sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_INTEGER_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_INTEGER_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -239,24 +239,24 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsUpdateIntegerAttribute']); - $this->assertFalse($column['body']['data']['collectionsUpdateIntegerAttribute']['required']); - $this->assertEquals(12, $column['body']['data']['collectionsUpdateIntegerAttribute']['min']); - $this->assertEquals(160, $column['body']['data']['collectionsUpdateIntegerAttribute']['max']); - $this->assertEquals(50, $column['body']['data']['collectionsUpdateIntegerAttribute']['default']); + $this->assertIsArray($column['body']['data']['tablesUpdateIntegerColumn']); + $this->assertFalse($column['body']['data']['tablesUpdateIntegerColumn']['required']); + $this->assertEquals(12, $column['body']['data']['tablesUpdateIntegerColumn']['min']); + $this->assertEquals(160, $column['body']['data']['tablesUpdateIntegerColumn']['max']); + $this->assertEquals(50, $column['body']['data']['tablesUpdateIntegerColumn']['default']); $this->assertEquals(200, $column['headers']['status-code']); return $data; } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testCreateBooleanAttribute($data): array + public function testCreateBooleanColumn($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_BOOLEAN_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_BOOLEAN_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -274,22 +274,22 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $column['body']); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsCreateBooleanAttribute']); + $this->assertIsArray($column['body']['data']['tablesCreateBooleanColumn']); return $data; } /** - * @depends testCreateBooleanAttribute + * @depends testCreateBooleanColumn * @throws Exception */ - public function testUpdateBooleanAttribute($data): array + public function testUpdateBooleanColumn($data): array { - // Wait for attributes to be available + // Wait for columns to be available sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_BOOLEAN_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_BOOLEAN_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -307,22 +307,22 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsUpdateBooleanAttribute']); - $this->assertFalse($column['body']['data']['collectionsUpdateBooleanAttribute']['required']); - $this->assertTrue($column['body']['data']['collectionsUpdateBooleanAttribute']['default']); + $this->assertIsArray($column['body']['data']['tablesUpdateBooleanColumn']); + $this->assertFalse($column['body']['data']['tablesUpdateBooleanColumn']['required']); + $this->assertTrue($column['body']['data']['tablesUpdateBooleanColumn']['default']); $this->assertEquals(200, $column['headers']['status-code']); return $data; } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testCreateFloatAttribute($data): array + public function testCreateFloatColumn($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_FLOAT_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_FLOAT_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -343,22 +343,22 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $column['body']); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsCreateFloatAttribute']); + $this->assertIsArray($column['body']['data']['tablesCreateFloatColumn']); return $data; } /** - * @depends testCreateFloatAttribute + * @depends testCreateFloatColumn * @throws Exception */ - public function testUpdateFloatAttribute($data): array + public function testUpdateFloatColumn($data): array { - // Wait for attributes to be available + // Wait for columns to be available sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_FLOAT_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_FLOAT_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -378,24 +378,24 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsUpdateFloatAttribute']); - $this->assertFalse($column['body']['data']['collectionsUpdateFloatAttribute']['required']); - $this->assertEquals(100.0, $column['body']['data']['collectionsUpdateFloatAttribute']['min']); - $this->assertEquals(1000000.0, $column['body']['data']['collectionsUpdateFloatAttribute']['max']); - $this->assertEquals(2500.0, $column['body']['data']['collectionsUpdateFloatAttribute']['default']); + $this->assertIsArray($column['body']['data']['tablesUpdateFloatColumn']); + $this->assertFalse($column['body']['data']['tablesUpdateFloatColumn']['required']); + $this->assertEquals(100.0, $column['body']['data']['tablesUpdateFloatColumn']['min']); + $this->assertEquals(1000000.0, $column['body']['data']['tablesUpdateFloatColumn']['max']); + $this->assertEquals(2500.0, $column['body']['data']['tablesUpdateFloatColumn']['default']); $this->assertEquals(200, $column['headers']['status-code']); return $data; } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testCreateEmailAttribute($data): array + public function testCreateEmailColumn($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_EMAIL_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_EMAIL_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -413,22 +413,22 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $column['body']); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsCreateEmailAttribute']); + $this->assertIsArray($column['body']['data']['tablesCreateEmailColumn']); return $data; } /** - * @depends testCreateEmailAttribute + * @depends testCreateEmailColumn * @throws Exception */ - public function testUpdateEmailAttribute($data): array + public function testUpdateEmailColumn($data): array { - // Wait for attributes to be available + // Wait for columns to be available sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_EMAIL_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_EMAIL_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -446,22 +446,22 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsUpdateEmailAttribute']); - $this->assertFalse($column['body']['data']['collectionsUpdateEmailAttribute']['required']); - $this->assertEquals('torsten@appwrite.io', $column['body']['data']['collectionsUpdateEmailAttribute']['default']); + $this->assertIsArray($column['body']['data']['tablesUpdateEmailColumn']); + $this->assertFalse($column['body']['data']['tablesUpdateEmailColumn']['required']); + $this->assertEquals('torsten@appwrite.io', $column['body']['data']['tablesUpdateEmailColumn']['default']); $this->assertEquals(200, $column['headers']['status-code']); return $data; } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testCreateEnumAttribute($data): array + public function testCreateEnumColumn($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_ENUM_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_ENUM_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -484,23 +484,23 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $column['body']); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsCreateEnumAttribute']); + $this->assertIsArray($column['body']['data']['tablesCreateEnumColumn']); return $data; } /** - * @depends testCreateEnumAttribute + * @depends testCreateEnumColumn * @throws Exception */ - public function testUpdateEnumAttribute($data): array + public function testUpdateEnumColumn($data): array { - // Wait for attributes to be available + // Wait for columns to be available sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_ENUM_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_ENUM_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -523,24 +523,24 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsUpdateEnumAttribute']); - $this->assertFalse($column['body']['data']['collectionsUpdateEnumAttribute']['required']); - $this->assertEquals('tech', $column['body']['data']['collectionsUpdateEnumAttribute']['default']); - $this->assertContains('tech', $column['body']['data']['collectionsUpdateEnumAttribute']['elements']); - $this->assertNotContains('guest', $column['body']['data']['collectionsUpdateEnumAttribute']['elements']); + $this->assertIsArray($column['body']['data']['tablesUpdateEnumColumn']); + $this->assertFalse($column['body']['data']['tablesUpdateEnumColumn']['required']); + $this->assertEquals('tech', $column['body']['data']['tablesUpdateEnumColumn']['default']); + $this->assertContains('tech', $column['body']['data']['tablesUpdateEnumColumn']['elements']); + $this->assertNotContains('guest', $column['body']['data']['tablesUpdateEnumColumn']['elements']); $this->assertEquals(200, $column['headers']['status-code']); return $data; } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testCreateDatetimeAttribute($data): array + public function testCreateDatetimeColumn($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_DATETIME_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_DATETIME_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -558,22 +558,22 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $column['body']); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsCreateDatetimeAttribute']); + $this->assertIsArray($column['body']['data']['tablesCreateDatetimeColumn']); return $data; } /** - * @depends testCreateDatetimeAttribute + * @depends testCreateDatetimeColumn * @throws Exception */ - public function testUpdateDatetimeAttribute($data): array + public function testUpdateDatetimeColumn($data): array { - // Wait for attributes to be available + // Wait for columns to be available sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_DATETIME_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_DATETIME_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -591,27 +591,27 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsUpdateDatetimeAttribute']); - $this->assertFalse($column['body']['data']['collectionsUpdateDatetimeAttribute']['required']); - $this->assertEquals('2000-01-01T00:00:00Z', $column['body']['data']['collectionsUpdateDatetimeAttribute']['default']); + $this->assertIsArray($column['body']['data']['tablesUpdateDatetimeColumn']); + $this->assertFalse($column['body']['data']['tablesUpdateDatetimeColumn']['required']); + $this->assertEquals('2000-01-01T00:00:00Z', $column['body']['data']['tablesUpdateDatetimeColumn']['default']); $this->assertEquals(200, $column['headers']['status-code']); return $data; } /** - * @depends testCreateCollection + * @depends testCreateTable */ - public function testCreateRelationshipAttribute(array $data): array + public function testCreateRelationshipColumn(array $data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_RELATIONSHIP_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_RELATIONSHIP_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['collection2']['_id'], // Movies - 'relatedCollectionId' => $data['table']['_id'], // Actors + 'tableId' => $data['table2']['_id'], // Movies + 'relatedTableId' => $data['table']['_id'], // Actors 'type' => Database::RELATION_ONE_TO_MANY, 'twoWay' => true, 'key' => 'actors', @@ -626,25 +626,25 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $column['body']); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsCreateRelationshipAttribute']); + $this->assertIsArray($column['body']['data']['tablesCreateRelationshipColumn']); return $data; } /** - * @depends testCreateRelationshipAttribute + * @depends testCreateRelationshipColumn */ - public function testUpdateRelationshipAttribute(array $data): array + public function testUpdateRelationshipColumn(array $data): array { sleep(1); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_RELATIONSHIP_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_RELATIONSHIP_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], - 'tableId' => $data['collection2']['_id'], + 'tableId' => $data['table2']['_id'], 'key' => 'actors', 'onDelete' => Database::RELATION_MUTATE_CASCADE, ] @@ -657,19 +657,19 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $column['body']); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsUpdateRelationshipAttribute']); + $this->assertIsArray($column['body']['data']['tablesUpdateRelationshipColumn']); return $data; } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testCreateIPAttribute($data): array + public function testCreateIPColumn($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_IP_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_IP_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -688,22 +688,22 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $column['body']); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsCreateIpAttribute']); + $this->assertIsArray($column['body']['data']['tablesCreateIpColumn']); return $data; } /** - * @depends testCreateIPAttribute + * @depends testCreateIPColumn * @throws Exception */ - public function testUpdateIPAttribute($data): array + public function testUpdateIPColumn($data): array { - // Wait for attributes to be available + // Wait for columns to be available sleep(3); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_IP_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_IP_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -721,22 +721,22 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsUpdateIpAttribute']); - $this->assertFalse($column['body']['data']['collectionsUpdateIpAttribute']['required']); - $this->assertEquals('127.0.0.1', $column['body']['data']['collectionsUpdateIpAttribute']['default']); + $this->assertIsArray($column['body']['data']['tablesUpdateIpColumn']); + $this->assertFalse($column['body']['data']['tablesUpdateIpColumn']['required']); + $this->assertEquals('127.0.0.1', $column['body']['data']['tablesUpdateIpColumn']['default']); $this->assertEquals(200, $column['headers']['status-code']); return $data; } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testCreateURLAttribute($data): array + public function testCreateURLColumn($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_URL_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_URL_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -755,22 +755,22 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $column['body']); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsCreateUrlAttribute']); + $this->assertIsArray($column['body']['data']['tablesCreateUrlColumn']); return $data; } /** - * @depends testCreateURLAttribute + * @depends testCreateURLColumn * @throws Exception */ - public function testUpdateURLAttribute($data): void + public function testUpdateURLColumn($data): void { - // Wait for attributes to be available + // Wait for columns to be available sleep(3); $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_URL_ATTRIBUTE); + $query = $this->getQuery(self::$UPDATE_URL_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -788,21 +788,21 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsUpdateUrlAttribute']); - $this->assertFalse($column['body']['data']['collectionsUpdateUrlAttribute']['required']); - $this->assertEquals('https://cloud.appwrite.io', $column['body']['data']['collectionsUpdateUrlAttribute']['default']); + $this->assertIsArray($column['body']['data']['tablesUpdateUrlColumn']); + $this->assertFalse($column['body']['data']['tablesUpdateUrlColumn']['required']); + $this->assertEquals('https://cloud.appwrite.io', $column['body']['data']['tablesUpdateUrlColumn']['default']); $this->assertEquals(200, $column['headers']['status-code']); } /** - * @depends testUpdateStringAttribute - * @depends testUpdateIntegerAttribute + * @depends testUpdateStringColumn + * @depends testUpdateIntegerColumn * @throws Exception */ public function testCreateIndex($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_INDEX); + $query = $this->getQuery(self::$CREATE_COLUMN_INDEX); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -810,7 +810,7 @@ class DatabaseServerTest extends Scope 'tableId' => $data['table']['_id'], 'key' => 'index', 'type' => 'key', - 'attributes' => [ + 'columns' => [ 'name', 'age', ], @@ -824,26 +824,26 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $index['body']); $this->assertIsArray($index['body']['data']); - $this->assertIsArray($index['body']['data']['collectionsCreateIndex']); + $this->assertIsArray($index['body']['data']['tablesCreateIndex']); return [ 'database' => $data['database'], 'table' => $data['table'], - 'index' => $index['body']['data']['collectionsCreateIndex'], + 'index' => $index['body']['data']['tablesCreateIndex'], ]; } /** - * @depends testUpdateStringAttribute - * @depends testUpdateIntegerAttribute - * @depends testUpdateBooleanAttribute - * @depends testUpdateEnumAttribute + * @depends testUpdateStringColumn + * @depends testUpdateIntegerColumn + * @depends testUpdateBooleanColumn + * @depends testUpdateEnumColumn * @throws Exception */ - public function testCreateDocument($data): array + public function testCreateRow($data): array { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$CREATE_DOCUMENT); + $query = $this->getQuery(self::$CREATE_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -875,7 +875,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $row['body']); $this->assertIsArray($row['body']['data']); - $row = $row['body']['data']['collectionsCreateDocument']; + $row = $row['body']['data']['tablesCreateRow']; $this->assertIsArray($row); return [ @@ -886,13 +886,13 @@ class DatabaseServerTest extends Scope } // /** - // * @depends testCreateStringAttribute - // * @depends testCreateIntegerAttribute - // * @depends testCreateBooleanAttribute - // * @depends testCreateFloatAttribute - // * @depends testCreateEmailAttribute - // * @depends testCreateEnumAttribute - // * @depends testCreateDatetimeAttribute + // * @depends testCreateStringColumn + // * @depends testCreateIntegerColumn + // * @depends testCreateBooleanColumn + // * @depends testCreateFloatColumn + // * @depends testCreateEmailColumn + // * @depends testCreateEnumColumn + // * @depends testCreateDatetimeColumn // * @throws Exception // */ // public function testCreateCustomEntity(): array @@ -969,13 +969,13 @@ class DatabaseServerTest extends Scope } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testGetCollections($data): void + public function testGetTables($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_COLLECTIONS); + $query = $this->getQuery(self::$GET_TABLES); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -990,17 +990,17 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $tables['body']); $this->assertIsArray($tables['body']['data']); - $this->assertIsArray($tables['body']['data']['databasesListCollections']); + $this->assertIsArray($tables['body']['data']['databasesListTables']); } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testGetCollection($data): void + public function testGetTable($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_COLLECTION); + $query = $this->getQuery(self::$GET_TABLE); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -1016,18 +1016,18 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $table['body']); $this->assertIsArray($table['body']['data']); - $this->assertIsArray($table['body']['data']['databasesGetCollection']); + $this->assertIsArray($table['body']['data']['databasesGetTable']); } /** - * @depends testUpdateStringAttribute - * @depends testUpdateIntegerAttribute + * @depends testUpdateStringColumn + * @depends testUpdateIntegerColumn * @throws Exception */ - public function testGetAttributes($data): void + public function testGetColumns($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_ATTRIBUTES); + $query = $this->getQuery(self::$GET_COLUMNS); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -1043,17 +1043,17 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $columns['body']); $this->assertIsArray($columns['body']['data']); - $this->assertIsArray($columns['body']['data']['collectionsListAttributes']); + $this->assertIsArray($columns['body']['data']['tablesListColumns']); } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testGetAttribute($data): void + public function testGetColumn($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_ATTRIBUTE); + $query = $this->getQuery(self::$GET_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -1070,7 +1070,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $column['body']); $this->assertIsArray($column['body']['data']); - $this->assertIsArray($column['body']['data']['collectionsGetAttribute']); + $this->assertIsArray($column['body']['data']['tablesGetColumn']); } /** @@ -1080,7 +1080,7 @@ class DatabaseServerTest extends Scope public function testGetIndexes($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_INDEXES); + $query = $this->getQuery(self::$GET_COLUMN_INDEXES); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -1096,7 +1096,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $indices['body']); $this->assertIsArray($indices['body']['data']); - $this->assertIsArray($indices['body']['data']['collectionsListIndexes']); + $this->assertIsArray($indices['body']['data']['tablesListIndexes']); } /** @@ -1106,7 +1106,7 @@ class DatabaseServerTest extends Scope public function testGetIndex($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_INDEX); + $query = $this->getQuery(self::$GET_COLUMN_INDEX); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -1123,17 +1123,17 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $index['body']); $this->assertIsArray($index['body']['data']); - $this->assertIsArray($index['body']['data']['collectionsGetIndex']); + $this->assertIsArray($index['body']['data']['tablesGetIndex']); } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testGetDocuments($data): void + public function testGetRows($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_DOCUMENTS); + $query = $this->getQuery(self::$GET_ROWS); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -1149,17 +1149,17 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $rows['body']); $this->assertIsArray($rows['body']['data']); - $this->assertIsArray($rows['body']['data']['collectionsListDocuments']); + $this->assertIsArray($rows['body']['data']['tablesListRows']); } /** - * @depends testCreateDocument + * @depends testCreateRow * @throws Exception */ - public function testGetDocument($data): void + public function testGetRow($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$GET_DOCUMENT); + $query = $this->getQuery(self::$GET_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -1176,7 +1176,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $row['body']); $this->assertIsArray($row['body']['data']); - $this->assertIsArray($row['body']['data']['collectionsGetDocument']); + $this->assertIsArray($row['body']['data']['tablesGetRow']); } // /** @@ -1253,19 +1253,19 @@ class DatabaseServerTest extends Scope } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testUpdateCollection($data) + public function testUpdateTable($data) { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_COLLECTION); + $query = $this->getQuery(self::$UPDATE_TABLE); $gqlPayload = [ 'query' => $query, 'variables' => [ 'databaseId' => $data['database']['_id'], 'tableId' => $data['table']['_id'], - 'name' => 'New Collection Name', + 'name' => 'New Table Name', 'rowSecurity' => false, ] ]; @@ -1277,17 +1277,17 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $table['body']); $this->assertIsArray($table['body']['data']); - $this->assertIsArray($table['body']['data']['databasesUpdateCollection']); + $this->assertIsArray($table['body']['data']['databasesUpdateTable']); } /** - * @depends testCreateDocument + * @depends testCreateRow * @throws Exception */ - public function testUpdateDocument($data): void + public function testUpdateRow($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$UPDATE_DOCUMENT); + $query = $this->getQuery(self::$UPDATE_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -1295,7 +1295,7 @@ class DatabaseServerTest extends Scope 'tableId' => $data['table']['_id'], 'rowId' => $data['row']['_id'], 'data' => [ - 'name' => 'New Document Name', + 'name' => 'New Row Name', ], ] ]; @@ -1307,9 +1307,9 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $row['body']); $this->assertIsArray($row['body']['data']); - $row = $row['body']['data']['collectionsUpdateDocument']; + $row = $row['body']['data']['tablesUpdateRow']; $this->assertIsArray($row); - $this->assertStringContainsString('New Document Name', $row['data']); + $this->assertStringContainsString('New Row Name', $row['data']); } // /** @@ -1341,13 +1341,13 @@ class DatabaseServerTest extends Scope // } /** - * @depends testCreateDocument + * @depends testCreateRow * @throws Exception */ - public function testDeleteDocument($data): void + public function testDeleteRow($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$DELETE_DOCUMENT); + $query = $this->getQuery(self::$DELETE_ROW); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -1391,13 +1391,13 @@ class DatabaseServerTest extends Scope // } /** - * @depends testUpdateStringAttribute + * @depends testUpdateStringColumn * @throws Exception */ - public function testDeleteAttribute($data): void + public function testDeleteColumn($data): void { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$DELETE_ATTRIBUTE); + $query = $this->getQuery(self::$DELETE_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ @@ -1417,13 +1417,13 @@ class DatabaseServerTest extends Scope } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws Exception */ - public function testDeleteCollection($data) + public function testDeleteTable($data) { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$DELETE_COLLECTION); + $query = $this->getQuery(self::$DELETE_TABLE); $gqlPayload = [ 'query' => $query, 'variables' => [ From 68994f263490e129ceeacda491be42f9e57331e2 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 10:19:01 +0530 Subject: [PATCH 115/343] fix: graphql tests. --- tests/e2e/Services/GraphQL/Base.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 65154e2f93..8cad67b909 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -82,17 +82,17 @@ trait Base public static string $GET_COLUMN = 'get_column'; public static string $DELETE_COLUMN = 'delete_column'; - // Collection Indexes - public static string $CREATE_INDEX = 'create_index'; - public static string $GET_INDEXES = 'get_indexes'; - public static string $GET_INDEX = 'get_index'; - public static string $DELETE_INDEX = 'delete_index'; + // Attribute Indexes + public static string $CREATE_INDEX = 'create_attribute_index'; + public static string $GET_INDEXES = 'get_attribute_indexes'; + public static string $GET_INDEX = 'get_attribute_index'; + public static string $DELETE_INDEX = 'delete_attribute_index'; // Column Indexes - public static string $CREATE_COLUMN_INDEX = 'create_index'; - public static string $GET_COLUMN_INDEXES = 'get_indexes'; - public static string $GET_COLUMN_INDEX = 'get_index'; - public static string $DELETE_COLUMN_INDEX = 'delete_index'; + public static string $CREATE_COLUMN_INDEX = 'create_column_index'; + public static string $GET_COLUMN_INDEXES = 'get_column_indexes'; + public static string $GET_COLUMN_INDEX = 'get_column_index'; + public static string $DELETE_COLUMN_INDEX = 'delete_column_index'; // Documents public static string $CREATE_DOCUMENT = 'create_document_rest'; @@ -995,8 +995,8 @@ trait Base } }'; case self::$CREATE_COLUMN_INDEX: - return 'mutation createIndex($databaseId: String!, $tableId: String!, $key: String!, $type: String!, $attributes: [String!]!, $orders: [String!]){ - tablesCreateIndex(databaseId: $databaseId, tableId: $tableId, key: $key, type: $type, attributes: $attributes, orders: $orders) { + return 'mutation createIndex($databaseId: String!, $tableId: String!, $key: String!, $type: String!, $columns: [String!]!, $orders: [String!]){ + tablesCreateIndex(databaseId: $databaseId, tableId: $tableId, key: $key, type: $type, columns: $columns, orders: $orders) { key type status From 5022a052ce10ed4db669a2cf687615718bc48b7e Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 10:20:23 +0530 Subject: [PATCH 116/343] update: test coverage for databases. --- .github/workflows/tests.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 335e46c16b..a7fc1cf0c6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -145,8 +145,7 @@ jobs: Account, Avatars, Console, - Databases/Collections, - Databases/Tables, + Databases, Functions, FunctionsSchedule, GraphQL, @@ -214,8 +213,7 @@ jobs: Account, Avatars, Console, - Databases/Collections, - Databases/Tables, + Databases, Functions, FunctionsSchedule, GraphQL, From fbe2609f7b9561b207ba96f8fa1721e6a6da763d Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 10:34:44 +0530 Subject: [PATCH 117/343] update: simplify setting events context param. --- .../Collections/Attributes/Action.php | 20 +++++++++++++------ .../Collections/Attributes/Delete.php | 9 ++++----- .../Collections/Documents/Action.php | 8 ++++++++ .../Collections/Documents/Create.php | 8 ++++---- .../Collections/Documents/Delete.php | 8 ++++---- .../Collections/Documents/Update.php | 8 ++++---- .../Databases/Collections/Indexes/Action.php | 8 ++++++++ .../Databases/Collections/Indexes/Create.php | 4 ++-- .../Databases/Collections/Indexes/Delete.php | 4 ++-- 9 files changed, 50 insertions(+), 27 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 954e997872..095b679223 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -204,6 +204,14 @@ abstract class Action extends UtopiaAction : Exception::COLUMN_NOT_AVAILABLE; } + /** + * Get the correct collections context for Events queue. + */ + final protected function getCollectionsEventsContext(): string + { + return $this->isCollectionsAPI() ? 'collection' : 'table'; + } + /** * Get the proper column/attribute type based on set context. */ @@ -407,11 +415,11 @@ abstract class Action extends UtopiaAction $queueForEvents ->setContext('database', $db) ->setParam('databaseId', $databaseId) + ->setParam('collectionId', $collection->getId()) + ->setParam('tableId', $collection->getId()) ->setParam('attributeId', $attribute->getId()) ->setParam('columnId', $attribute->getId()) - ->setParam('tableId', $collection->getId()) - ->setParam('collectionId', $collection->getId()) - ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); + ->setContext($this->getCollectionsEventsContext(), $collection); $response->setStatusCode(SwooleResponse::STATUS_CODE_CREATED); @@ -608,11 +616,11 @@ abstract class Action extends UtopiaAction $queueForEvents ->setContext('database', $db) ->setParam('databaseId', $databaseId) + ->setParam('collectionId', $collection->getId()) + ->setParam('tableId', $collection->getId()) ->setParam('attributeId', $attribute->getId()) ->setParam('columnId', $attribute->getId()) - ->setParam('tableId', $collection->getId()) - ->setParam('collectionId', $collection->getId()) - ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); + ->setContext($this->getCollectionsEventsContext(), $collection); return $attribute; } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 81bc77a9ba..cf5b7766b3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -145,13 +145,12 @@ class Delete extends Action $queueForEvents ->setContext('database', $db) ->setParam('databaseId', $databaseId) - ->setPayload($response->output($attribute, $model)) - ->setParam('attributeId', $attribute->getId()) - ->setParam('columnId', $attribute->getId()) ->setParam('collectionId', $collection->getId()) ->setParam('tableId', $collection->getId()) - // set proper context - ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); + ->setParam('attributeId', $attribute->getId()) + ->setParam('columnId', $attribute->getId()) + ->setPayload($response->output($attribute, $model)) + ->setContext($this->getCollectionsEventsContext(), $collection); $response->noContent(); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index a5b8fc5805..01ee2d9f84 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -127,4 +127,12 @@ abstract class Action extends UtopiaAction ? Exception::DOCUMENT_MISSING_PAYLOAD : Exception::ROW_MISSING_PAYLOAD; } + + /** + * Get the correct collections context for Events queue. + */ + final protected function getCollectionsEventsContext(): string + { + return $this->isCollectionsAPI() ? 'collection' : 'table'; + } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index a8f1561f84..bd59c9ee35 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -309,11 +309,11 @@ class Create extends Action $queueForEvents ->setParam('databaseId', $databaseId) ->setContext('database', $database) - ->setParam('rowId', $document->getId()) - ->setParam('documentId', $document->getId()) - ->setParam('tableId', $collection->getId()) ->setParam('collectionId', $collection->getId()) + ->setParam('tableId', $collection->getId()) + ->setParam('documentId', $document->getId()) + ->setParam('rowId', $document->getId()) ->setPayload($response->getPayload(), sensitive: $relationships) - ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); + ->setContext($this->getCollectionsEventsContext(), $collection); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index 66e1b37320..c218e713bf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -164,11 +164,11 @@ class Delete extends Action $queueForEvents ->setParam('databaseId', $databaseId) ->setContext('database', $database) - ->setParam('rowId', $document->getId()) - ->setParam('documentId', $document->getId()) - ->setParam('tableId', $collection->getId()) ->setParam('collectionId', $collection->getId()) - ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection) + ->setParam('tableId', $collection->getId()) + ->setParam('documentId', $document->getId()) + ->setParam('rowId', $document->getId()) + ->setContext($this->getCollectionsEventsContext(), $collection) ->setPayload($response->output($document, $this->getResponseModel()), sensitive: $relationships); $response->noContent(); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index 5bee2ee761..17da8e552d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -297,11 +297,11 @@ class Update extends Action $queueForEvents ->setParam('databaseId', $databaseId) ->setContext('database', $database) - ->setParam('rowId', $document->getId()) - ->setParam('documentId', $document->getId()) - ->setParam('tableId', $collection->getId()) ->setParam('collectionId', $collection->getId()) - ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection) + ->setParam('tableId', $collection->getId()) + ->setParam('documentId', $document->getId()) + ->setParam('rowId', $document->getId()) + ->setContext($this->getCollectionsEventsContext(), $collection) ->setPayload($response->getPayload(), sensitive: $relationships); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php index 93459440f0..c1e3f61114 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php @@ -152,4 +152,12 @@ abstract class Action extends UtopiaAction ? Exception::ATTRIBUTE_NOT_AVAILABLE : Exception::COLUMN_NOT_AVAILABLE; } + + /** + * Get the correct collections context for Events queue. + */ + final protected function getCollectionsEventsContext(): string + { + return $this->isCollectionsAPI() ? 'collection' : 'table'; + } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index 014627e0a8..c18ab69b10 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -221,9 +221,9 @@ class Create extends Action ->setContext('database', $db) ->setParam('databaseId', $databaseId) ->setParam('indexId', $index->getId()) - ->setParam('tableId', $collection->getId()) ->setParam('collectionId', $collection->getId()) - ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); + ->setParam('tableId', $collection->getId()) + ->setContext($this->getCollectionsEventsContext(), $collection); $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index f86cf7b11f..a208e059f6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -118,8 +118,8 @@ class Delete extends Action ->setParam('indexId', $index->getId()) ->setParam('tableId', $collection->getId()) ->setParam('collectionId', $collection->getId()) - ->setPayload($response->output($index, $this->getResponseModel())) - ->setContext($this->isCollectionsAPI() ? 'collection' : 'table', $collection); + ->setContext($this->getCollectionsEventsContext(), $collection) + ->setPayload($response->output($index, $this->getResponseModel())); $response->noContent(); } From 5dca1ff0d624b5b9378fef397269190a28238e81 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 10:36:16 +0530 Subject: [PATCH 118/343] update: fix test variable. --- .../Tables/DatabasesPermissionsMemberTest.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php index 7b0e9d8a64..32a97aeadf 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php @@ -136,9 +136,9 @@ class DatabasesPermissionsMemberTest extends Scope 'rowSecurity' => true, ]); $this->assertEquals(201, $public['headers']['status-code']); - $this->collections = ['public' => $public['body']['$id']]; + $this->tables = ['public' => $public['body']['$id']]; - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $this->collections['public'] . '/columns/string', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $this->tables['public'] . '/columns/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -157,9 +157,9 @@ class DatabasesPermissionsMemberTest extends Scope 'rowSecurity' => true, ]); $this->assertEquals(201, $private['headers']['status-code']); - $this->collections['private'] = $private['body']['$id']; + $this->tables['private'] = $private['body']['$id']; - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $this->collections['private'] . '/columns/string', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $this->tables['private'] . '/columns/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -173,9 +173,9 @@ class DatabasesPermissionsMemberTest extends Scope 'rowSecurity' => true, ]); $this->assertEquals(201, $private['headers']['status-code']); - $this->collections['doconly'] = $doconly['body']['$id']; + $this->tables['doconly'] = $doconly['body']['$id']; - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $this->collections['doconly'] . '/columns/string', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $this->tables['doconly'] . '/columns/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -186,7 +186,7 @@ class DatabasesPermissionsMemberTest extends Scope return [ 'users' => $this->users, - 'tables' => $this->collections, + 'tables' => $this->tables, 'databaseId' => $databaseId ]; } From 45370f91c3b93e0373d8982ae481de90bfafd638 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 10:52:43 +0530 Subject: [PATCH 119/343] add: table apis to webhook tests. --- tests/e2e/Services/Webhooks/WebhooksBase.php | 352 ++++++++++++++++++- 1 file changed, 351 insertions(+), 1 deletion(-) diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index c743810feb..b26f964479 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -36,7 +36,7 @@ trait WebhooksBase return base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); } - + // Collection APIs public function testCreateCollection(): array { /** @@ -389,6 +389,356 @@ trait WebhooksBase return $data; } + // Table APIs + public function testCreateTable(): array + { + /** + * Create database + */ + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'Actors DB', + ]); + + $databaseId = $database['body']['$id']; + + /** + * Test for SUCCESS + */ + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Actors', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'rowSecurity' => true, + ]); + + $actorsId = $actors['body']['$id']; + + $this->assertEquals($actors['headers']['status-code'], 201); + $this->assertNotEmpty($actors['body']['$id']); + + $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); + + $this->assertEquals($webhook['method'], 'POST'); + $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); + $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); + $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); + $this->assertNotEmpty($webhook['data']['$id']); + $this->assertEquals($webhook['data']['name'], 'Actors'); + $this->assertIsArray($webhook['data']['$permissions']); + $this->assertCount(4, $webhook['data']['$permissions']); + + return array_merge(['actorsId' => $actorsId, 'databaseId' => $databaseId]); + } + + /** + * @depends testCreateTable + */ + public function testCreateColumns(array $data): array + { + $actorsId = $data['actorsId']; + $databaseId = $data['databaseId']; + + $firstName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actorsId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'firstName', + 'size' => 256, + 'required' => true, + ]); + + $lastName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actorsId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'lastName', + 'size' => 256, + 'required' => true, + ]); + + $extra = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actorsId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'extra', + 'size' => 64, + 'required' => false, + ]); + + $this->assertEquals($firstName['headers']['status-code'], 202); + $this->assertEquals($firstName['body']['key'], 'firstName'); + $this->assertEquals($lastName['headers']['status-code'], 202); + $this->assertEquals($lastName['body']['key'], 'lastName'); + $this->assertEquals($extra['headers']['status-code'], 202); + $this->assertEquals($extra['body']['key'], 'extra'); + + // wait for database worker to kick in + sleep(10); + + $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); + + $this->assertEquals($webhook['method'], 'POST'); + $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); + $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.columns.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.columns.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.columns.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.columns.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); + $this->assertNotEmpty($webhook['data']['key']); + $this->assertEquals($webhook['data']['key'], 'extra'); + + $removed = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['actorsId'] . '/columns/' . $extra['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(204, $removed['headers']['status-code']); + + $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); + + // $this->assertEquals($webhook['method'], 'DELETE'); + $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); + $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.columns.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.columns.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.columns.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.columns.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); + $this->assertNotEmpty($webhook['data']['key']); + $this->assertEquals($webhook['data']['key'], 'extra'); + + return $data; + } + + /** + * @depends testCreateColumns + */ + public function testCreateRow(array $data): array + { + $actorsId = $data['actorsId']; + $databaseId = $data['databaseId']; + + /** + * Test for SUCCESS + */ + $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actorsId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'firstName' => 'Chris', + 'lastName' => 'Evans', + ], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $documentId = $row['body']['$id']; + + $this->assertEquals($row['headers']['status-code'], 201); + $this->assertNotEmpty($row['body']['$id']); + + $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); + + $this->assertEquals($webhook['method'], 'POST'); + $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); + $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); + $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); + $this->assertNotEmpty($webhook['data']['$id']); + $this->assertEquals($webhook['data']['firstName'], 'Chris'); + $this->assertEquals($webhook['data']['lastName'], 'Evans'); + $this->assertIsArray($webhook['data']['$permissions']); + $this->assertCount(3, $webhook['data']['$permissions']); + + $data['rowId'] = $row['body']['$id']; + + return $data; + } + + /** + * @depends testCreateRow + */ + public function testUpdateRow(array $data): array + { + $actorsId = $data['actorsId']; + $databaseId = $data['databaseId']; + + /** + * Test for SUCCESS + */ + $document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $actorsId . '/rows/' . $data['rowId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'firstName' => 'Chris1', + 'lastName' => 'Evans2', + ], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $rowId = $document['body']['$id']; + + $this->assertEquals($document['headers']['status-code'], 200); + $this->assertNotEmpty($document['body']['$id']); + + $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); + + $this->assertEquals($webhook['method'], 'POST'); + $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); + $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$rowId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$rowId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$rowId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$rowId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); + $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); + $this->assertNotEmpty($webhook['data']['$id']); + $this->assertEquals($webhook['data']['firstName'], 'Chris1'); + $this->assertEquals($webhook['data']['lastName'], 'Evans2'); + $this->assertIsArray($webhook['data']['$permissions']); + $this->assertCount(3, $webhook['data']['$permissions']); + + return $data; + } + + /** + * @depends testCreateTable + */ + #[Retry(count: 1)] + public function testDeleteRow(array $data): array + { + $actorsId = $data['actorsId']; + $databaseId = $data['databaseId']; + + /** + * Test for SUCCESS + */ + $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actorsId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'firstName' => 'Bradly', + 'lastName' => 'Cooper', + + ], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $rowId = $row['body']['$id']; + + $this->assertEquals($row['headers']['status-code'], 201); + $this->assertNotEmpty($row['body']['$id']); + + $row = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $actorsId . '/rows/' . $row['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals($row['headers']['status-code'], 204); + + $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); + + $this->assertEquals($webhook['method'], 'POST'); + $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); + $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.rows.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$rowId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.*.rows.{$rowId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$rowId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.rows.{$rowId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); + $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); + $this->assertNotEmpty($webhook['data']['$id']); + $this->assertEquals($webhook['data']['firstName'], 'Bradly'); + $this->assertEquals($webhook['data']['lastName'], 'Cooper'); + $this->assertIsArray($webhook['data']['$permissions']); + $this->assertCount(3, $webhook['data']['$permissions']); + + return $data; + } public function testCreateStorageBucket(): array { From afa8341f9584cf347da93ac2f817e78af6a35a94 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 11:01:36 +0530 Subject: [PATCH 120/343] add: table apis to webhook custom server tests. --- .../Webhooks/WebhooksCustomServerTest.php | 351 ++++++++++++++---- 1 file changed, 269 insertions(+), 82 deletions(-) diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php index d2f132e960..6fe184b03f 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php @@ -19,6 +19,7 @@ class WebhooksCustomServerTest extends Scope use ProjectCustom; use SideServer; + // Collection APIs /** * @depends testCreateAttributes */ @@ -39,15 +40,15 @@ class WebhooksCustomServerTest extends Scope 'documentSecurity' => true, ]); - $this->assertEquals($actors['headers']['status-code'], 200); + $this->assertEquals(200, $actors['headers']['status-code']); $this->assertNotEmpty($actors['body']['$id']); $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -55,9 +56,9 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); - $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); + $this->assertTrue(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? '')); $this->assertNotEmpty($webhook['data']['$id']); - $this->assertEquals($webhook['data']['name'], 'Actors1'); + $this->assertEquals('Actors1', $webhook['data']['name']); $this->assertIsArray($webhook['data']['$permissions']); $this->assertCount(4, $webhook['data']['$permissions']); @@ -84,8 +85,8 @@ class WebhooksCustomServerTest extends Scope ]); $indexKey = $index['body']['key']; - $this->assertEquals($index['headers']['status-code'], 202); - $this->assertEquals($index['body']['key'], 'fullname'); + $this->assertEquals(202, $index['headers']['status-code']); + $this->assertEquals('fullname', $index['body']['key']); // wait for database worker to create index sleep(5); @@ -93,9 +94,9 @@ class WebhooksCustomServerTest extends Scope $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -105,7 +106,7 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); - $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); + $this->assertTrue(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? '')); // Remove index $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['actorsId'] . '/indexes/' . $index['body']['key'], array_merge([ @@ -119,8 +120,8 @@ class WebhooksCustomServerTest extends Scope $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); // $this->assertEquals($webhook['method'], 'DELETE'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.indexes.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -130,7 +131,7 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); - $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); + $this->assertTrue(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? '')); return $data; } @@ -172,7 +173,7 @@ class WebhooksCustomServerTest extends Scope $id = $actors['body']['$id']; - $this->assertEquals($actors['headers']['status-code'], 201); + $this->assertEquals(201, $actors['headers']['status-code']); $this->assertNotEmpty($actors['body']['$id']); $actors = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'], array_merge([ @@ -181,14 +182,14 @@ class WebhooksCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), []); - $this->assertEquals($actors['headers']['status-code'], 204); + $this->assertEquals(204, $actors['headers']['status-code']); $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); $this->assertStringContainsString('databases.' . $databaseId . '.collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('databases.' . $databaseId . '.collections.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("databases.{$databaseId}.collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -196,9 +197,195 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); - $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); + $this->assertTrue(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? '')); $this->assertNotEmpty($webhook['data']['$id']); - $this->assertEquals($webhook['data']['name'], 'Demo'); + $this->assertEquals('Demo', $webhook['data']['name']); + $this->assertIsArray($webhook['data']['$permissions']); + $this->assertCount(4, $webhook['data']['$permissions']); + + return []; + } + + // Table APIs + /** + * @depends testCreateColumns + */ + public function testUpdateTable($data): array + { + $id = $data['actorsId']; + $databaseId = $data['databaseId']; + + /** + * Test for SUCCESS + */ + $actors = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'name' => 'Actors1', + 'rowSecurity' => true, + ]); + + $this->assertEquals(200, $actors['headers']['status-code']); + $this->assertNotEmpty($actors['body']['$id']); + + $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); + + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); + $this->assertEmpty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''); + $this->assertNotEmpty($webhook['data']['$id']); + $this->assertEquals('Actors1', $webhook['data']['name']); + $this->assertIsArray($webhook['data']['$permissions']); + $this->assertCount(4, $webhook['data']['$permissions']); + + return array_merge(['actorsId' => $actors['body']['$id']]); + } + + /** + * @depends testCreateColumns + */ + public function testCreateDeleteColumnIndexes($data): array + { + $actorsId = $data['actorsId']; + $databaseId = $data['databaseId']; + + $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['actorsId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'fullname', + 'type' => 'key', + 'columns' => ['lastName', 'firstName'], + 'orders' => ['ASC', 'ASC'], + ]); + + $this->assertEquals(202, $index['headers']['status-code']); + $this->assertEquals('fullname', $index['body']['key']); + + // wait for database worker to create index + sleep(5); + + $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); + + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.indexes.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.indexes.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); + $this->assertTrue(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? '')); + + // Remove index + $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['actorsId'] . '/indexes/' . $index['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + // // wait for database worker to remove index + $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); + + // $this->assertEquals($webhook['method'], 'DELETE'); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.indexes.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.indexes.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.indexes.*", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$actorsId}.indexes.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); + $this->assertTrue(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? '')); + + return $data; + } + + public function testDeleteTable(): array + { + /** + * Create database + */ + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], $this->getHeaders()), [ + 'databaseId' => ID::unique(), + 'name' => 'Actors DB', + ]); + + $databaseId = $database['body']['$id']; + + /** + * Test for SUCCESS + */ + $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Demo', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'rowSecurity' => true, + ]); + + $id = $actors['body']['$id']; + + $this->assertEquals(201, $actors['headers']['status-code']); + $this->assertNotEmpty($actors['body']['$id']); + + $actors = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(204, $actors['headers']['status-code']); + + $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); + + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString('databases.' . $databaseId . '.tables.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertStringContainsString("databases.{$databaseId}.tables.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); + $this->assertEmpty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''); + $this->assertNotEmpty($webhook['data']['$id']); + $this->assertEquals('Demo', $webhook['data']['name']); $this->assertIsArray($webhook['data']['$permissions']); $this->assertCount(4, $webhook['data']['$permissions']); @@ -224,7 +411,7 @@ class WebhooksCustomServerTest extends Scope 'name' => $name, ]); - $this->assertEquals($user['headers']['status-code'], 201); + $this->assertEquals(201, $user['headers']['status-code']); $this->assertNotEmpty($user['body']['$id']); $id = $user['body']['$id']; @@ -232,9 +419,9 @@ class WebhooksCustomServerTest extends Scope $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); $this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('users.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -245,11 +432,11 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); $this->assertNotEmpty($webhook['data']['$id']); $this->assertEquals($webhook['data']['name'], $name); - $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['registration'])); - $this->assertEquals($webhook['data']['status'], true); + $this->assertTrue((new DatetimeValidator())->isValid($webhook['data']['registration'])); + $this->assertTrue($webhook['data']['status']); $this->assertEquals($webhook['data']['email'], $email); - $this->assertEquals($webhook['data']['emailVerification'], false); - $this->assertEquals($webhook['data']['prefs'], []); + $this->assertFalse($webhook['data']['emailVerification']); + $this->assertEquals([], $webhook['data']['prefs']); /** * Test for FAILURE @@ -274,15 +461,15 @@ class WebhooksCustomServerTest extends Scope 'prefs' => ['a' => 'b'] ]); - $this->assertEquals($user['headers']['status-code'], 200); - $this->assertEquals($user['body']['a'], 'b'); + $this->assertEquals(200, $user['headers']['status-code']); + $this->assertEquals('b', $user['body']['a']); $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); $this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('users.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('users.*.update.prefs', $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -293,7 +480,7 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); - $this->assertEquals($webhook['data']['a'], 'b'); + $this->assertEquals('b', $webhook['data']['a']); return $data; } @@ -315,15 +502,15 @@ class WebhooksCustomServerTest extends Scope 'status' => false, ]); - $this->assertEquals($user['headers']['status-code'], 200); + $this->assertEquals(200, $user['headers']['status-code']); $this->assertNotEmpty($user['body']['$id']); $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); $this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('users.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('users.*.update.status', $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -336,11 +523,11 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); $this->assertNotEmpty($webhook['data']['$id']); $this->assertEquals($webhook['data']['name'], $data['name']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['registration'])); - $this->assertEquals($webhook['data']['status'], false); + $this->assertTrue((new DatetimeValidator())->isValid($webhook['data']['registration'])); + $this->assertFalse($webhook['data']['status']); $this->assertEquals($webhook['data']['email'], $data['email']); - $this->assertEquals($webhook['data']['emailVerification'], false); - $this->assertEquals($webhook['data']['prefs']['a'], 'b'); + $this->assertFalse($webhook['data']['emailVerification']); + $this->assertEquals('b', $webhook['data']['prefs']['a']); return $data; } @@ -360,14 +547,14 @@ class WebhooksCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals($user['headers']['status-code'], 204); + $this->assertEquals(204, $user['headers']['status-code']); $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); $this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('users.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -378,11 +565,11 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); $this->assertNotEmpty($webhook['data']['$id']); $this->assertEquals($webhook['data']['name'], $data['name']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['registration'])); - $this->assertEquals($webhook['data']['status'], false); + $this->assertTrue((new DatetimeValidator())->isValid($webhook['data']['registration'])); + $this->assertFalse($webhook['data']['status']); $this->assertEquals($webhook['data']['email'], $data['email']); - $this->assertEquals($webhook['data']['emailVerification'], false); - $this->assertEquals($webhook['data']['prefs']['a'], 'b'); + $this->assertFalse($webhook['data']['emailVerification']); + $this->assertEquals('b', $webhook['data']['prefs']['a']); return $data; } @@ -406,15 +593,15 @@ class WebhooksCustomServerTest extends Scope $id = $function['body']['$id'] ?? ''; - $this->assertEquals($function['headers']['status-code'], 201); + $this->assertEquals(201, $function['headers']['status-code']); $this->assertNotEmpty($function['body']['$id']); $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -447,7 +634,7 @@ class WebhooksCustomServerTest extends Scope ] ]); - $this->assertEquals($function['headers']['status-code'], 200); + $this->assertEquals(200, $function['headers']['status-code']); $this->assertEquals($function['body']['$id'], $data['functionId']); // Create variable @@ -464,9 +651,9 @@ class WebhooksCustomServerTest extends Scope $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); // $this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString('functions.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -504,15 +691,15 @@ class WebhooksCustomServerTest extends Scope $functionId = $data['functionId'] ?? ''; $deploymentId = $deployment['body']['$id'] ?? ''; - $this->assertEquals($deployment['headers']['status-code'], 202); + $this->assertEquals(202, $deployment['headers']['status-code']); $this->assertNotEmpty($deployment['body']['$id']); $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); // $this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString('functions.*.deployments.*', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString("functions.*.deployments.{$deploymentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -544,7 +731,7 @@ class WebhooksCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); - $this->assertEquals($response['headers']['status-code'], 200); + $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); // Wait for deployment to be built. @@ -553,9 +740,9 @@ class WebhooksCustomServerTest extends Scope $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); // $this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString('functions.*.deployments.*', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString('functions.*.deployments.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -596,14 +783,14 @@ class WebhooksCustomServerTest extends Scope $executionId = $execution['body']['$id'] ?? ''; - $this->assertEquals($execution['headers']['status-code'], 202); + $this->assertEquals(202, $execution['headers']['status-code']); $this->assertNotEmpty($execution['body']['$id']); $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); // $this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString('functions.*.executions.*', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString('functions.*.executions.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -624,9 +811,9 @@ class WebhooksCustomServerTest extends Scope $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); // $this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString('functions.*.executions.*', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString('functions.*.executions.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -663,15 +850,15 @@ class WebhooksCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals($deployment['headers']['status-code'], 204); + $this->assertEquals(204, $deployment['headers']['status-code']); $this->assertEmpty($deployment['body']); $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); // $this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString('functions.*.deployments.*', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString('functions.*.deployments.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); @@ -714,9 +901,9 @@ class WebhooksCustomServerTest extends Scope $webhook = $this->getLastRequest(); $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); - $this->assertEquals($webhook['method'], 'POST'); - $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); - $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); + $this->assertEquals('POST', $webhook['method']); + $this->assertEquals('application/json', $webhook['headers']['Content-Type']); + $this->assertEquals('Appwrite-Server vdev. Please report abuse at security@appwrite.io', $webhook['headers']['User-Agent']); // $this->assertStringContainsString('functions.*', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString('functions.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); // $this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); From 6bdfe3b8955dfac773fab926619c32fe9ef1654b Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 11:34:20 +0530 Subject: [PATCH 121/343] address naming comments. --- .../Tables/DatabasesConsoleClientTest.php | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/e2e/Services/Databases/Tables/DatabasesConsoleClientTest.php b/tests/e2e/Services/Databases/Tables/DatabasesConsoleClientTest.php index 087ece167f..8a8d8de170 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesConsoleClientTest.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesConsoleClientTest.php @@ -16,7 +16,7 @@ class DatabasesConsoleClientTest extends Scope use ProjectCustom; use SideConsole; - public function testCreateCollection(): array + public function testCreateTable(): array { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -50,10 +50,10 @@ class DatabasesConsoleClientTest extends Scope ]); $this->assertEquals(201, $movies['headers']['status-code']); - $this->assertEquals($movies['body']['name'], 'Movies'); + $this->assertEquals('Movies', $movies['body']['name']); /** - * Test when database is disabled but can still create collections + * Test when database is disabled but can still create tables */ $database = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId, array_merge([ 'content-type' => 'application/json', @@ -81,7 +81,7 @@ class DatabasesConsoleClientTest extends Scope ]); /** - * Test when collection is disabled but can still modify collections + * Test when table is disabled but can still modify tables */ $database = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $movies['body']['$id'], array_merge([ 'content-type' => 'application/json', @@ -92,20 +92,20 @@ class DatabasesConsoleClientTest extends Scope ]); $this->assertEquals(201, $tvShows['headers']['status-code']); - $this->assertEquals($tvShows['body']['name'], 'TvShows'); + $this->assertEquals('TvShows', $tvShows['body']['name']); return ['moviesId' => $movies['body']['$id'], 'databaseId' => $databaseId, 'tvShowsId' => $tvShows['body']['$id']]; } /** - * @depends testCreateCollection + * @depends testCreateTable * @param array $data * @throws \Exception */ - public function testListCollection(array $data) + public function testListTable(array $data) { /** - * Test when database is disabled but can still call list collections + * Test when database is disabled but can still call list tables */ $databaseId = $data['databaseId']; @@ -119,17 +119,17 @@ class DatabasesConsoleClientTest extends Scope } /** - * @depends testCreateCollection + * @depends testCreateTable * @param array $data * @throws \Exception */ - public function testGetCollection(array $data) + public function testGetTable(array $data) { $databaseId = $data['databaseId']; $moviesCollectionId = $data['moviesId']; /** - * Test when database and collection are disabled but can still call get collection + * Test when database and table are disabled but can still call get table */ $table = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $moviesCollectionId, array_merge([ 'content-type' => 'application/json', @@ -143,18 +143,18 @@ class DatabasesConsoleClientTest extends Scope } /** - * @depends testCreateCollection + * @depends testCreateTable * @param array $data * @throws \Exception * @throws \Exception */ - public function testUpdateCollection(array $data) + public function testUpdateTable(array $data) { $databaseId = $data['databaseId']; $moviesCollectionId = $data['moviesId']; /** - * Test When database and collection are disabled but can still call update collection + * Test When database and table are disabled but can still call update table */ $table = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $moviesCollectionId, array_merge([ 'content-type' => 'application/json', @@ -171,18 +171,18 @@ class DatabasesConsoleClientTest extends Scope } /** - * @depends testCreateCollection + * @depends testCreateTable * @param array $data * @throws \Exception * @throws \Exception */ - public function testDeleteCollection(array $data) + public function testDeleteTable(array $data) { $databaseId = $data['databaseId']; $tvShowsId = $data['tvShowsId']; /** - * Test when database and collection are disabled but can still call delete collection + * Test when database and table are disabled but can still call delete table */ $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tvShowsId, array_merge([ 'content-type' => 'application/json', @@ -190,11 +190,11 @@ class DatabasesConsoleClientTest extends Scope ], $this->getHeaders())); $this->assertEquals(204, $response['headers']['status-code']); - $this->assertEquals($response['body'], ""); + $this->assertEquals("", $response['body']); } /** - * @depends testCreateCollection + * @depends testCreateTable */ public function testGetDatabaseUsage(array $data) { @@ -226,7 +226,7 @@ class DatabasesConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(15, count($response['body'])); + $this->assertCount(15, $response['body']); $this->assertEquals('24h', $response['body']['range']); $this->assertIsNumeric($response['body']['rowsTotal']); $this->assertIsNumeric($response['body']['tablesTotal']); @@ -236,9 +236,9 @@ class DatabasesConsoleClientTest extends Scope /** - * @depends testCreateCollection + * @depends testCreateTable */ - public function testGetCollectionUsage(array $data) + public function testGetTableUsage(array $data) { $databaseId = $data['databaseId']; /** @@ -280,10 +280,10 @@ class DatabasesConsoleClientTest extends Scope } /** - * @depends testCreateCollection + * @depends testCreateTable * @throws \Utopia\Database\Exception\Query */ - public function testGetCollectionLogs(array $data) + public function testGetTableLogs(array $data) { $databaseId = $data['databaseId']; /** From 15e0385723f7e7d3a11dd07065cf7ae181cb7435 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 11:36:13 +0530 Subject: [PATCH 122/343] update: exception name. --- .../Databases/Http/Databases/Collections/Indexes/Action.php | 2 +- .../Databases/Http/Databases/Collections/Indexes/Create.php | 2 +- .../Databases/Http/Databases/Collections/Indexes/Delete.php | 2 +- .../Databases/Http/Databases/Collections/Indexes/Get.php | 2 +- .../Databases/Http/Databases/Collections/Indexes/XList.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php index c1e3f61114..07a32ce122 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php @@ -86,7 +86,7 @@ abstract class Action extends UtopiaAction /** * Get the appropriate grandparent level not found exception. */ - final protected function getGrantParentNotFoundException(): string + final protected function getGrandParentNotFoundException(): string { return $this->isCollectionsAPI() ? Exception::COLLECTION_NOT_FOUND diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index c18ab69b10..a963640597 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -89,7 +89,7 @@ class Create extends Action if ($collection->isEmpty()) { // table or collection. - throw new Exception($this->getGrantParentNotFoundException()); + throw new Exception($this->getGrandParentNotFoundException()); } $count = $dbForProject->count('indexes', [ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index a208e059f6..70df7c4f7a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -82,7 +82,7 @@ class Delete extends Action if ($collection->isEmpty()) { // table or collection. - throw new Exception($this->getGrantParentNotFoundException()); + throw new Exception($this->getGrandParentNotFoundException()); } $index = $dbForProject->getDocument('indexes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php index fa10406f2a..466d6fa99e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php @@ -71,7 +71,7 @@ class Get extends Action if ($collection->isEmpty()) { // table or collection. - throw new Exception($this->getGrantParentNotFoundException()); + throw new Exception($this->getGrandParentNotFoundException()); } $index = $collection->find('key', $key, 'indexes'); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index 733e6854b2..d44c80b393 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -77,7 +77,7 @@ class XList extends Action if ($collection->isEmpty()) { // table or collection. - throw new Exception($this->getGrantParentNotFoundException()); + throw new Exception($this->getGrandParentNotFoundException()); } $queries = Query::parseQueries($queries); From 9ba29d47799f10902e5ae8074fcfbdfd26d6aecb Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 11:36:55 +0530 Subject: [PATCH 123/343] update: var name. --- tests/e2e/Services/GraphQL/Base.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 8cad67b909..aa90502163 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -25,8 +25,8 @@ trait Base public static string $CREATE_TABLE = 'create_table'; public static string $GET_TABLE = 'get_table'; public static string $GET_TABLES = 'list_tables'; - public static string $UPDATE_TABLE = 'update_tables'; - public static string $DELETE_TABLE = 'delete_tables'; + public static string $UPDATE_TABLE = 'update_table'; + public static string $DELETE_TABLE = 'delete_table'; // Attributes public static string $CREATE_STRING_ATTRIBUTE = 'create_string_attribute'; From e50d7df56ca8616c3d464b59a3045c70e316d28d Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 11:38:28 +0530 Subject: [PATCH 124/343] fix: audits event. --- .../Databases/Http/Databases/Collections/Documents/Create.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index bd59c9ee35..d6c9960a5b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -51,7 +51,7 @@ class Create extends Action ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].create') ->label('scope', 'documents.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'row.create') + ->label('audits.event', 'document.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) From 63d591e7664ee8ba0921ae3b46c72a69d4f3d37a Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 11:39:46 +0530 Subject: [PATCH 125/343] fix: method name. --- tests/e2e/Services/GraphQL/Tables/AbuseTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Services/GraphQL/Tables/AbuseTest.php b/tests/e2e/Services/GraphQL/Tables/AbuseTest.php index 80bde907f9..623d4ff783 100644 --- a/tests/e2e/Services/GraphQL/Tables/AbuseTest.php +++ b/tests/e2e/Services/GraphQL/Tables/AbuseTest.php @@ -29,7 +29,7 @@ class AbuseTest extends Scope public function testRateLimitEnforced() { - $data = $this->createCollection(); + $data = $this->createTable(); $databaseId = $data['databaseId']; $tableId = $data['tableId']; $projectId = $this->getProject()['$id']; @@ -114,7 +114,7 @@ class AbuseTest extends Scope $this->assertEquals('Too many queries.', $response['body']['message']); } - private function createCollection(): array + private function createTable(): array { $projectId = $this->getProject()['$id']; $query = $this->getQuery(self::$CREATE_DATABASE); From b0d9215ea5ba68e1b20bf28b59950dfc16fb3393 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 11:57:32 +0530 Subject: [PATCH 126/343] fix: abuse tests! --- tests/e2e/Services/GraphQL/Base.php | 256 +++++++++++++++++- .../GraphQL/Collections/AbuseTest.php | 2 +- .../e2e/Services/GraphQL/Tables/AbuseTest.php | 8 +- 3 files changed, 255 insertions(+), 11 deletions(-) diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index aa90502163..f050fa9638 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -306,7 +306,8 @@ trait Base public static string $UPDATE_PUSH_NOTIFICATION = 'update_push_notification'; // Complex queries - public static string $COMPLEX_QUERY = 'complex_query'; + public static string $COMPLEX_QUERY_TABLE = 'complex_query_table'; + public static string $COMPLEX_QUERY_COLLECTION = 'complex_query_collection'; // Attribute Fragments public static string $FRAGMENT_ATTRIBUTES = ' @@ -2689,7 +2690,7 @@ trait Base status } }'; - case self::$COMPLEX_QUERY: + case self::$COMPLEX_QUERY_COLLECTION: return 'mutation complex($databaseId: String!, $databaseName: String!, $collectionId: String!, $collectionName: String!, $documentSecurity: Boolean!, $collectionPermissions: [String!]!) { databasesCreate(databaseId: $databaseId, name: $databaseName) { _id @@ -2700,7 +2701,7 @@ trait Base _createdAt _updatedAt _permissions - _databaseId + databaseId name documentSecurity attributes { @@ -2712,7 +2713,7 @@ trait Base status } } - databasesCreateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "name", size: 255, required: true) { + collectionsCreateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "name", size: 255, required: true) { key type status @@ -2721,7 +2722,7 @@ trait Base default array } - databasesCreateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "age", min: 0, max: 150, required: true) { + collectionsCreateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "age", min: 0, max: 150, required: true) { key type status @@ -2731,7 +2732,7 @@ trait Base default array } - databasesCreateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "alive", required: false, default: true) { + collectionsCreateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "alive", required: false, default: true) { key type status @@ -2932,6 +2933,249 @@ trait Base } } }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; + case self::$COMPLEX_QUERY_TABLE: + return 'mutation complex($databaseId: String!, $databaseName: String!, $tableId: String!, $tableName: String!, $rowSecurity: Boolean!, $tablePermissions: [String!]!) { + databasesCreate(databaseId: $databaseId, name: $databaseName) { + _id + name + } + databasesCreateTable(databaseId: $databaseId, tableId: $tableId, name: $tableName, rowSecurity: $rowSecurity, permissions: $tablePermissions) { + _id + _createdAt + _updatedAt + _permissions + databaseId + name + rowSecurity + columns { + ...columnProperties + } + indexes { + key + type + status + } + } + tablesCreateStringColumn(databaseId: $databaseId, tableId: $tableId, key: "name", size: 255, required: true) { + key + type + status + size + required + default + array + } + tablesCreateIntegerColumn(databaseId: $databaseId, tableId: $tableId, key: "age", min: 0, max: 150, required: true) { + key + type + status + required + min + max + default + array + } + tablesCreateBooleanColumn(databaseId: $databaseId, tableId: $tableId, key: "alive", required: false, default: true) { + key + type + status + required + default + array + } + user1: usersCreate(userId: "unique()", email: "test1@appwrite.io", password: "password", name: "Tester 1") { + _id + _createdAt + _updatedAt + name + phone + email + status + registration + passwordUpdate + emailVerification + phoneVerification + prefs { + data + } + } + user2: usersCreate(userId: "unique()", email: "test2@appwrite.io", password: "password", name: "Tester 2") { + _id + _createdAt + _updatedAt + name + phone + email + status + registration + passwordUpdate + emailVerification + phoneVerification + prefs { + data + } + } + user3: usersCreate(userId: "unique()", email: "test3@appwrite.io", password: "password", name: "Tester 3") { + _id + _createdAt + _updatedAt + name + phone + email + status + registration + passwordUpdate + emailVerification + phoneVerification + prefs { + data + } + } + user4: usersCreate(userId: "unique()", email: "test4@appwrite.io", password: "password", name: "Tester 4") { + _id + _createdAt + _updatedAt + name + phone + email + status + registration + passwordUpdate + emailVerification + phoneVerification + prefs { + data + } + } + user5: usersCreate(userId: "unique()", email: "test5@appwrite.io", password: "password", name: "Tester 5") { + _id + _createdAt + _updatedAt + name + phone + email + status + registration + passwordUpdate + emailVerification + phoneVerification + prefs { + data + } + } + user6: usersCreate(userId: "unique()", email: "test6@appwrite.io", password: "password", name: "Tester 6") { + _id + _createdAt + _updatedAt + name + phone + email + status + registration + passwordUpdate + emailVerification + phoneVerification + prefs { + data + } + } + user7: usersCreate(userId: "unique()", email: "test7@appwrite.io", password: "password", name: "Tester 7") { + _id + _createdAt + _updatedAt + name + phone + email + status + registration + passwordUpdate + emailVerification + phoneVerification + prefs { + data + } + } + user8: usersCreate(userId: "unique()", email: "test8@appwrite.io", password: "password", name: "Tester 8") { + _id + _createdAt + _updatedAt + name + phone + email + status + registration + passwordUpdate + emailVerification + phoneVerification + prefs { + data + } + } + user9: usersCreate(userId: "unique()", email: "test9@appwrite.io", password: "password", name: "Tester 9") { + _id + _createdAt + _updatedAt + name + phone + email + status + registration + passwordUpdate + emailVerification + phoneVerification + prefs { + data + } + } + user10: usersCreate(userId: "unique()", email: "test10@appwrite.io", password: "password", name: "Tester 10") { + _id + _createdAt + _updatedAt + name + phone + email + status + registration + passwordUpdate + emailVerification + phoneVerification + prefs { + data + } + } + user11: usersCreate(userId: "unique()", email: "test11@appwrite.io", password: "password", name: "Tester 11") { + _id + _createdAt + _updatedAt + name + phone + email + status + registration + passwordUpdate + emailVerification + phoneVerification + prefs { + data + } + } + user12: usersCreate(userId: "unique()", email: "test12@appwrite.io", password: "password", name: "Tester 5") { + _id + _createdAt + _updatedAt + name + phone + email + status + registration + passwordUpdate + emailVerification + phoneVerification + prefs { + data + } + } + }' . PHP_EOL . self::$FRAGMENT_COLUMNS; } throw new \InvalidArgumentException('Invalid query type'); diff --git a/tests/e2e/Services/GraphQL/Collections/AbuseTest.php b/tests/e2e/Services/GraphQL/Collections/AbuseTest.php index a45bebd714..a58a57ec5a 100644 --- a/tests/e2e/Services/GraphQL/Collections/AbuseTest.php +++ b/tests/e2e/Services/GraphQL/Collections/AbuseTest.php @@ -65,7 +65,7 @@ class AbuseTest extends Scope public function testComplexQueryBlocked() { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$COMPLEX_QUERY); + $query = $this->getQuery(self::$COMPLEX_QUERY_COLLECTION); $graphQLPayload = [ 'query' => $query, 'variables' => [ diff --git a/tests/e2e/Services/GraphQL/Tables/AbuseTest.php b/tests/e2e/Services/GraphQL/Tables/AbuseTest.php index 623d4ff783..abb5019d55 100644 --- a/tests/e2e/Services/GraphQL/Tables/AbuseTest.php +++ b/tests/e2e/Services/GraphQL/Tables/AbuseTest.php @@ -65,7 +65,7 @@ class AbuseTest extends Scope public function testComplexQueryBlocked() { $projectId = $this->getProject()['$id']; - $query = $this->getQuery(self::$COMPLEX_QUERY); + $query = $this->getQuery(self::$COMPLEX_QUERY_TABLE); $graphQLPayload = [ 'query' => $query, 'variables' => [ @@ -75,8 +75,8 @@ class AbuseTest extends Scope 'databaseId' => 'database', 'databaseName' => 'database', 'tableId' => 'table', - 'collectionName' => 'table', - 'collectionPermissions' => [ + 'tableName' => 'table', + 'tablePermissions' => [ Permission::read(Role::users()), Permission::create(Role::users()), Permission::update(Role::users()), @@ -157,7 +157,7 @@ class AbuseTest extends Scope $tableId = $response['body']['data']['databasesCreateTable']['_id']; - $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); + $query = $this->getQuery(self::$CREATE_STRING_COLUMN); $gqlPayload = [ 'query' => $query, 'variables' => [ From 087ccfe347c03e7148c80045dc527e48e112c9bc Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 10 May 2025 12:06:17 +0530 Subject: [PATCH 127/343] remove: todo. --- app/config/scopes.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/config/scopes.php b/app/config/scopes.php index d459ffb2fc..7dea7b1cd5 100644 --- a/app/config/scopes.php +++ b/app/config/scopes.php @@ -1,6 +1,5 @@ [ 'description' => 'Access to create, update, and delete user sessions', From 0f677376907f21e605dd816d2d7ff2ef449dd3c7 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 13 May 2025 17:49:31 +0530 Subject: [PATCH 128/343] change: color. --- app/config/locale/templates/email-inner-base.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/locale/templates/email-inner-base.tpl b/app/config/locale/templates/email-inner-base.tpl index c17e37ab8a..64fbdd33b1 100644 --- a/app/config/locale/templates/email-inner-base.tpl +++ b/app/config/locale/templates/email-inner-base.tpl @@ -1,6 +1,6 @@

    {{hello}}

    {{body}}

    -
    +

    {{buttonText}}

    {{footer}}

    {{thanks}} From 6530d31e7a00c88ec57bb4992017d5636cbba9b2 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Wed, 4 Jun 2025 14:07:43 +0530 Subject: [PATCH 129/343] Use ->action(...)) --- src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php | 2 +- .../Platform/Modules/Functions/Http/Deployments/Create.php | 2 +- .../Platform/Modules/Functions/Http/Deployments/Delete.php | 2 +- .../Modules/Functions/Http/Deployments/Download/Get.php | 2 +- .../Modules/Functions/Http/Deployments/Duplicate/Create.php | 2 +- .../Platform/Modules/Functions/Http/Deployments/Get.php | 2 +- .../Modules/Functions/Http/Deployments/Status/Update.php | 2 +- .../Modules/Functions/Http/Deployments/Template/Create.php | 2 +- .../Platform/Modules/Functions/Http/Deployments/Vcs/Create.php | 2 +- .../Platform/Modules/Functions/Http/Deployments/XList.php | 2 +- .../Platform/Modules/Functions/Http/Executions/Create.php | 2 +- .../Platform/Modules/Functions/Http/Executions/Delete.php | 2 +- src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php | 2 +- .../Platform/Modules/Functions/Http/Executions/XList.php | 2 +- .../Platform/Modules/Functions/Http/Functions/Create.php | 2 +- .../Platform/Modules/Functions/Http/Functions/Delete.php | 2 +- .../Modules/Functions/Http/Functions/Deployment/Update.php | 2 +- src/Appwrite/Platform/Modules/Functions/Http/Functions/Get.php | 2 +- .../Platform/Modules/Functions/Http/Functions/Update.php | 2 +- .../Platform/Modules/Functions/Http/Functions/XList.php | 2 +- src/Appwrite/Platform/Modules/Functions/Http/Runtimes/XList.php | 2 +- .../Platform/Modules/Functions/Http/Specifications/XList.php | 2 +- src/Appwrite/Platform/Modules/Functions/Http/Templates/Get.php | 2 +- .../Platform/Modules/Functions/Http/Templates/XList.php | 2 +- src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php | 2 +- src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php | 2 +- .../Platform/Modules/Functions/Http/Variables/Create.php | 2 +- .../Platform/Modules/Functions/Http/Variables/Delete.php | 2 +- src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php | 2 +- .../Platform/Modules/Functions/Http/Variables/Update.php | 2 +- .../Platform/Modules/Functions/Http/Variables/XList.php | 2 +- src/Appwrite/Platform/Modules/Functions/Workers/Builds.php | 2 +- src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php | 2 +- src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php | 2 +- src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php | 2 +- src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php | 2 +- src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php | 2 +- src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php | 2 +- .../Platform/Modules/Proxy/Http/Rules/Function/Create.php | 2 +- .../Platform/Modules/Proxy/Http/Rules/Redirect/Create.php | 2 +- src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php | 2 +- .../Platform/Modules/Sites/Http/Deployments/Download/Get.php | 2 +- .../Modules/Sites/Http/Deployments/Duplicate/Create.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Deployments/Get.php | 2 +- .../Platform/Modules/Sites/Http/Deployments/Status/Update.php | 2 +- .../Platform/Modules/Sites/Http/Deployments/Template/Create.php | 2 +- .../Platform/Modules/Sites/Http/Deployments/Vcs/Create.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Frameworks/XList.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Sites/Delete.php | 2 +- .../Platform/Modules/Sites/Http/Sites/Deployment/Update.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Sites/Get.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php | 2 +- .../Platform/Modules/Sites/Http/Specifications/XList.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Templates/Get.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Templates/XList.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Variables/XList.php | 2 +- .../Modules/Tokens/Http/Tokens/Buckets/Files/Create.php | 2 +- .../Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php | 2 +- src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Delete.php | 2 +- src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Get.php | 2 +- src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Update.php | 2 +- src/Appwrite/Platform/Tasks/Doctor.php | 2 +- src/Appwrite/Platform/Tasks/Install.php | 2 +- src/Appwrite/Platform/Tasks/Maintenance.php | 2 +- src/Appwrite/Platform/Tasks/QueueRetry.php | 2 +- src/Appwrite/Platform/Tasks/SDKs.php | 2 +- src/Appwrite/Platform/Tasks/SSL.php | 2 +- src/Appwrite/Platform/Tasks/Screenshot.php | 2 +- src/Appwrite/Platform/Tasks/StatsResources.php | 2 +- src/Appwrite/Platform/Tasks/Upgrade.php | 2 +- src/Appwrite/Platform/Tasks/Vars.php | 2 +- src/Appwrite/Platform/Workers/Audits.php | 2 +- src/Appwrite/Platform/Workers/Databases.php | 2 +- src/Appwrite/Platform/Workers/Functions.php | 2 +- src/Appwrite/Platform/Workers/Mails.php | 2 +- src/Appwrite/Platform/Workers/Messaging.php | 2 +- src/Appwrite/Platform/Workers/Migrations.php | 2 +- src/Appwrite/Platform/Workers/StatsResources.php | 2 +- src/Appwrite/Platform/Workers/StatsUsage.php | 2 +- src/Appwrite/Platform/Workers/StatsUsageDump.php | 2 +- src/Appwrite/Platform/Workers/Webhooks.php | 2 +- 95 files changed, 95 insertions(+), 95 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index 16a94dc00c..114a24ef22 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -57,7 +57,7 @@ class Get extends Action ->param('type', '', new WhiteList(['rules']), 'Resource type.') ->inject('response') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php index 1f3febbfef..202f98924d 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php @@ -87,7 +87,7 @@ class Create extends Action ->inject('deviceForLocal') ->inject('queueForBuilds') ->inject('plan') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php index 84878055d8..0e51141b65 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php @@ -62,7 +62,7 @@ class Delete extends Action ->inject('queueForDeletes') ->inject('queueForEvents') ->inject('deviceForFunctions') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php index 9456ff13a6..9c338d571a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php @@ -61,7 +61,7 @@ class Get extends Action ->inject('dbForProject') ->inject('deviceForFunctions') ->inject('deviceForBuilds') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php index 8f739dd37f..ebbf8e6b8c 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php @@ -62,7 +62,7 @@ class Create extends Action ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('deviceForFunctions') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Get.php index e9c5240f5c..a79da7f908 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Get.php @@ -49,7 +49,7 @@ class Get extends Action ->param('deploymentId', '', new UID(), 'Deployment ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php index c5436d1d05..897a334567 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php @@ -59,7 +59,7 @@ class Update extends Action ->inject('project') ->inject('queueForEvents') ->inject('executor') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php index 55230bd4a5..5d8eb4585e 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php @@ -75,7 +75,7 @@ class Create extends Base ->inject('project') ->inject('queueForBuilds') ->inject('gitHub') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php index 48f3894bb2..0ad9852722 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php @@ -72,7 +72,7 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php index 38f1f38e89..c055d57c70 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php @@ -57,7 +57,7 @@ class XList extends Action ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index fd1b2076a8..b170be3fac 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -94,7 +94,7 @@ class Create extends Base ->inject('queueForFunctions') ->inject('geodb') ->inject('executor') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php index cd85b5e534..dc5aebd4ed 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php @@ -62,7 +62,7 @@ class Delete extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php index 892ce30f47..84764eea24 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php @@ -52,7 +52,7 @@ class Get extends Base ->param('executionId', '', new UID(), 'Execution ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index a31e95b1c8..a73a5e6189 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -58,7 +58,7 @@ class XList extends Base ->param('queries', [], new Executions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Executions::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php index fd8da657eb..07a02d33d5 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php @@ -114,7 +114,7 @@ class Create extends Base ->inject('dbForPlatform') ->inject('request') ->inject('gitHub') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php index 91da68538c..72d5589252 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php @@ -61,7 +61,7 @@ class Delete extends Base ->inject('queueForDeletes') ->inject('queueForEvents') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index e840441774..82c154840a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -62,7 +62,7 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Get.php index 9ce6560fd0..e8da162b8a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Get.php @@ -49,7 +49,7 @@ class Get extends Base ->param('functionId', '', new UID(), 'Function ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php index a19ec1e278..23ce3bc78b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php @@ -104,7 +104,7 @@ class Update extends Base ->inject('dbForPlatform') ->inject('gitHub') ->inject('executor') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php index cd0eba2c50..4b03a5b6cc 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php @@ -56,7 +56,7 @@ class XList extends Base ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Runtimes/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Runtimes/XList.php index bfccff0479..0690d1a139 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Runtimes/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Runtimes/XList.php @@ -47,7 +47,7 @@ class XList extends Base ] )) ->inject('response') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(Response $response) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Specifications/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Specifications/XList.php index 39186e7ab7..4c059b09d0 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Specifications/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Specifications/XList.php @@ -48,7 +48,7 @@ class XList extends Base )) ->inject('response') ->inject('plan') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(Response $response, array $plan) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Templates/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Templates/Get.php index 237898f6fa..f66322839b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Templates/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Templates/Get.php @@ -49,7 +49,7 @@ class Get extends Base )) ->param('templateId', '', new Text(128), 'Template ID.') ->inject('response') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $templateId, Response $response) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php index 05b54a75d0..86e7f21362 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php @@ -53,7 +53,7 @@ class XList extends Base ->param('limit', 25, new Range(1, 5000), 'Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.', true) ->param('offset', 0, new Range(0, 5000), 'Offset the list of returned templates. Maximum offset is 5000.', true) ->inject('response') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(array $runtimes, array $usecases, int $limit, int $offset, Response $response) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php index e0d659c9ba..7a50e2ab78 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php @@ -55,7 +55,7 @@ class Get extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $functionId, string $range, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php index e64fe9a600..6a4ded4db7 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php @@ -52,7 +52,7 @@ class XList extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $range, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php index 9300524c64..2b6941c48b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php @@ -65,7 +65,7 @@ class Create extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('project') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php index 3d6bfebcb9..e9bdf77df1 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php @@ -57,7 +57,7 @@ class Delete extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php index 70cc66219a..e5c01c72ad 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php @@ -53,7 +53,7 @@ class Get extends Base ->param('variableId', '', new UID(), 'Variable unique ID.', false) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $functionId, string $variableId, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php index 4102022267..15c2ad816c 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php @@ -61,7 +61,7 @@ class Update extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/XList.php index 9c02cfe07c..29465b7572 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/XList.php @@ -53,7 +53,7 @@ class XList extends Base ->param('functionId', '', new UID(), 'Function unique ID.', false) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $functionId, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index de5543c9f3..f1b24f601d 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -75,7 +75,7 @@ class Builds extends Action ->inject('log') ->inject('executor') ->inject('plan') - ->callback([$this, 'action']); + ->callback($this->action(...)); } /** diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php index 43f7d4ac02..e534769bb2 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php @@ -57,7 +57,7 @@ class Create extends Action ->inject('user') ->inject('response') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $projectId, string $name, ?string $expire, Document $user, Response $response, Database $dbForPlatform) diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php index f6cb966f50..71bd7d96d2 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php @@ -49,7 +49,7 @@ class Delete extends Action ->param('keyId', '', new UID(), 'Key unique ID.') ->inject('response') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $projectId, string $keyId, Response $response, Database $dbForPlatform) diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php index bd472b26e7..0440748b7b 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php @@ -49,7 +49,7 @@ class Get extends Action ->param('keyId', '', new UID(), 'Key unique ID.') ->inject('response') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $projectId, string $keyId, Response $response, Database $dbForPlatform) diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php index d5e6839174..cb2498e68c 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php @@ -52,7 +52,7 @@ class Update extends Action ->param('expire', null, new DatetimeValidator(), 'Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format.') ->inject('response') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $projectId, string $keyId, string $name, ?string $expire, Response $response, Database $dbForPlatform) { diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php index 864531d32d..17029c5a36 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php @@ -53,7 +53,7 @@ class XList extends Action ->param('queries', [], new DevKeys(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', DevKeys::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $projectId, ?array $queries, Response $response, Database $dbForPlatform) diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php index e4d0d2899f..f459672268 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php @@ -66,7 +66,7 @@ class Create extends Action ->inject('queueForCertificates') ->inject('queueForEvents') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $domain, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform) diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php index 6c5a87a68d..b77f78bf67 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php @@ -71,7 +71,7 @@ class Create extends Action ->inject('queueForEvents') ->inject('dbForPlatform') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $domain, string $functionId, string $branch, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php index d0c9dbbbe3..1cb671a76a 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php @@ -70,7 +70,7 @@ class Create extends Action ->inject('queueForCertificates') ->inject('queueForEvents') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $domain, string $url, int $statusCode, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform) diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php index 894c954a32..830fade45c 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php @@ -71,7 +71,7 @@ class Create extends Action ->inject('queueForEvents') ->inject('dbForPlatform') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $domain, string $siteId, string $branch, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index d78d43aec7..380d418fd1 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -86,7 +86,7 @@ class Create extends Action ->inject('deviceForLocal') ->inject('queueForBuilds') ->inject('plan') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php index 27db10c484..64c26bb4d7 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php @@ -62,7 +62,7 @@ class Delete extends Action ->inject('queueForDeletes') ->inject('queueForEvents') ->inject('deviceForSites') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php index e83af0bab6..9c05f3f3fd 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php @@ -60,7 +60,7 @@ class Get extends Action ->inject('dbForProject') ->inject('deviceForSites') ->inject('deviceForBuilds') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php index bff0735328..e12777f9d5 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -65,7 +65,7 @@ class Create extends Action ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('deviceForSites') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Get.php index d280231159..d583c62fb1 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Get.php @@ -49,7 +49,7 @@ class Get extends Action ->param('deploymentId', '', new UID(), 'Deployment ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $siteId, string $deploymentId, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php index 2c6da43893..51ee252609 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php @@ -57,7 +57,7 @@ class Update extends Action ->inject('project') ->inject('queueForEvents') ->inject('executor') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php index 5b29521ce5..fc0ea5898c 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -77,7 +77,7 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php index eb6fdf4094..ddad5d793a 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php @@ -72,7 +72,7 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php index d7cfc1d3ad..d709c26ab2 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php @@ -57,7 +57,7 @@ class XList extends Action ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $siteId, array $queries, string $search, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Frameworks/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Frameworks/XList.php index cf2bb8c62b..a042fd6e7c 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Frameworks/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Frameworks/XList.php @@ -46,7 +46,7 @@ class XList extends Base ] )) ->inject('response') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(Response $response) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php index a411cee91f..cfb35163af 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php @@ -55,7 +55,7 @@ class Delete extends Base ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $siteId, string $logId, Response $response, Database $dbForProject, Event $queueForEvents) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php index 3d1ace2d20..bcfbd715e1 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php @@ -50,7 +50,7 @@ class Get extends Base ->param('logId', '', new UID(), 'Log ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $siteId, string $logId, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php index a873d32603..79cd49b724 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php @@ -57,7 +57,7 @@ class XList extends Base ->param('queries', [], new Logs(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Executions::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $siteId, array $queries, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php index c509799024..1bc9e11c3e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php @@ -89,7 +89,7 @@ class Create extends Base ->inject('project') ->inject('queueForEvents') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Delete.php index 37666215e5..ed9b059c33 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Delete.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Delete.php @@ -58,7 +58,7 @@ class Delete extends Base ->inject('dbForProject') ->inject('queueForDeletes') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index a54d0c7889..227e7a6982 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -60,7 +60,7 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Get.php index 88ff5f1d51..d86d98ef71 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Get.php @@ -49,7 +49,7 @@ class Get extends Base ->param('siteId', '', new UID(), 'Site ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $siteId, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php index 212b410178..b7e140f3ad 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php @@ -97,7 +97,7 @@ class Update extends Base ->inject('dbForPlatform') ->inject('gitHub') ->inject('executor') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php index 0a3b257f59..988a2d2e20 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php @@ -56,7 +56,7 @@ class XList extends Base ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(array $queries, string $search, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Specifications/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Specifications/XList.php index 2a9447f8c6..a76f067114 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Specifications/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Specifications/XList.php @@ -48,7 +48,7 @@ class XList extends Base )) ->inject('response') ->inject('plan') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(Response $response, array $plan) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Templates/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Templates/Get.php index a4066fb787..633ef31e68 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Templates/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Templates/Get.php @@ -49,7 +49,7 @@ class Get extends Base )) ->param('templateId', '', new Text(128), 'Template ID.') ->inject('response') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $templateId, Response $response) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Templates/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Templates/XList.php index 414ecc9987..4fe00f3edf 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Templates/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Templates/XList.php @@ -53,7 +53,7 @@ class XList extends Base ->param('limit', 25, new Range(1, 5000), 'Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.', true) ->param('offset', 0, new Range(0, 5000), 'Offset the list of returned templates. Maximum offset is 5000.', true) ->inject('response') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php index 8bf19a9c28..f969f5b3af 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php @@ -55,7 +55,7 @@ class Get extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php index e37d3e792e..d36cc56ae5 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php @@ -52,7 +52,7 @@ class XList extends Base ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $range, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php index ff1a5c50ec..aa17298cf0 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php @@ -62,7 +62,7 @@ class Create extends Base ->inject('response') ->inject('dbForProject') ->inject('project') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $siteId, string $key, string $value, bool $secret, Response $response, Database $dbForProject, Document $project) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php index e4594a7c3d..840464535f 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php @@ -54,7 +54,7 @@ class Delete extends Base ->param('variableId', '', new UID(), 'Variable unique ID.', false) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $siteId, string $variableId, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php index a14129d432..964453e348 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php @@ -53,7 +53,7 @@ class Get extends Base ->param('variableId', '', new UID(), 'Variable unique ID.', false) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $siteId, string $variableId, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php index cd438a0ebb..aba375c471 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php @@ -58,7 +58,7 @@ class Update extends Base ->param('secret', null, new Boolean(), 'Secret variables can be updated or deleted, but only sites can read them during build and runtime.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/XList.php index 15e21296a5..51ab355c75 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Variables/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/XList.php @@ -53,7 +53,7 @@ class XList extends Base ->param('siteId', '', new UID(), 'Site unique ID.', false) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php index fb96849ed2..3f8ef96b92 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php @@ -65,7 +65,7 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $bucketId, string $fileId, ?string $expire, Response $response, Database $dbForProject, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php index 38fe10e2d9..214707177b 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php @@ -55,7 +55,7 @@ class XList extends Action ->param('queries', [], new FileTokens(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', FileTokens::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $bucketId, string $fileId, array $queries, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Delete.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Delete.php index fcac9a6b24..c36df367ee 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Delete.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Delete.php @@ -58,7 +58,7 @@ class Delete extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $tokenId, Response $response, Database $dbForProject, Event $queueForEvents) diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Get.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Get.php index 66b9c1b5cb..4da9e125f2 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Get.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Get.php @@ -50,7 +50,7 @@ class Get extends Action ->param('tokenId', '', new UID(), 'Token ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $tokenId, Response $response, Database $dbForProject) diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Update.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Update.php index c341831c0d..7a15708011 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Update.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Update.php @@ -61,7 +61,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $tokenId, ?string $expire, Response $response, Database $dbForProject, Event $queueForEvents) diff --git a/src/Appwrite/Platform/Tasks/Doctor.php b/src/Appwrite/Platform/Tasks/Doctor.php index b543555477..20eeb0826e 100644 --- a/src/Appwrite/Platform/Tasks/Doctor.php +++ b/src/Appwrite/Platform/Tasks/Doctor.php @@ -34,7 +34,7 @@ class Doctor extends Action $this ->desc('Validate server health') ->inject('register') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(Registry $register): void diff --git a/src/Appwrite/Platform/Tasks/Install.php b/src/Appwrite/Platform/Tasks/Install.php index c7b1f72453..c3b4e33593 100644 --- a/src/Appwrite/Platform/Tasks/Install.php +++ b/src/Appwrite/Platform/Tasks/Install.php @@ -31,7 +31,7 @@ class Install extends Action ->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true) ->param('interactive', 'Y', new Text(1), 'Run an interactive session', true) ->param('no-start', false, new Boolean(true), 'Run an interactive session', true) - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive, bool $noStart): void diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index fd9d05dec9..d3776129e7 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -27,7 +27,7 @@ class Maintenance extends Action ->inject('console') ->inject('queueForCertificates') ->inject('queueForDeletes') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(Database $dbForPlatform, Document $console, Certificate $queueForCertificates, Delete $queueForDeletes): void diff --git a/src/Appwrite/Platform/Tasks/QueueRetry.php b/src/Appwrite/Platform/Tasks/QueueRetry.php index f8099dcb00..442fa39823 100644 --- a/src/Appwrite/Platform/Tasks/QueueRetry.php +++ b/src/Appwrite/Platform/Tasks/QueueRetry.php @@ -24,7 +24,7 @@ class QueueRetry extends Action ->param('name', '', new Text(100), 'Queue name') ->param('limit', 0, new Wildcard(), 'jobs limit', true) ->inject('publisher') - ->callback([$this, 'action']); + ->callback($this->action(...)); } /** diff --git a/src/Appwrite/Platform/Tasks/SDKs.php b/src/Appwrite/Platform/Tasks/SDKs.php index a0009fd59f..2d3fad383e 100644 --- a/src/Appwrite/Platform/Tasks/SDKs.php +++ b/src/Appwrite/Platform/Tasks/SDKs.php @@ -46,7 +46,7 @@ class SDKs extends Action ->param('git', null, new Nullable(new WhiteList(['yes', 'no'])), 'Should we use git push?', optional: true) ->param('production', null, new Nullable(new WhiteList(['yes', 'no'])), 'Should we push to production?', optional: true) ->param('message', null, new Nullable(new Text(256)), 'Commit Message', optional: true) - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(?string $selectedPlatform, ?string $selectedSDK, ?string $version, ?string $git, ?string $production, ?string $message): void diff --git a/src/Appwrite/Platform/Tasks/SSL.php b/src/Appwrite/Platform/Tasks/SSL.php index ae1c93a360..651cb4de11 100644 --- a/src/Appwrite/Platform/Tasks/SSL.php +++ b/src/Appwrite/Platform/Tasks/SSL.php @@ -24,7 +24,7 @@ class SSL extends Action ->param('domain', System::getEnv('_APP_DOMAIN', ''), new Hostname(), 'Domain to generate certificate for. If empty, main domain will be used.', true) ->param('skip-check', true, new Boolean(true), 'If DNS and renew check should be skipped. Defaults to true, and when true, all jobs will result in certificate generation attempt.', true) ->inject('queueForCertificates') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $domain, bool|string $skipCheck, Certificate $queueForCertificates): void diff --git a/src/Appwrite/Platform/Tasks/Screenshot.php b/src/Appwrite/Platform/Tasks/Screenshot.php index 3a9c9a64f5..5a4d8a76b7 100644 --- a/src/Appwrite/Platform/Tasks/Screenshot.php +++ b/src/Appwrite/Platform/Tasks/Screenshot.php @@ -21,7 +21,7 @@ class Screenshot extends Action $this ->desc('Create Site template screenshot') ->param('templateId', '', new Text(128), 'Template ID.') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $templateId): void diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index ca2a6860ff..dce26d2180 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -45,7 +45,7 @@ class StatsResources extends Action ->inject('dbForPlatform') ->inject('logError') ->inject('queueForStatsResources') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(Database $dbForPlatform, callable $logError, EventStatsResources $queue): void diff --git a/src/Appwrite/Platform/Tasks/Upgrade.php b/src/Appwrite/Platform/Tasks/Upgrade.php index dfd10d347e..d6159d2718 100644 --- a/src/Appwrite/Platform/Tasks/Upgrade.php +++ b/src/Appwrite/Platform/Tasks/Upgrade.php @@ -23,7 +23,7 @@ class Upgrade extends Install ->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true) ->param('interactive', 'Y', new Text(1), 'Run an interactive session', true) ->param('no-start', false, new Boolean(true), 'Run an interactive session', true) - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive, bool $noStart): void diff --git a/src/Appwrite/Platform/Tasks/Vars.php b/src/Appwrite/Platform/Tasks/Vars.php index 70ae550ef9..542b5bdc9f 100644 --- a/src/Appwrite/Platform/Tasks/Vars.php +++ b/src/Appwrite/Platform/Tasks/Vars.php @@ -18,7 +18,7 @@ class Vars extends Action { $this ->desc('List all the server environment variables') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(): void diff --git a/src/Appwrite/Platform/Workers/Audits.php b/src/Appwrite/Platform/Workers/Audits.php index 76309145b8..aadb58f971 100644 --- a/src/Appwrite/Platform/Workers/Audits.php +++ b/src/Appwrite/Platform/Workers/Audits.php @@ -47,7 +47,7 @@ class Audits extends Action ->inject('message') ->inject('getProjectDB') ->inject('project') - ->callback([$this, 'action']); + ->callback($this->action(...)); $this->lastTriggeredTime = time(); } diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index b2691b420e..30f9fef5b6 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -38,7 +38,7 @@ class Databases extends Action ->inject('dbForProject') ->inject('queueForRealtime') ->inject('log') - ->callback([$this, 'action']); + ->callback($this->action(...)); } /** diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index c8c68a58ba..d42de68178 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -53,7 +53,7 @@ class Functions extends Action ->inject('log') ->inject('executor') ->inject('isResourceBlocked') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Workers/Mails.php b/src/Appwrite/Platform/Workers/Mails.php index 3a15182e51..4e8b5e085c 100644 --- a/src/Appwrite/Platform/Workers/Mails.php +++ b/src/Appwrite/Platform/Workers/Mails.php @@ -29,7 +29,7 @@ class Mails extends Action ->inject('message') ->inject('register') ->inject('log') - ->callback([$this, 'action']); + ->callback($this->action(...)); } /** diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 8491e91a6c..ae9a10efc0 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -72,7 +72,7 @@ class Messaging extends Action ->inject('dbForProject') ->inject('deviceForFiles') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); + ->callback($this->action(...)); } /** diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index b746365f20..0067df863a 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -69,7 +69,7 @@ class Migrations extends Action ->inject('logError') ->inject('queueForRealtime') ->inject('deviceForImports') - ->callback([$this, 'action']); + ->callback($this->action(...)); } /** diff --git a/src/Appwrite/Platform/Workers/StatsResources.php b/src/Appwrite/Platform/Workers/StatsResources.php index 19d1223d95..430a0a38a0 100644 --- a/src/Appwrite/Platform/Workers/StatsResources.php +++ b/src/Appwrite/Platform/Workers/StatsResources.php @@ -49,7 +49,7 @@ class StatsResources extends Action ->inject('getLogsDB') ->inject('dbForPlatform') ->inject('logError') - ->callback([$this, 'action']); + ->callback($this->action(...)); } /** diff --git a/src/Appwrite/Platform/Workers/StatsUsage.php b/src/Appwrite/Platform/Workers/StatsUsage.php index 25c80fabdc..d5bf3fbf5f 100644 --- a/src/Appwrite/Platform/Workers/StatsUsage.php +++ b/src/Appwrite/Platform/Workers/StatsUsage.php @@ -119,7 +119,7 @@ class StatsUsage extends Action ->inject('getProjectDB') ->inject('getLogsDB') ->inject('register') - ->callback([$this, 'action']); + ->callback($this->action(...)); $this->lastTriggeredTime = time(); } diff --git a/src/Appwrite/Platform/Workers/StatsUsageDump.php b/src/Appwrite/Platform/Workers/StatsUsageDump.php index 77ec3f13e6..e1b25b0f04 100644 --- a/src/Appwrite/Platform/Workers/StatsUsageDump.php +++ b/src/Appwrite/Platform/Workers/StatsUsageDump.php @@ -95,7 +95,7 @@ class StatsUsageDump extends Action ->inject('getProjectDB') ->inject('getLogsDB') ->inject('register') - ->callback([$this, 'action']); + ->callback($this->action(...)); } /** diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index ada4d6faaa..2388e05413 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -38,7 +38,7 @@ class Webhooks extends Action ->inject('queueForStatsUsage') ->inject('log') ->inject('plan') - ->callback([$this, 'action']); + ->callback($this->action(...)); } /** From 54552bf1b4ac1896e843d3c46e83041385fa45cd Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Wed, 4 Jun 2025 18:34:01 +0530 Subject: [PATCH 130/343] Create branch url for first git deployment --- .../Platform/Modules/Compute/Base.php | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 0541df551a..a6afee0f6d 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -6,6 +6,7 @@ use Appwrite\Event\Build; use Appwrite\Extend\Exception; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -226,6 +227,43 @@ class Base extends Action ])) ); + // VCS branch preview + if (!empty($providerBranch)) { + $branchPrefix = substr($providerBranch, 0, 16); + if (strlen($providerBranch) > 16) { + $remainingChars = substr($providerBranch, 16); + $branchPrefix .= '-' . substr(hash('sha256', $remainingChars), 0, 7); + } + $resourceProjectHash = substr(hash('sha256', $site->getId() . $project->getId()), 0, 7); + $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; + $ruleId = md5($domain); + try { + Authorization::skip( + fn () => $dbForPlatform->createDocument('rules', new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain, + 'type' => 'deployment', + 'trigger' => 'deployment', + 'deploymentId' => $deployment->getId(), + 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentResourceType' => 'site', + 'deploymentResourceId' => $site->getId(), + 'deploymentResourceInternalId' => $site->getInternalId(), + 'deploymentVcsProviderBranch' => $providerBranch, + 'status' => 'verified', + 'certificateId' => '', + 'search' => implode(' ', [$ruleId, $domain]), + 'owner' => 'Appwrite', + 'region' => $project->getAttribute('region') + ])) + ); + } catch (Duplicate $err) { + // Ignore, rule already exists; will be updated by builds worker + } + } + $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($site) From fa8e5b5b8e5ae8cbdd733cc093179ba9239cf897 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Wed, 4 Jun 2025 19:11:07 +0530 Subject: [PATCH 131/343] Add commit url --- .../Platform/Modules/Compute/Base.php | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index a6afee0f6d..204570db4e 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -227,6 +227,36 @@ class Base extends Action ])) ); + if (!empty($commitDetails['commitHash'])) { + $domain = "commit-" . substr($commitDetails['commitHash'], 0, 16) . ".{$sitesDomain}"; + $ruleId = md5($domain); + try { + Authorization::skip( + fn () => $dbForPlatform->createDocument('rules', new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain, + 'type' => 'deployment', + 'trigger' => 'deployment', + 'deploymentId' => $deployment->getId(), + 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentResourceType' => 'site', + 'deploymentResourceId' => $site->getId(), + 'deploymentResourceInternalId' => $site->getInternalId(), + 'deploymentVcsProviderBranch' => $providerBranch, + 'status' => 'verified', + 'certificateId' => '', + 'search' => implode(' ', [$ruleId, $domain]), + 'owner' => 'Appwrite', + 'region' => $project->getAttribute('region') + ])) + ); + } catch (Duplicate $err) { + // Ignore, rule already exists; will be updated by builds worker + } + } + // VCS branch preview if (!empty($providerBranch)) { $branchPrefix = substr($providerBranch, 0, 16); From fcdddf7bf0511e696b3906012d72916a34a1c616 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 11 Jun 2025 12:21:48 +0530 Subject: [PATCH 132/343] address comments. --- app/config/errors.php | 13 +++-- app/config/events.php | 2 +- app/init/constants.php | 12 ----- src/Appwrite/Event/Event.php | 48 ++++++++++++++++- src/Appwrite/Event/Realtime.php | 51 ++----------------- src/Appwrite/Extend/Exception.php | 45 ++++++++-------- src/Appwrite/Messaging/Adapter/Realtime.php | 2 - .../Platform/Modules/Databases/Constants.php | 23 +++++++++ 8 files changed, 106 insertions(+), 90 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Constants.php diff --git a/app/config/errors.php b/app/config/errors.php index de26b077fc..f7e8f194ab 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -69,9 +69,14 @@ return [ 'description' => 'The request contains one or more invalid arguments. Please refer to the endpoint documentation.', 'code' => 400, ], - Exception::GENERAL_QUERY_LIMIT_EXCEEDED => [ - 'name' => Exception::GENERAL_QUERY_LIMIT_EXCEEDED, - 'description' => 'Query limit exceeded for the current attribute/column. Usage of more than 100 query values on a single attribute/column is prohibited.', + Exception::GENERAL_ATTRIBUTE_QUERY_LIMIT_EXCEEDED => [ + 'name' => Exception::GENERAL_ATTRIBUTE_QUERY_LIMIT_EXCEEDED, + 'description' => 'Query limit exceeded for the current attribute.', + 'code' => 400, + ], + Exception::GENERAL_COLUMN_QUERY_LIMIT_EXCEEDED => [ + 'name' => Exception::GENERAL_COLUMN_QUERY_LIMIT_EXCEEDED, + 'description' => 'Query limit exceeded for the current column.', 'code' => 400, ], Exception::GENERAL_QUERY_INVALID => [ @@ -813,7 +818,7 @@ return [ ], Exception::ATTRIBUTE_INVALID_RESIZE => [ 'name' => Exception::ATTRIBUTE_INVALID_RESIZE, - 'description' => "Existing data is too large for new size, truncate your existing data then try again.", + 'description' => 'Existing data is too large for new size, truncate your existing data then try again.', 'code' => 400, ], diff --git a/app/config/events.php b/app/config/events.php index b0e6b9f5fc..8e759aaf56 100644 --- a/app/config/events.php +++ b/app/config/events.php @@ -129,7 +129,7 @@ return [ '$resource' => true, '$description' => 'This event triggers on any columns event.', 'create' => [ - '$description' => 'This event triggers when an column is created.', + '$description' => 'This event triggers when a column is created.', ], 'delete' => [ '$description' => 'This event triggers when an column is deleted.' diff --git a/app/init/constants.php b/app/init/constants.php index c3b6d4a058..143bba29bd 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -265,15 +265,3 @@ const TOKENS_RESOURCE_TYPE_FILES = 'files'; const TOKENS_RESOURCE_TYPE_SITES = 'sites'; const TOKENS_RESOURCE_TYPE_FUNCTIONS = 'functions'; const TOKENS_RESOURCE_TYPE_DATABASES = 'databases'; - -// Context constants for database - -const DATABASE_ROWS_CONTEXT = 'row'; -const DATABASE_TABLES_CONTEXT = 'table'; -const DATABASE_COLUMNS_CONTEXT = 'column'; -const DATABASE_INDEX_CONTEXT = 'index'; - -const DATABASE_DOCUMENTS_CONTEXT = 'document'; -const DATABASE_ATTRIBUTES_CONTEXT = 'attribute'; -const DATABASE_COLLECTIONS_CONTEXT = 'collection'; -const DATABASE_COLUMN_INDEX_CONTEXT = 'columnIndex'; diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index d699a45417..73ca8126a0 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -576,7 +576,12 @@ class Event /** * Force a non-assoc array. */ - return \array_values($events); + $eventValues = \array_values($events); + + /** + * Return a combined list of table, collection events. + */ + return Event::mirrorCollectionEvents($pattern, $eventValues[0], $eventValues); } /** @@ -597,4 +602,45 @@ class Event $this->context = $event->context; return $this; } + + /** + * Adds `table` events for `collection` events. + * + * Example: + * + * `databases.*.collections.*.documents.*.update` →\ + * `[databases.*.collections.*.documents.*.update, databases.*.tables.*.rows.*.update]` + */ + private static function mirrorCollectionEvents(string $pattern, string $firstEvent, array $events): array + { + $tableEventMap = [ + 'documents' => 'rows', + 'collections' => 'tables', + 'attributes' => 'columns', + ]; + + if ( + str_contains($pattern, 'databases.') && + str_contains($firstEvent, 'collections') + ) { + $pairedEvents = []; + + foreach ($events as $event) { + $pairedEvents[] = $event; + + if (str_contains($event, 'collections')) { + $tableSideEvent = str_replace( + array_keys($tableEventMap), + array_values($tableEventMap), + $event + ); + $pairedEvents[] = $tableSideEvent; + } + } + + $events = $pairedEvents; + } + + return $events; + } } diff --git a/src/Appwrite/Event/Realtime.php b/src/Appwrite/Event/Realtime.php index 016006ae73..6cb51ffa14 100644 --- a/src/Appwrite/Event/Realtime.php +++ b/src/Appwrite/Event/Realtime.php @@ -72,11 +72,7 @@ class Realtime extends Event return false; } - $events = Event::generateEvents($this->getEvent(), $this->getParams()); - $firstEvent = $events[0]; // most verbose event pattern - - // generate and merge all collection and tables api events. - $events = $this->mirrorCollectionEvents($firstEvent, $events); + $allEvents = Event::generateEvents($this->getEvent(), $this->getParams()); $payload = new Document($this->getPayload()); @@ -87,7 +83,7 @@ class Realtime extends Event $tableOrCollection = $this->getContext('table') ?? $this->getContext('collection'); $target = RealtimeAdapter::fromPayload( - event: $firstEvent, + event: $allEvents[0], payload: $payload, project: $this->getProject(), database: $db, @@ -103,7 +99,7 @@ class Realtime extends Event $this->realtime->send( projectId: $projectId, payload: $this->getRealtimePayload(), - events: $events, + events: $allEvents, channels: $target['channels'], roles: $target['roles'], options: [ @@ -115,45 +111,4 @@ class Realtime extends Event return true; } - - /** - * Adds `table` events for `collection` events. - * - * Example: - * - * `databases.*.collections.*.documents.*.update` →\ - * `[databases.*.collections.*.documents.*.update, databases.*.tables.*.rows.*.update]` - */ - private function mirrorCollectionEvents(string $firstEvent, array $events): array - { - $tableEventMap = [ - 'documents' => 'rows', - 'collections' => 'tables', - 'attributes' => 'columns', - ]; - - if ( - str_contains($this->getEvent(), 'databases.') && - str_contains($firstEvent, 'collections') - ) { - $pairedEvents = []; - - foreach ($events as $event) { - $pairedEvents[] = $event; - - if (str_contains($event, 'collections')) { - $tableSideEvent = str_replace( - array_keys($tableEventMap), - array_values($tableEventMap), - $event - ); - $pairedEvents[] = $tableSideEvent; - } - } - - $events = $pairedEvents; - } - - return $events; - } } diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 38a562571c..29880a03b1 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -48,7 +48,8 @@ class Exception extends \Exception public const GENERAL_SMTP_DISABLED = 'general_smtp_disabled'; public const GENERAL_PHONE_DISABLED = 'general_phone_disabled'; public const GENERAL_ARGUMENT_INVALID = 'general_argument_invalid'; - public const GENERAL_QUERY_LIMIT_EXCEEDED = 'general_query_limit_exceeded'; + public const GENERAL_COLUMN_QUERY_LIMIT_EXCEEDED = 'general_column_query_limit_exceeded'; + public const GENERAL_ATTRIBUTE_QUERY_LIMIT_EXCEEDED = 'general_attribute_query_limit_exceeded'; public const GENERAL_QUERY_INVALID = 'general_query_invalid'; public const GENERAL_ROUTE_NOT_FOUND = 'general_route_not_found'; public const GENERAL_CURSOR_NOT_FOUND = 'general_cursor_not_found'; @@ -197,9 +198,9 @@ class Exception extends \Exception public const COLLECTION_LIMIT_EXCEEDED = 'collection_limit_exceeded'; /** Tables */ - public const TABLE_NOT_FOUND = 'table_not_found'; - public const TABLE_ALREADY_EXISTS = 'table_already_exists'; - public const TABLE_LIMIT_EXCEEDED = 'table_limit_exceeded'; + public const TABLE_NOT_FOUND = 'table_not_found'; + public const TABLE_ALREADY_EXISTS = 'table_already_exists'; + public const TABLE_LIMIT_EXCEEDED = 'table_limit_exceeded'; /** Documents */ public const DOCUMENT_NOT_FOUND = 'document_not_found'; @@ -211,13 +212,13 @@ class Exception extends \Exception public const DOCUMENT_DELETE_RESTRICTED = 'document_delete_restricted'; /** Rows */ - public const ROW_NOT_FOUND = 'row_not_found'; - public const ROW_INVALID_STRUCTURE = 'row_invalid_structure'; - public const ROW_MISSING_DATA = 'row_missing_data'; - public const ROW_MISSING_PAYLOAD = 'row_missing_payload'; - public const ROW_ALREADY_EXISTS = 'row_already_exists'; - public const ROW_UPDATE_CONFLICT = 'row_update_conflict'; - public const ROW_DELETE_RESTRICTED = 'row_delete_restricted'; + public const ROW_NOT_FOUND = 'row_not_found'; + public const ROW_INVALID_STRUCTURE = 'row_invalid_structure'; + public const ROW_MISSING_DATA = 'row_missing_data'; + public const ROW_MISSING_PAYLOAD = 'row_missing_payload'; + public const ROW_ALREADY_EXISTS = 'row_already_exists'; + public const ROW_UPDATE_CONFLICT = 'row_update_conflict'; + public const ROW_DELETE_RESTRICTED = 'row_delete_restricted'; /** Attributes */ public const ATTRIBUTE_NOT_FOUND = 'attribute_not_found'; @@ -232,16 +233,16 @@ class Exception extends \Exception public const ATTRIBUTE_INVALID_RESIZE = 'attribute_invalid_resize'; /** Columns */ - public const COLUMN_NOT_FOUND = 'column_not_found'; - public const COLUMN_UNKNOWN = 'column_unknown'; - public const COLUMN_NOT_AVAILABLE = 'column_not_available'; - public const COLUMN_FORMAT_UNSUPPORTED = 'column_format_unsupported'; - public const COLUMN_DEFAULT_UNSUPPORTED = 'column_default_unsupported'; - public const COLUMN_ALREADY_EXISTS = 'column_already_exists'; - public const COLUMN_LIMIT_EXCEEDED = 'column_limit_exceeded'; - public const COLUMN_VALUE_INVALID = 'column_value_invalid'; - public const COLUMN_TYPE_INVALID = 'column_type_invalid'; - public const COLUMN_INVALID_RESIZE = 'column_invalid_resize'; + public const COLUMN_NOT_FOUND = 'column_not_found'; + public const COLUMN_UNKNOWN = 'column_unknown'; + public const COLUMN_NOT_AVAILABLE = 'column_not_available'; + public const COLUMN_FORMAT_UNSUPPORTED = 'column_format_unsupported'; + public const COLUMN_DEFAULT_UNSUPPORTED = 'column_default_unsupported'; + public const COLUMN_ALREADY_EXISTS = 'column_already_exists'; + public const COLUMN_LIMIT_EXCEEDED = 'column_limit_exceeded'; + public const COLUMN_VALUE_INVALID = 'column_value_invalid'; + public const COLUMN_TYPE_INVALID = 'column_type_invalid'; + public const COLUMN_INVALID_RESIZE = 'column_invalid_resize'; /** Relationship */ public const RELATIONSHIP_VALUE_INVALID = 'relationship_value_invalid'; @@ -347,7 +348,7 @@ class Exception extends \Exception public const MESSAGE_MISSING_SCHEDULE = 'message_missing_schedule'; /** Targets */ - public const TARGET_PROVIDER_INVALID_TYPE = 'target_provider_invalid_type'; + public const TARGET_PROVIDER_INVALID_TYPE = 'target_provider_invalid_type'; /** Schedules */ public const SCHEDULE_NOT_FOUND = 'schedule_not_found'; diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index bfe87c49db..aff4e400ce 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -312,12 +312,10 @@ class Realtime extends Adapter throw new \Exception('Collection or the Table needs to be passed to Realtime for Document/Row events in the Database.'); } - // 1.7.x - Tables API $channels[] = 'rows'; $channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$tableId') . '.rows'; $channels[] = 'databases.' . $database->getId() . '.tables.' . $payload->getAttribute('$tableId') . '.rows.' . $payload->getId(); - // 1.6.x - Collections API $channels[] = 'documents'; $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents'; $channels[] = 'databases.' . $database->getId() . '.collections.' . $payload->getAttribute('$collectionId') . '.documents.' . $payload->getId(); diff --git a/src/Appwrite/Platform/Modules/Databases/Constants.php b/src/Appwrite/Platform/Modules/Databases/Constants.php new file mode 100644 index 0000000000..b17248bf4d --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Constants.php @@ -0,0 +1,23 @@ + Date: Wed, 11 Jun 2025 12:51:31 +0530 Subject: [PATCH 133/343] update: `getInternalId()` -> `getSequence()` --- .../Collections/Attributes/Action.php | 52 +++++++++---------- .../Collections/Attributes/Delete.php | 16 +++--- .../Databases/Collections/Attributes/Get.php | 4 +- .../Attributes/Relationship/Create.php | 8 +-- .../Collections/Attributes/XList.php | 10 ++-- .../Http/Databases/Collections/Create.php | 6 +-- .../Http/Databases/Collections/Delete.php | 6 +-- .../Collections/Documents/Create.php | 12 ++--- .../Collections/Documents/Delete.php | 10 ++-- .../Databases/Collections/Documents/Get.php | 8 +-- .../Collections/Documents/Logs/XList.php | 4 +- .../Collections/Documents/Update.php | 16 +++--- .../Databases/Collections/Documents/XList.php | 12 ++--- .../Http/Databases/Collections/Get.php | 2 +- .../Databases/Collections/Indexes/Create.php | 14 ++--- .../Databases/Collections/Indexes/Delete.php | 6 +-- .../Databases/Collections/Indexes/Get.php | 2 +- .../Databases/Collections/Indexes/XList.php | 6 +-- .../Http/Databases/Collections/Logs/XList.php | 4 +- .../Http/Databases/Collections/Update.php | 6 +-- .../Http/Databases/Collections/Usage/Get.php | 6 +-- .../Http/Databases/Collections/XList.php | 6 +-- .../Databases/Http/Databases/Create.php | 2 +- .../Databases/Http/Databases/Delete.php | 2 +- .../Databases/Http/Databases/Usage/Get.php | 10 ++-- 25 files changed, 115 insertions(+), 115 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 095b679223..2e0e598695 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -287,7 +287,7 @@ abstract class Action extends UtopiaAction throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $db->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); @@ -310,7 +310,7 @@ abstract class Action extends UtopiaAction if ($type === Database::VAR_RELATIONSHIP) { $options['side'] = Database::RELATION_SIDE_PARENT; - $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection'] ?? ''); + $relatedCollection = $dbForProject->getDocument('database_' . $db->getSequence(), $options['relatedCollection'] ?? ''); if ($relatedCollection->isEmpty()) { $parent = $this->isCollectionsAPI() ? 'collection' : 'table'; throw new Exception($this->getParentNotFoundException(), "The related $parent was not found."); @@ -319,11 +319,11 @@ abstract class Action extends UtopiaAction try { $attribute = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), + '$id' => ID::custom($db->getSequence() . '_' . $collection->getSequence() . '_' . $key), 'key' => $key, - 'databaseInternalId' => $db->getInternalId(), + 'databaseInternalId' => $db->getSequence(), 'databaseId' => $db->getId(), - 'collectionInternalId' => $collection->getInternalId(), + 'collectionInternalId' => $collection->getSequence(), 'collectionId' => $collectionId, 'type' => $type, 'status' => 'processing', // processing, available, failed, deleting, stuck @@ -345,13 +345,13 @@ abstract class Action extends UtopiaAction } catch (LimitException) { throw new Exception($this->getLimitException()); } catch (Throwable $e) { - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $db->getSequence() . '_collection_' . $collection->getSequence()); throw $e; } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $db->getSequence() . '_collection_' . $collection->getSequence()); if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { $twoWayKey = $options['twoWayKey']; @@ -361,11 +361,11 @@ abstract class Action extends UtopiaAction try { $twoWayAttribute = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $twoWayKey), + '$id' => ID::custom($db->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $twoWayKey), 'key' => $twoWayKey, - 'databaseInternalId' => $db->getInternalId(), + 'databaseInternalId' => $db->getSequence(), 'databaseId' => $db->getId(), - 'collectionInternalId' => $relatedCollection->getInternalId(), + 'collectionInternalId' => $relatedCollection->getSequence(), 'collectionId' => $relatedCollection->getId(), 'type' => $type, 'status' => 'processing', // processing, available, failed, deleting, stuck @@ -389,13 +389,13 @@ abstract class Action extends UtopiaAction $dbForProject->deleteDocument('attributes', $attribute->getId()); throw new Exception($this->getLimitException()); } catch (Throwable $e) { - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $relatedCollection->getId()); + $dbForProject->purgeCachedCollection('database_' . $db->getSequence() . '_collection_' . $relatedCollection->getSequence()); throw $e; } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $relatedCollection->getId()); + $dbForProject->purgeCachedCollection('database_' . $db->getSequence() . '_collection_' . $relatedCollection->getSequence()); } $queueForDatabase @@ -434,13 +434,13 @@ abstract class Action extends UtopiaAction throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $db->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } - $attribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $db->getSequence() . '_' . $collection->getSequence() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception($this->getNotFoundException()); @@ -466,7 +466,7 @@ abstract class Action extends UtopiaAction throw new Exception($this->getDefaultUnsupportedException(), 'Cannot set default value for array ' . $this->getContext() . 's'); } - $collectionId = 'database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId(); + $collectionId = 'database_' . $db->getSequence() . '_collection_' . $collection->getSequence(); $attribute ->setAttribute('default', $default) @@ -546,9 +546,9 @@ abstract class Action extends UtopiaAction } if ($primaryDocumentOptions['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $primaryDocumentOptions['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $db->getSequence(), $primaryDocumentOptions['relatedCollection']); - $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $db->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $primaryDocumentOptions['twoWayKey']); if (!empty($newKey) && $newKey !== $key) { $options['twoWayKey'] = $newKey; @@ -556,9 +556,9 @@ abstract class Action extends UtopiaAction $relatedOptions = \array_merge($relatedAttribute->getAttribute('options'), $options); $relatedAttribute->setAttribute('options', $relatedOptions); - $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); + $dbForProject->updateDocument('attributes', $db->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $relatedCollection->getId()); } } else { try { @@ -586,7 +586,7 @@ abstract class Action extends UtopiaAction $originalUid = $attribute->getId(); $attribute - ->setAttribute('$id', ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $newKey)) + ->setAttribute('$id', ID::custom($db->getSequence() . '_' . $collection->getSequence() . '_' . $newKey)) ->setAttribute('key', $newKey); $dbForProject->updateDocument('attributes', $originalUid, $attribute); @@ -608,10 +608,10 @@ abstract class Action extends UtopiaAction } } } else { - $attribute = $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute); + $attribute = $dbForProject->updateDocument('attributes', $db->getSequence() . '_' . $collection->getSequence() . '_' . $key, $attribute); } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collection->getId()); + $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $collection->getId()); $queueForEvents ->setContext('database', $db) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index cf5b7766b3..1f31097caf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -76,12 +76,12 @@ class Delete extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $db->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } - $attribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $db->getSequence() . '_' . $collection->getSequence() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception($this->getNotFoundException()); } @@ -98,18 +98,18 @@ class Delete extends Action $attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $db->getSequence() . '_collection_' . $collection->getSequence()); if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { $options = $attribute->getAttribute('options'); if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $db->getSequence(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } - $relatedAttribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $db->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $options['twoWayKey']); if ($relatedAttribute->isEmpty()) { throw new Exception($this->getNotFoundException()); } @@ -118,8 +118,8 @@ class Delete extends Action $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']); - $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $options['relatedCollection']); + $dbForProject->purgeCachedCollection('database_' . $db->getSequence() . '_collection_' . $relatedCollection->getSequence()); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index 96e40c750d..ba91af54a2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -76,12 +76,12 @@ class Get extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } - $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception($this->getNotFoundException()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php index 193e3eaa09..0bbb3faa67 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php @@ -93,14 +93,14 @@ class Create extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } - $relatedCollectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); - $relatedCollection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollectionDocument->getInternalId()); + $relatedCollectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId); + $relatedCollection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $relatedCollectionDocument->getSequence()); if ($relatedCollection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 7f2f23df62..dac7d94ab5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -69,7 +69,7 @@ class XList extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } @@ -78,8 +78,8 @@ class XList extends Action \array_push( $queries, - Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$collection->getInternalId()]) + Query::equal('databaseInternalId', [$database->getSequence()]), + Query::equal('collectionInternalId', [$collection->getSequence()]) ); $cursor = \array_filter( @@ -97,8 +97,8 @@ class XList extends Action $attributeId = $cursor->getValue(); $cursorDocument = Authorization::skip( fn () => $dbForProject->find('attributes', [ - Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$collection->getInternalId()]), + Query::equal('databaseInternalId', [$database->getSequence()]), + Query::equal('collectionInternalId', [$collection->getSequence()]), Query::equal('key', [$attributeId]), Query::limit(1), ]) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php index a65bf9c311..6b80901e05 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -89,9 +89,9 @@ class Create extends Action $permissions = Permission::aggregate($permissions) ?? []; try { - $collection = $dbForProject->createDocument('database_' . $database->getInternalId(), new Document([ + $collection = $dbForProject->createDocument('database_' . $database->getSequence(), new Document([ '$id' => $collectionId, - 'databaseInternalId' => $database->getInternalId(), + 'databaseInternalId' => $database->getSequence(), 'databaseId' => $databaseId, '$permissions' => $permissions, 'documentSecurity' => $documentSecurity, @@ -100,7 +100,7 @@ class Create extends Action 'search' => \implode(' ', [$collectionId, $name]), ])); - $dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), permissions: $permissions, documentSecurity: $documentSecurity); + $dbForProject->createCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), permissions: $permissions, documentSecurity: $documentSecurity); } catch (DuplicateException) { throw new Exception($this->getDuplicateException()); } catch (LimitException) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php index d838d16b94..67bddbc9ff 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php @@ -72,17 +72,17 @@ class Delete extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception($this->getNotFoundException()); } - if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $collectionId)) { + if (!$dbForProject->deleteDocument('database_' . $database->getSequence(), $collectionId)) { $type = $this->getContext(); throw new Exception(Exception::GENERAL_SERVER_ERROR, "Failed to remove $type from DB"); } - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_COLLECTION) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index d6c9960a5b..23883c9ff4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -107,7 +107,7 @@ class Create extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); @@ -199,7 +199,7 @@ class Create extends Action $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -213,7 +213,7 @@ class Create extends Action } if ($relation instanceof Document) { $current = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()) + fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId()) ); if ($current->isEmpty()) { @@ -244,7 +244,7 @@ class Create extends Action $checkPermissions($collection, $document, Database::PERMISSION_CREATE); try { - $document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document); + $document = $dbForProject->createDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $document); } catch (StructureException $e) { throw new Exception($this->getInvalidStructureException(), $e->getMessage()); } catch (DuplicateException) { @@ -275,7 +275,7 @@ class Create extends Action $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -290,7 +290,7 @@ class Create extends Action $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); // per collection + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); // per collection $response->addHeader('X-Debug-Operations', $operations); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index c218e713bf..32af5b0127 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -88,14 +88,14 @@ class Delete extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); } // Read permission should not be required for delete - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($document->isEmpty()) { throw new Exception($this->getNotFoundException()); @@ -104,7 +104,7 @@ class Delete extends Action try { $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) { $dbForProject->deleteDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId ); }); @@ -134,7 +134,7 @@ class Delete extends Action $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -149,7 +149,7 @@ class Delete extends Action $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1); // per collection + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1); // per collection $response->addHeader('X-Debug-Operations', 1); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index aa01eebcdf..f8fd749dc2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -79,7 +79,7 @@ class Get extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); @@ -87,7 +87,7 @@ class Get extends Action try { $queries = Query::parseQueries($queries); - $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries); + $document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId, $queries); } catch (AuthorizationException) { throw new Exception(Exception::USER_UNAUTHORIZED); } catch (QueryException $e) { @@ -133,7 +133,7 @@ class Get extends Action $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -148,7 +148,7 @@ class Get extends Action $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); $response->addHeader('X-Debug-Operations', $operations); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php index bb24d41b30..1053c00ff9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php @@ -82,13 +82,13 @@ class XList extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } - $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); + $document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId); if ($document->isEmpty()) { throw new Exception($this->getNotFoundException()); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index 17da8e552d..58408ae4ab 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -101,7 +101,7 @@ class Update extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); @@ -109,7 +109,7 @@ class Update extends Action // Read permission should not be required for update /** @var Document $document */ - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($document->isEmpty()) { throw new Exception($this->getNotFoundException()); @@ -179,7 +179,7 @@ class Update extends Action $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -194,7 +194,7 @@ class Update extends Action } if ($relation instanceof Document) { $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); $relation->removeAttribute('$collectionId'); @@ -202,7 +202,7 @@ class Update extends Action // Attribute $collection is required for Utopia. $relation->setAttribute( '$collection', - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() + 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence() ); if ($oldDocument->isEmpty()) { @@ -226,7 +226,7 @@ class Update extends Action $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); $response->addHeader('X-Debug-Operations', $operations); @@ -234,7 +234,7 @@ class Update extends Action $document = $dbForProject->withRequestTimestamp( $requestTimestamp, fn () => $dbForProject->updateDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $document->getId(), $newDocument ) @@ -271,7 +271,7 @@ class Update extends Action $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 57af51d908..d11128ed7b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -79,7 +79,7 @@ class XList extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); @@ -108,7 +108,7 @@ class XList extends Action $documentId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($cursorDocument->isEmpty()) { $type = ucfirst($this->getContext()); @@ -118,8 +118,8 @@ class XList extends Action $cursor->setValue($cursorDocument); } try { - $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); - $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); + $documents = $dbForProject->find('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries); + $total = $dbForProject->count('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries, APP_LIMIT_COUNT); } catch (OrderException $e) { $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; $attribute = $this->isCollectionsAPI() ? 'attribute' : 'column'; @@ -165,7 +165,7 @@ class XList extends Action $relatedCollectionId = $relationship->getAttribute('relatedCollection'); // todo: Use local cache for this getDocument - $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)); + $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId)); foreach ($relations as $index => $doc) { if ($doc instanceof Document) { @@ -191,7 +191,7 @@ class XList extends Action $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); $response->addHeader('X-Debug-Operations', $operations); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php index bf06e29e26..9ff9e3e442 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php @@ -66,7 +66,7 @@ class Get extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception($this->getNotFoundException()); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index a963640597..e688088640 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -85,7 +85,7 @@ class Create extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $db->getSequence(), $collectionId); if ($collection->isEmpty()) { // table or collection. @@ -93,8 +93,8 @@ class Create extends Action } $count = $dbForProject->count('indexes', [ - Query::equal('collectionInternalId', [$collection->getInternalId()]), - Query::equal('databaseInternalId', [$db->getInternalId()]) + Query::equal('collectionInternalId', [$collection->getSequence()]), + Query::equal('databaseInternalId', [$db->getSequence()]) ], 61); $limit = $dbForProject->getLimitForIndexes(); @@ -173,12 +173,12 @@ class Create extends Action } $index = new Document([ - '$id' => ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), + '$id' => ID::custom($db->getSequence() . '_' . $collection->getSequence() . '_' . $key), 'key' => $key, 'status' => 'processing', // processing, available, failed, deleting, stuck - 'databaseInternalId' => $db->getInternalId(), + 'databaseInternalId' => $db->getSequence(), 'databaseId' => $databaseId, - 'collectionInternalId' => $collection->getInternalId(), + 'collectionInternalId' => $collection->getSequence(), 'collectionId' => $collectionId, 'type' => $type, 'attributes' => $attributes, @@ -201,7 +201,7 @@ class Create extends Action throw new Exception($this->getDuplicateException()); } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $collectionId); $queueForDatabase ->setType(DATABASE_TYPE_CREATE_INDEX) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index 70df7c4f7a..6fe3e3f42c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -78,14 +78,14 @@ class Delete extends Action if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $db->getSequence(), $collectionId); if ($collection->isEmpty()) { // table or collection. throw new Exception($this->getGrandParentNotFoundException()); } - $index = $dbForProject->getDocument('indexes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $index = $dbForProject->getDocument('indexes', $db->getSequence() . '_' . $collection->getSequence() . '_' . $key); if (empty($index->getId())) { throw new Exception($this->getNotFoundException()); @@ -96,7 +96,7 @@ class Delete extends Action $index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $collectionId); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_INDEX) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php index 466d6fa99e..8d5513e1c0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php @@ -67,7 +67,7 @@ class Get extends Action if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { // table or collection. diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index d44c80b393..5929d56a91 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -73,7 +73,7 @@ class XList extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { // table or collection. @@ -104,8 +104,8 @@ class XList extends Action $indexId = $cursor->getValue(); $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ - Query::equal('collectionInternalId', [$collection->getInternalId()]), - Query::equal('databaseInternalId', [$database->getInternalId()]), + Query::equal('collectionInternalId', [$collection->getSequence()]), + Query::equal('databaseInternalId', [$database->getSequence()]), Query::equal('key', [$indexId]), Query::limit(1) ])); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php index 7785ec2890..6e9f86260c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php @@ -81,8 +81,8 @@ class XList extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + $collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $collectionDocument->getSequence()); if ($collection->isEmpty()) { throw new Exception($this->getNotFoundException()); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php index d7a2751166..e1e8da7017 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php @@ -78,7 +78,7 @@ class Update extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception($this->getNotFoundException()); } @@ -91,7 +91,7 @@ class Update extends Action $enabled ??= $collection->getAttribute('enabled', true); $collection = $dbForProject->updateDocument( - 'database_' . $database->getInternalId(), + 'database_' . $database->getSequence(), $collectionId, $collection ->setAttribute('name', $name) @@ -101,7 +101,7 @@ class Update extends Action ->setAttribute('search', \implode(' ', [$collectionId, $name])) ); - $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity); + $dbForProject->updateCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $permissions, $documentSecurity); $queueForEvents ->setContext('database', $database) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php index 995200fcc7..5d49be7723 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php @@ -67,8 +67,8 @@ class Get extends Action public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject): void { $database = $dbForProject->getDocument('databases', $databaseId); - $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + $collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $collectionDocument->getSequence()); if ($collection->isEmpty()) { throw new Exception($this->getNotFoundException()); @@ -78,7 +78,7 @@ class Get extends Action $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collectionDocument->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), + str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collectionDocument->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index 1b50c3f090..e9df7db598 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -94,7 +94,7 @@ class XList extends Action } $collectionIdId = $cursor->getValue(); - $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionIdId); + $cursorDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionIdId); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, ucfirst($this->getContext()) . " '$collectionIdId' for the 'cursor' value not found."); @@ -106,8 +106,8 @@ class XList extends Action $filterQueries = Query::groupByType($queries)['filters']; try { - $collections = $dbForProject->find('database_' . $database->getInternalId(), $queries); - $total = $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT); + $collections = $dbForProject->find('database_' . $database->getSequence(), $queries); + $total = $dbForProject->count('database_' . $database->getSequence(), $filterQueries, APP_LIMIT_COUNT); } catch (OrderException $e) { $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; $attribute = $this->isCollectionsAPI() ? 'attribute' : 'column'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php index a734cbdd22..1f368ec77a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php @@ -109,7 +109,7 @@ class Create extends Action 'orders' => $index['orders'], ]); } - $dbForProject->createCollection('database_' . $database->getInternalId(), $attributes, $indexes); + $dbForProject->createCollection('database_' . $database->getSequence(), $attributes, $indexes); } catch (DuplicateException) { throw new Exception(Exception::DATABASE_ALREADY_EXISTS); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php index e0651b5e5b..60df83bb77 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php @@ -73,7 +73,7 @@ class Delete extends Action } $dbForProject->purgeCachedDocument('databases', $database->getId()); - $dbForProject->purgeCachedCollection('databases_' . $database->getInternalId()); + $dbForProject->purgeCachedCollection('databases_' . $database->getSequence()); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_DATABASE) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php index 222201d5ed..fab12a9735 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -70,11 +70,11 @@ class Get extends Action $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_STORAGE), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASES_OPERATIONS_READS), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASES_OPERATIONS_WRITES) + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_COLLECTIONS), + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_DOCUMENTS), + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_STORAGE), + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASES_OPERATIONS_READS), + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASES_OPERATIONS_WRITES) ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { From e07a1817ab57d9175f9be29d0785fd3429b29ff5 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 11 Jun 2025 13:42:55 +0530 Subject: [PATCH 134/343] update: remove conflict, restrict and relationship exceptions from global handler. --- app/controllers/general.php | 19 ---------------- .../Collections/Attributes/Action.php | 22 +++++++++++++++++-- .../Collections/Documents/Action.php | 19 ++++++++++++++++ .../Collections/Documents/Delete.php | 9 +++++--- .../Collections/Documents/Update.php | 12 +++++----- 5 files changed, 51 insertions(+), 30 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 46bc367d63..5aed7c21ea 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1174,14 +1174,6 @@ App::error() break; } break; - case 'Utopia\Database\Exception\Conflict': - $error = new AppwriteException( - $isTablesAPI - ? AppwriteException::ROW_UPDATE_CONFLICT - : AppwriteException::DOCUMENT_UPDATE_CONFLICT, - previous: $error - ); - break; case 'Utopia\Database\Exception\Timeout': $error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error); break; @@ -1203,20 +1195,9 @@ App::error() ? AppwriteException::ROW_ALREADY_EXISTS : AppwriteException::DOCUMENT_ALREADY_EXISTS ); - break; - case 'Utopia\Database\Exception\Restricted': - $error = new AppwriteException( - $isTablesAPI - ? AppwriteException::ROW_DELETE_RESTRICTED - : AppwriteException::DOCUMENT_DELETE_RESTRICTED - ); - break; case 'Utopia\Database\Exception\Authorization': $error = new AppwriteException(AppwriteException::USER_UNAUTHORIZED); break; - case 'Utopia\Database\Exception\Relationship': - $error = new AppwriteException(AppwriteException::RELATIONSHIP_VALUE_INVALID, $error->getMessage(), previous: $error); - break; case 'Utopia\Database\Exception\NotFound': $error = new AppwriteException( $isTablesAPI diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 2e0e598695..92751bcbe4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -14,6 +14,8 @@ use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Exception\Index as IndexException; use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\NotFound as NotFoundException; +use Utopia\Database\Exception\Relationship as RelationshipException; +use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Exception\Truncate as TruncateException; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; @@ -124,6 +126,16 @@ abstract class Action extends UtopiaAction : Exception::COLUMN_ALREADY_EXISTS; } + /** + * Get the correct invalid structure message. + */ + final protected function getInvalidStructureException(): string + { + return $this->isCollectionsAPI() + ? Exception::DOCUMENT_INVALID_STRUCTURE + : Exception::ROW_INVALID_STRUCTURE; + } + /** * Get the appropriate limit exceeded exception. */ @@ -541,8 +553,14 @@ abstract class Action extends UtopiaAction newKey: $newKey, onDelete: $primaryDocumentOptions['onDelete'], ); - } catch (NotFoundException) { - throw new Exception($this->getNotFoundException()); + } catch (IndexException) { + throw new Exception(Exception::INDEX_INVALID); + } catch (LimitException) { + throw new Exception($this->getLimitException()); + } catch (RelationshipException $e) { + throw new Exception(Exception::RELATIONSHIP_VALUE_INVALID, $e->getMessage()); + } catch (StructureException $e) { + throw new Exception($this->getInvalidStructureException(), $e->getMessage()); } if ($primaryDocumentOptions['twoWay']) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index 01ee2d9f84..32bb314cd2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -97,6 +97,25 @@ abstract class Action extends UtopiaAction : Exception::ROW_ALREADY_EXISTS; } + /** + * Get the appropriate conflict exception. + */ + final protected function getConflictException(): string + { + return $this->isCollectionsAPI() + ? Exception::DOCUMENT_UPDATE_CONFLICT + : Exception::ROW_UPDATE_CONFLICT; + } + + /** + * Get the appropriate delete restricted exception. + */ + final protected function getRestrictedException(): string + { + return $this->isCollectionsAPI() + ? Exception::DOCUMENT_DELETE_RESTRICTED + : Exception::ROW_DELETE_RESTRICTED; + } /** * Get the correct invalid structure message. diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index 32af5b0127..9944de4e36 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -13,7 +13,8 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Exception\NotFound as NotFoundException; +use Utopia\Database\Exception\Conflict as ConflictException; +use Utopia\Database\Exception\Restricted as RestrictedException; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; @@ -108,8 +109,10 @@ class Delete extends Action $documentId ); }); - } catch (NotFoundException) { - throw new Exception($this->getParentNotFoundException()); + } catch (ConflictException) { + throw new Exception($this->getConflictException()); + } catch (RestrictedException) { + throw new Exception($this->getRestrictedException()); } // Add $collection and $databaseId for all documents diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index 58408ae4ab..c3a2fe6df3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -13,9 +13,9 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Exception\Authorization as AuthorizationException; +use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Duplicate as DuplicateException; -use Utopia\Database\Exception\NotFound as NotFoundException; +use Utopia\Database\Exception\Relationship as RelationshipException; use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -239,14 +239,14 @@ class Update extends Action $newDocument ) ); - } catch (AuthorizationException) { - throw new Exception(Exception::USER_UNAUTHORIZED); + } catch (ConflictException) { + throw new Exception($this->getConflictException()); } catch (DuplicateException) { throw new Exception($this->getDuplicateException()); + } catch (RelationshipException $e) { + throw new Exception(Exception::RELATIONSHIP_VALUE_INVALID, $e->getMessage()); } catch (StructureException $e) { throw new Exception($this->getInvalidStructureException(), $e->getMessage()); - } catch (NotFoundException) { - throw new Exception($this->getParentNotFoundException()); } // Add $collectionId and $databaseId for all documents From e6268fe5a64a3d8cd01d23b8af84bbbea4ad2055 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 11 Jun 2025 15:58:22 +0530 Subject: [PATCH 135/343] update: remove query exceptions from global handler. --- app/controllers/general.php | 4 +-- .../Collections/Attributes/XList.php | 35 +++++++++++++------ .../Databases/Collections/Documents/Get.php | 10 +++--- .../Collections/Documents/Logs/XList.php | 3 -- .../Databases/Collections/Documents/XList.php | 2 ++ .../Databases/Collections/Indexes/XList.php | 9 ++++- .../Http/Databases/Collections/XList.php | 16 +++++---- .../Databases/Http/Databases/XList.php | 4 +++ 8 files changed, 56 insertions(+), 27 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 5aed7c21ea..9d9a03db92 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1177,9 +1177,6 @@ App::error() case 'Utopia\Database\Exception\Timeout': $error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error); break; - case 'Utopia\Database\Exception\Query': - $error = new AppwriteException(AppwriteException::GENERAL_QUERY_INVALID, $error->getMessage(), previous: $error); - break; case 'Utopia\Database\Exception\Structure': $error = new AppwriteException( $isTablesAPI @@ -1195,6 +1192,7 @@ App::error() ? AppwriteException::ROW_ALREADY_EXISTS : AppwriteException::DOCUMENT_ALREADY_EXISTS ); + // no break case 'Utopia\Database\Exception\Authorization': $error = new AppwriteException(AppwriteException::USER_UNAUTHORIZED); break; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index dac7d94ab5..307cb98eff 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -11,6 +11,7 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception\Order as OrderException; +use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Query\Cursor; @@ -74,7 +75,11 @@ class XList extends Action throw new Exception($this->getParentNotFoundException()); } - $queries = Query::parseQueries($queries); + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } \array_push( $queries, @@ -95,33 +100,43 @@ class XList extends Action } $attributeId = $cursor->getValue(); - $cursorDocument = Authorization::skip( - fn () => $dbForProject->find('attributes', [ + try { + $cursorDocument = $dbForProject->findOne('attributes', [ Query::equal('databaseInternalId', [$database->getSequence()]), Query::equal('collectionInternalId', [$collection->getSequence()]), Query::equal('key', [$attributeId]), - Query::limit(1), - ]) - ); + ]); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } - if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { + if ($cursorDocument->isEmpty()) { $type = ucfirst($this->getContext()); throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "$type '$attributeId' for the 'cursor' value not found."); } - $cursor->setValue($cursorDocument[0]); + $cursor->setValue($cursorDocument); } - $filters = Query::groupByType($queries)['filters']; + $filterQueries = Query::groupByType($queries)['filters']; try { $attributes = $dbForProject->find('attributes', $queries); - $total = $dbForProject->count('attributes', $filters, APP_LIMIT_COUNT); + $total = $dbForProject->count('attributes', $filterQueries, APP_LIMIT_COUNT); } catch (OrderException $e) { $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; $attribute = $this->isCollectionsAPI() ? 'attribute' : 'column'; $message = "The order $attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all $documents order $attribute values are non-null."; throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, $message); + } catch (QueryException) { + throw new Exception(Exception::GENERAL_QUERY_INVALID); + } + + foreach ($attributes as $attribute) { + if ($attribute->getAttribute('type') === Database::VAR_STRING) { + $filters = $attribute->getAttribute('filters', []); + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + } } $response->dynamic(new Document([ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index f8fd749dc2..da730246bf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; @@ -71,10 +70,10 @@ class Get extends Action public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage): void { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } @@ -87,9 +86,12 @@ class Get extends Action try { $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + try { $document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId, $queries); - } catch (AuthorizationException) { - throw new Exception(Exception::USER_UNAUTHORIZED); } catch (QueryException $e) { throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php index 1053c00ff9..2856d9ddd0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php @@ -77,19 +77,16 @@ class XList extends Action public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); - if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } $document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId); - if ($document->isEmpty()) { throw new Exception($this->getNotFoundException()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index d11128ed7b..02e2900ac8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -125,6 +125,8 @@ class XList extends Action $attribute = $this->isCollectionsAPI() ? 'attribute' : 'column'; $message = "The order $attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all $documents order $attribute values are non-null."; throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, $message); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } $operations = 0; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index 5929d56a91..caf6c72559 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -12,6 +12,7 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception\Order as OrderException; +use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Query\Cursor; @@ -80,7 +81,11 @@ class XList extends Action throw new Exception($this->getGrandParentNotFoundException()); } - $queries = Query::parseQueries($queries); + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } \array_push( $queries, @@ -126,6 +131,8 @@ class XList extends Action $attribute = $this->isCollectionsAPI() ? 'attribute' : 'column'; $message = "The order $attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all $documents order $attribute values are non-null."; throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, $message); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } $response->dynamic(new Document([ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index e9df7db598..15705e835e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -12,6 +12,7 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception\Order as OrderException; +use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Query\Cursor; @@ -73,7 +74,11 @@ class XList extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } - $queries = Query::parseQueries($queries); + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } if (!empty($search)) { $queries[] = Query::search('search', $search); @@ -108,11 +113,10 @@ class XList extends Action try { $collections = $dbForProject->find('database_' . $database->getSequence(), $queries); $total = $dbForProject->count('database_' . $database->getSequence(), $filterQueries, APP_LIMIT_COUNT); - } catch (OrderException $e) { - $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; - $attribute = $this->isCollectionsAPI() ? 'attribute' : 'column'; - $message = "The order $attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all $documents order $attribute values are non-null."; - throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, $message); + } catch (OrderException) { + throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL); + } catch (QueryException) { + throw new Exception(Exception::GENERAL_QUERY_INVALID); } $response->dynamic(new Document([ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php index 1fd0967b37..8bb9184baa 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php @@ -12,6 +12,7 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception\Order as OrderException; +use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Query\Cursor; use Utopia\Platform\Action; @@ -98,7 +99,10 @@ class XList extends Action $total = $dbForProject->count('databases', $filterQueries, APP_LIMIT_COUNT); } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); + } catch (QueryException) { + throw new Exception(Exception::GENERAL_QUERY_INVALID); } + $response->dynamic(new Document([ 'databases' => $databases, 'total' => $total, From 3a88c74109a1a1fea51dd8e3ea4b902d9259264e Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 11 Jun 2025 16:18:06 +0530 Subject: [PATCH 136/343] update: remove structure exceptions from global handler. --- app/controllers/general.php | 9 --- .../Collections/Attributes/Action.php | 11 ++-- .../Collections/Documents/Update.php | 2 - .../Databases/Http/Databases/Create.php | 60 ++++++++++--------- 4 files changed, 38 insertions(+), 44 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 9d9a03db92..0d0a253661 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1177,15 +1177,6 @@ App::error() case 'Utopia\Database\Exception\Timeout': $error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error); break; - case 'Utopia\Database\Exception\Structure': - $error = new AppwriteException( - $isTablesAPI - ? AppwriteException::ROW_INVALID_STRUCTURE - : AppwriteException::DOCUMENT_INVALID_STRUCTURE, - $error->getMessage(), - previous: $error - ); - break; case 'Utopia\Database\Exception\Duplicate': $error = new AppwriteException( $isTablesAPI diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 92751bcbe4..3939a0370c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -395,17 +395,20 @@ abstract class Action extends UtopiaAction $dbForProject->checkAttribute($relatedCollection, $twoWayAttribute); $dbForProject->createDocument('attributes', $twoWayAttribute); } catch (DuplicateException) { - $dbForProject->deleteDocument('attributes', $attribute->getId()); throw new Exception($this->getDuplicateException()); } catch (LimitException) { - $dbForProject->deleteDocument('attributes', $attribute->getId()); throw new Exception($this->getLimitException()); + } catch (StructureException) { + throw new Exception($this->getInvalidStructureException()); } catch (Throwable $e) { - $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $relatedCollection->getId()); - $dbForProject->purgeCachedCollection('database_' . $db->getSequence() . '_collection_' . $relatedCollection->getSequence()); + $dbForProject->deleteDocument('attributes', $attribute->getId()); throw $e; + } finally { + $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $db->getSequence() . '_collection_' . $collection->getSequence()); } + // If operation succeeded, purge the cache for the related collection too $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $relatedCollection->getId()); $dbForProject->purgeCachedCollection('database_' . $db->getSequence() . '_collection_' . $relatedCollection->getSequence()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index c3a2fe6df3..f69dfb3f98 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -228,8 +228,6 @@ class Update extends Action ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); - $response->addHeader('X-Debug-Operations', $operations); - try { $document = $dbForProject->withRequestTimestamp( $requestTimestamp, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php index 1f368ec77a..6e4dc5e136 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php @@ -14,6 +14,9 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate as DuplicateException; +use Utopia\Database\Exception\Index as IndexException; +use Utopia\Database\Exception\Limit as LimitException; +use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -76,42 +79,41 @@ class Create extends Action 'enabled' => $enabled, 'search' => implode(' ', [$databaseId, $name]), ])); - $database = $dbForProject->getDocument('databases', $databaseId); + } catch (DuplicateException) { + throw new Exception(Exception::DATABASE_ALREADY_EXISTS); + } catch (StructureException $e) { + // TODO: @Jake, how do we handle this document/row? + // there's no context awareness at this level on what the api is. + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); + } - $collections = (Config::getParam('collections', [])['databases'] ?? [])['collections'] ?? []; - if (empty($collections)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'The "collections" collection is not configured.'); - } + $database = $dbForProject->getDocument('databases', $databaseId); - $attributes = []; - $indexes = []; + $collections = (Config::getParam('collections', [])['databases'] ?? [])['collections'] ?? []; + if (empty($collections)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'The "collections" collection is not configured.'); + } - foreach ($collections['attributes'] as $attribute) { - $attributes[] = new Document([ - '$id' => $attribute['$id'], - 'type' => $attribute['type'], - 'size' => $attribute['size'], - 'required' => $attribute['required'], - 'signed' => $attribute['signed'], - 'array' => $attribute['array'], - 'filters' => $attribute['filters'], - 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '' - ]); - } + $attributes = []; + foreach ($collections['attributes'] as $attribute) { + $attributes[] = new Document($attribute); + } - foreach ($collections['indexes'] as $index) { - $indexes[] = new Document([ - '$id' => $index['$id'], - 'type' => $index['type'], - 'attributes' => $index['attributes'], - 'lengths' => $index['lengths'], - 'orders' => $index['orders'], - ]); - } + $indexes = []; + foreach ($collections['indexes'] as $index) { + $indexes[] = new Document($index); + } + + try { $dbForProject->createCollection('database_' . $database->getSequence(), $attributes, $indexes); } catch (DuplicateException) { throw new Exception(Exception::DATABASE_ALREADY_EXISTS); + } catch (IndexException) { + throw new Exception(Exception::INDEX_INVALID); + } catch (LimitException) { + // TODO: @Jake, how do we handle this collection/table? + // there's no context awareness at this level on what the api is. + throw new Exception(Exception::COLLECTION_LIMIT_EXCEEDED); } $queueForEvents->setParam('databaseId', $database->getId()); From 6b53337a23be7a29c8faafe248f1600a20d2ee04 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 11 Jun 2025 16:44:32 +0530 Subject: [PATCH 137/343] update: remove duplicate exceptions from global handler. --- app/controllers/general.php | 7 ------- .../Http/Databases/Collections/Action.php | 10 ++++++++++ .../Collections/Attributes/Action.php | 19 +++++++++++-------- .../Http/Databases/Collections/Create.php | 19 +++++++++++++++++++ .../Collections/Documents/Create.php | 7 +++++-- 5 files changed, 45 insertions(+), 17 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 0d0a253661..6602198c0b 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1177,13 +1177,6 @@ App::error() case 'Utopia\Database\Exception\Timeout': $error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error); break; - case 'Utopia\Database\Exception\Duplicate': - $error = new AppwriteException( - $isTablesAPI - ? AppwriteException::ROW_ALREADY_EXISTS - : AppwriteException::DOCUMENT_ALREADY_EXISTS - ); - // no break case 'Utopia\Database\Exception\Authorization': $error = new AppwriteException(AppwriteException::USER_UNAUTHORIZED); break; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php index abec90f1a6..1028f4ea7f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php @@ -73,6 +73,16 @@ abstract class Action extends UtopiaAction : Exception::TABLE_ALREADY_EXISTS; } + /** + * Get the appropriate index invalid exception. + */ + final protected function getInvalidIndexException(): string + { + return $this->isCollectionsAPI() + ? Exception::INDEX_INVALID + : Exception::COLUMN_INDEX_INVALID; + } + /** * Get the exception to throw when the resource is not found. */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 3939a0370c..088490ad02 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -13,7 +13,6 @@ use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Exception\Index as IndexException; use Utopia\Database\Exception\Limit as LimitException; -use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Exception\Relationship as RelationshipException; use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Exception\Truncate as TruncateException; @@ -592,14 +591,14 @@ abstract class Action extends UtopiaAction formatOptions: $options, newKey: $newKey ?? null ); - } catch (TruncateException) { - throw new Exception($this->getInvalidResizeException()); - } catch (NotFoundException) { - throw new Exception($this->getNotFoundException()); - } catch (LimitException) { - throw new Exception($this->getLimitException()); + } catch (DuplicateException) { + throw new Exception($this->getDuplicateException()); } catch (IndexException $e) { throw new Exception($this->getInvalidIndexException(), $e->getMessage()); + } catch (LimitException) { + throw new Exception($this->getLimitException()); + } catch (TruncateException) { + throw new Exception($this->getInvalidResizeException()); } } @@ -610,7 +609,11 @@ abstract class Action extends UtopiaAction ->setAttribute('$id', ID::custom($db->getSequence() . '_' . $collection->getSequence() . '_' . $newKey)) ->setAttribute('key', $newKey); - $dbForProject->updateDocument('attributes', $originalUid, $attribute); + try { + $dbForProject->updateDocument('attributes', $originalUid, $attribute); + } catch (DuplicateException) { + throw new Exception($this->getDuplicateException()); + } /** * @var Document $index diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php index 6b80901e05..b5e7bf5415 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -13,7 +13,9 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate as DuplicateException; +use Utopia\Database\Exception\Index as IndexException; use Utopia\Database\Exception\Limit as LimitException; +use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Validator\Authorization; @@ -86,6 +88,7 @@ class Create extends Action $collectionId = $collectionId === 'unique()' ? ID::unique() : $collectionId; + // Map aggregate permissions into the multiple permissions they represent. $permissions = Permission::aggregate($permissions) ?? []; try { @@ -105,6 +108,22 @@ class Create extends Action throw new Exception($this->getDuplicateException()); } catch (LimitException) { throw new Exception($this->getLimitException()); + } catch (NotFoundException) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + try { + $dbForProject->createCollection( + id: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + permissions: $permissions, + documentSecurity: $documentSecurity + ); + } catch (DuplicateException) { + throw new Exception($this->getDuplicateException()); + } catch (IndexException) { + throw new Exception($this->getInvalidIndexException()); + } catch (LimitException) { + throw new Exception($this->getLimitException()); } $queueForEvents diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index 23883c9ff4..aef2ef4ace 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -16,6 +16,7 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Exception\NotFound as NotFoundException; +use Utopia\Database\Exception\Relationship as RelationshipException; use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -245,12 +246,14 @@ class Create extends Action try { $document = $dbForProject->createDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $document); - } catch (StructureException $e) { - throw new Exception($this->getInvalidStructureException(), $e->getMessage()); } catch (DuplicateException) { throw new Exception($this->getDuplicateException()); } catch (NotFoundException) { throw new Exception($this->getParentNotFoundException()); + } catch (RelationshipException $e) { + throw new Exception(Exception::RELATIONSHIP_VALUE_INVALID, $e->getMessage()); + } catch (StructureException $e) { + throw new Exception($this->getInvalidStructureException(), $e->getMessage()); } // Add $collectionId and $databaseId for all documents From dc439d1a1670f9a61bcb24ae5106f282f167f744 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 11 Jun 2025 16:46:21 +0530 Subject: [PATCH 138/343] update: remove authorization from global handler. --- app/controllers/general.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 6602198c0b..3a2a4c9d16 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1177,9 +1177,6 @@ App::error() case 'Utopia\Database\Exception\Timeout': $error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error); break; - case 'Utopia\Database\Exception\Authorization': - $error = new AppwriteException(AppwriteException::USER_UNAUTHORIZED); - break; case 'Utopia\Database\Exception\NotFound': $error = new AppwriteException( $isTablesAPI From 86a9598a5154188d2c11e3afc7ed26fec804049b Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 11 Jun 2025 16:51:09 +0530 Subject: [PATCH 139/343] update: remove not-found and index dependency exceptions from global handler. --- app/controllers/general.php | 18 ------------------ .../Collections/Attributes/Delete.php | 1 + 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 3a2a4c9d16..138e96f88a 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1177,24 +1177,6 @@ App::error() case 'Utopia\Database\Exception\Timeout': $error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error); break; - case 'Utopia\Database\Exception\NotFound': - $error = new AppwriteException( - $isTablesAPI - ? AppwriteException::TABLE_NOT_FOUND - : AppwriteException::COLLECTION_NOT_FOUND, - $error->getMessage(), - previous: $error - ); - break; - case 'Utopia\Database\Exception\Dependency': - $error = new AppwriteException( - $isTablesAPI - ? AppwriteException::COLUMN_INDEX_DEPENDENCY - : AppwriteException::INDEX_DEPENDENCY, - null, - previous: $error - ); - break; } $code = $error->getCode(); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 1f31097caf..242f6a4ea0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -90,6 +90,7 @@ class Delete extends Action $collection->getAttribute('indexes'), $dbForProject->getAdapter()->getSupportForCastIndexArray(), ); + if (!$validator->isValid($attribute)) { throw new Exception($this->getIndexDependencyException()); } From 3e1adc600409620c9bab9b03dc23a712aafdadbe Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 11 Jun 2025 16:51:27 +0530 Subject: [PATCH 140/343] remove: `$isTablesAPI` var. --- app/controllers/general.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 138e96f88a..416e6b1e86 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1159,9 +1159,6 @@ App::error() Console::error('[Error] Line: ' . $line); } - // routes like /tables, /tables/:tableId, etc. - $isTablesAPI = str_contains($route->getPath(), '/databases/:databaseId/tables'); - switch ($class) { case 'Utopia\Exception': $error = new AppwriteException(AppwriteException::GENERAL_UNKNOWN, $message, $code, $error); From 8e2eff7894dabc8d55fd96c79c94adc0932d90d7 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 11 Jun 2025 16:53:14 +0530 Subject: [PATCH 141/343] rollback: auth exception as per `1.8.x` source. --- app/controllers/general.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/controllers/general.php b/app/controllers/general.php index 416e6b1e86..0b64f30631 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1171,6 +1171,9 @@ App::error() break; } break; + case 'Utopia\Database\Exception\Authorization': + $error = new AppwriteException(AppwriteException::USER_UNAUTHORIZED); + break; case 'Utopia\Database\Exception\Timeout': $error = new AppwriteException(AppwriteException::DATABASE_TIMEOUT, previous: $error); break; From 7169e672459468c3ec5d3f9043cd6a7147f5c574 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 11 Jun 2025 20:05:09 +0530 Subject: [PATCH 142/343] add/update: `createDocuments` on module structure. --- .../Collections/Documents/Action.php | 25 +- .../Collections/Documents/Create.php | 269 +++++++++++++----- .../Http/Databases/Tables/Rows/Create.php | 38 ++- 3 files changed, 257 insertions(+), 75 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index 32bb314cd2..c4e41d415f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -17,6 +17,11 @@ abstract class Action extends UtopiaAction */ abstract protected function getResponseModel(): string; + /** + * Get the response model used in the SDK and HTTP responses for bulk action. + */ + abstract protected function getBulkResponseModel(): string; + /** * Set the context to either `row` or `document`. * @@ -25,12 +30,22 @@ abstract class Action extends UtopiaAction final protected function setContext(string $context): void { if (!\in_array($context, [DATABASE_ROWS_CONTEXT, DATABASE_DOCUMENTS_CONTEXT], true)) { - throw new \InvalidArgumentException("Invalid context '{$context}'. Use `DATABASE_ROWS_CONTEXT` or `DATABASE_DOCUMENTS_CONTEXT`"); + throw new \InvalidArgumentException("Invalid context '$context'. Use `DATABASE_ROWS_CONTEXT` or `DATABASE_DOCUMENTS_CONTEXT`"); } $this->context = $context; } + /** + * Get the plural of the given name. + * + * Used for endpoints with multiple sdk methods. + */ + final protected function getBulkActionName(string $name): string + { + return "{$name}s"; + } + /** * Get the current context. */ @@ -67,6 +82,14 @@ abstract class Action extends UtopiaAction return $this->isCollectionsAPI() ? 'collections' : 'tables'; } + /** + * Get the correct attribute/column structure context for errors. + */ + final protected function getStructureContext(): string + { + return $this->isCollectionsAPI() ? 'attributes' : 'columns'; + } + /** * Get the appropriate parent level not found exception. */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index aef2ef4ace..b55731a4f2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -9,6 +9,7 @@ use Appwrite\Extend\Exception; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; +use Appwrite\SDK\Parameter; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Response as UtopiaResponse; @@ -26,6 +27,7 @@ use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; +use Utopia\Validator\ArrayList; use Utopia\Validator\JSON; class Create extends Action @@ -42,6 +44,11 @@ class Create extends Action return UtopiaResponse::MODEL_DOCUMENT; } + protected function getBulkResponseModel(): string + { + return UtopiaResponse::MODEL_DOCUMENT_LIST; + } + public function __construct() { $this @@ -70,14 +77,41 @@ class Create extends Action model: $this->getResponseModel(), ) ], - contentType: ContentType::JSON + contentType: ContentType::JSON, + parameters: [ + new Parameter('databaseId', optional: false), + new Parameter('collectionId', optional: false), + new Parameter('documentId', optional: false), + new Parameter('data', optional: false), + new Parameter('permissions', optional: true), + ] + ), + new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: $this->getBulkActionName(self::getName()), + description: '/docs/references/databases/create-documents.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_CREATED, + model: $this->getBulkResponseModel(), + ) + ], + contentType: ContentType::JSON, + parameters: [ + new Parameter('databaseId', optional: false), + new Parameter('collectionId', optional: false), + new Parameter('documents', optional: false), + ] ) ]) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('documentId', '', new CustomId(), 'Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('documentId', '', new CustomId(), 'Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', true) ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define attributes before creating documents.') - ->param('data', [], new JSON(), 'Document data as JSON object.') + ->param('data', [], new JSON(), 'Document data as JSON object.', true) ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->param('documents', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of documents data as JSON objects.', true, ['plan']) ->inject('response') ->inject('dbForProject') ->inject('user') @@ -86,77 +120,128 @@ class Create extends Action ->callback([$this, 'action']); } - public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage): void + public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage): void { - $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array + $data = \is_string($data) + ? \json_decode($data, true) + : $data; - if (empty($data)) { + /** + * Determine which internal path to call, single or bulk + */ + if (empty($data) && empty($documents)) { + // No single or bulk documents provided throw new Exception($this->getMissingDataException()); } - - if (isset($data['$id'])) { - // `rows` or `documents` in message. - throw new Exception($this->getInvalidStructureException(), '$id is not allowed for creating new ' . $this->getContext() . 's, try update instead'); + if (!empty($data) && !empty($documents)) { + // Both single and bulk documents provided + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'You can only send one of the following parameters: data, ' . $this->getSdkGroup()); + } + if (!empty($data) && empty($documentId)) { + // Single document provided without document ID + $document = $this->isCollectionsAPI() ? 'Document' : 'Row'; + $message = "$document ID is required when creating a single " . strtolower($document) . '.'; + throw new Exception($this->getMissingDataException(), $message); + } + if (!empty($documents) && !empty($documentId)) { + // Bulk documents provided with document ID + $documentId = $this->isCollectionsAPI() ? 'documentId' : 'rowId'; + throw new Exception( + Exception::GENERAL_BAD_REQUEST, + "Param \"$documentId\" is not allowed when creating multiple " . $this->getSdkGroup() . ', set "$id" on each instead.' + ); + } + if (!empty($documents) && !empty($permissions)) { + // Bulk documents provided with permissions + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Param "permissions" is disallowed when creating multiple ' . $this->getSdkGroup() . ', set "$permissions" on each instead'); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $isBulk = true; + if (!empty($data)) { + // Single document provided, convert to single item array + // But remember that it was single to respond with a single document + $isBulk = false; + $documents = [$data]; + } $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + if ($isBulk && !$isAPIKey && !$isPrivilegedUser) { + throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE); + } + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); - if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); } - $allowedPermissions = [ - Database::PERMISSION_READ, - Database::PERMISSION_UPDATE, - Database::PERMISSION_DELETE, - ]; + $hasRelationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); - // Map aggregate permissions to into the set of individual permissions they represent. - $permissions = Permission::aggregate($permissions, $allowedPermissions); - - // Add permissions for current the user if none were provided. - if (\is_null($permissions)) { - $permissions = []; - if (!empty($user->getId())) { - foreach ($allowedPermissions as $permission) { - $permissions[] = (new Permission($permission, 'user', $user->getId()))->toString(); - } - } + if ($isBulk && $hasRelationships) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk create is not supported for ' . $this->getSdkNamespace() .' with relationship ' . $this->getStructureContext()); } - // Users can only manage their own roles, API keys and Admin users can manage any - if (!$isAPIKey && !$isPrivilegedUser) { - foreach (Database::PERMISSIONS as $type) { - foreach ($permissions as $permission) { - $permission = Permission::parse($permission); - if ($permission->getPermission() != $type) { - continue; - } - $role = (new Role( - $permission->getRole(), - $permission->getIdentifier(), - $permission->getDimension() - ))->toString(); - if (!Authorization::isRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')'); + $setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk) { + $allowedPermissions = [ + Database::PERMISSION_READ, + Database::PERMISSION_UPDATE, + Database::PERMISSION_DELETE, + ]; + + // If bulk, we need to validate permissions explicitly per document + if ($isBulk) { + $permissions = $document['$permissions'] ?? null; + if (!empty($permissions)) { + $validator = new Permissions(); + if (!$validator->isValid($permissions)) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, $validator->getDescription()); } } } - } - $data['$collection'] = $collection->getId(); // Adding this param to make API easier for developers - $data['$id'] = $documentId == 'unique()' ? ID::unique() : $documentId; - $data['$permissions'] = $permissions; - $document = new Document($data); + $permissions = Permission::aggregate($permissions, $allowedPermissions); + + // Add permissions for current the user if none were provided. + if (\is_null($permissions)) { + $permissions = []; + if (!empty($user->getId())) { + foreach ($allowedPermissions as $permission) { + $permissions[] = (new Permission($permission, 'user', $user->getId()))->toString(); + } + } + } + + // Users can only manage their own roles, API keys and Admin users can manage any + if (!$isAPIKey && !$isPrivilegedUser) { + foreach (Database::PERMISSIONS as $type) { + foreach ($permissions as $permission) { + $permission = Permission::parse($permission); + if ($permission->getPermission() != $type) { + continue; + } + $role = (new Role( + $permission->getRole(), + $permission->getIdentifier(), + $permission->getDimension() + ))->toString(); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', Authorization::getRoles()) . ')'); + } + } + } + } + + $document->setAttribute('$permissions', $permissions); + }; $operations = 0; @@ -242,10 +327,36 @@ class Create extends Action } }; - $checkPermissions($collection, $document, Database::PERMISSION_CREATE); + $documents = \array_map(function ($document) use ($collection, $permissions, $checkPermissions, $isBulk, $documentId, $setPermissions) { + $document['$collection'] = $collection->getId(); + + // Determine the source ID depending on whether it's a bulk operation. + $sourceId = $isBulk + ? ($document['$id'] ?? ID::unique()) + : $documentId; + + // If bulk, we need to validate ID explicitly + if ($isBulk) { + $validator = new CustomId(); + if (!$validator->isValid($sourceId)) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, $validator->getDescription()); + } + } + + // Assign a unique ID if needed, otherwise use the provided ID. + $document['$id'] = $sourceId === 'unique()' ? ID::unique() : $sourceId; + $document = new Document($document); + $setPermissions($document, $permissions); + $checkPermissions($collection, $document, Database::PERMISSION_CREATE); + + return $document; + }, $documents); try { - $document = $dbForProject->createDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $document); + $dbForProject->createDocuments( + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + $documents + ); } catch (DuplicateException) { throw new Exception($this->getDuplicateException()); } catch (NotFoundException) { @@ -256,8 +367,22 @@ class Create extends Action throw new Exception($this->getInvalidStructureException(), $e->getMessage()); } + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setParam('collectionId', $collection->getId()) + ->setContext('collection', $collection) + ->setContext('database', $database); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setContext('database', $database) + ->setParam('collectionId', $collection->getId()) + ->setParam('tableId', $collection->getId()) + ->setContext($this->getCollectionsEventsContext(), $collection); + // Add $collectionId and $databaseId for all documents $processDocument = function (Document $table, Document $document) use (&$processDocument, $dbForProject, $database) { + $document->removeAttribute('$collection'); $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $table->getId()); @@ -289,34 +414,34 @@ class Create extends Action } }; - $processDocument($collection, $document); + foreach ($documents as $document) { + $processDocument($collection, $document); + } $queueForStatsUsage - ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) - ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); // per collection + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); // per collection - $response->addHeader('X-Debug-Operations', $operations); + $response->setStatusCode(SwooleResponse::STATUS_CODE_CREATED); - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) - ->dynamic($document, $this->getResponseModel()); + if ($isBulk) { + $response->dynamic(new Document([ + 'total' => count($documents), + $this->getSdkGroup() => $documents + ]), $this->getBulkResponseModel()); - $relationships = \array_map( - fn ($document) => $document->getAttribute('key'), - \array_filter( - $collection->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ) - ); + return; + } $queueForEvents - ->setParam('databaseId', $databaseId) - ->setContext('database', $database) - ->setParam('collectionId', $collection->getId()) - ->setParam('tableId', $collection->getId()) - ->setParam('documentId', $document->getId()) - ->setParam('rowId', $document->getId()) - ->setPayload($response->getPayload(), sensitive: $relationships) - ->setContext($this->getCollectionsEventsContext(), $collection); + ->setParam('documentId', $documents[0]->getId()) + ->setParam('rowId', $documents[0]->getId()) + // TODO: @itznotabug - check if the events mirroring works here! + ->setEvent('databases.[databaseId].collections.[collectionId].documents.[documentId].create'); + + $response->dynamic( + $documents[0], + $this->getResponseModel() + ); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php index d041630894..881e562c10 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php @@ -6,6 +6,7 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Cre use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; +use Appwrite\SDK\Parameter; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Response as UtopiaResponse; @@ -14,6 +15,7 @@ use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; +use Utopia\Validator\ArrayList; use Utopia\Validator\JSON; class Create extends DocumentCreate @@ -30,6 +32,11 @@ class Create extends DocumentCreate return UtopiaResponse::MODEL_ROW; } + protected function getBulkResponseModel(): string + { + return UtopiaResponse::MODEL_ROW_LIST; + } + public function __construct() { $this->setContext(DATABASE_ROWS_CONTEXT); @@ -57,10 +64,36 @@ class Create extends DocumentCreate responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_CREATED, - model: self::getResponseModel(), + model: $this->getResponseModel(), ) ], - contentType: ContentType::JSON + contentType: ContentType::JSON, + parameters: [ + new Parameter('databaseId', optional: false), + new Parameter('tableId', optional: false), + new Parameter('rowId', optional: false), + new Parameter('data', optional: false), + new Parameter('permissions', optional: true), + ] + ), + new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: $this->getBulkActionName(self::getName()), + description: '/docs/references/databases/create-documents.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_CREATED, + model: $this->getBulkResponseModel(), + ) + ], + contentType: ContentType::JSON, + parameters: [ + new Parameter('databaseId', optional: false), + new Parameter('tableId', optional: false), + new Parameter('rows', optional: false), + ] ) ]) ->param('databaseId', '', new UID(), 'Database ID.') @@ -68,6 +101,7 @@ class Create extends DocumentCreate ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define columns before creating rows.') ->param('data', [], new JSON(), 'Row data as JSON object.') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->param('rows', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of documents data as JSON objects.', true, ['plan']) ->inject('response') ->inject('dbForProject') ->inject('user') From 7beae215352fcab2f8d1623cfde1ac833735b903 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 14:20:22 +0530 Subject: [PATCH 143/343] fix: missing context! --- .../Platform/Modules/Databases/Constants.php | 23 ---------------- .../Platform/Modules/Databases/Context.php | 26 +++++++++++++++++++ .../Http/Databases/Collections/Action.php | 11 ++++---- .../Collections/Attributes/Action.php | 9 ++++--- .../Collections/Documents/Action.php | 14 ++++------ .../Databases/Collections/Indexes/Action.php | 17 ++++++------ .../Tables/Columns/Boolean/Create.php | 3 ++- .../Tables/Columns/Boolean/Update.php | 3 ++- .../Tables/Columns/Datetime/Create.php | 3 ++- .../Tables/Columns/Datetime/Update.php | 3 ++- .../Http/Databases/Tables/Columns/Delete.php | 3 ++- .../Databases/Tables/Columns/Email/Create.php | 3 ++- .../Databases/Tables/Columns/Email/Update.php | 3 ++- .../Databases/Tables/Columns/Enum/Create.php | 3 ++- .../Databases/Tables/Columns/Enum/Update.php | 3 ++- .../Databases/Tables/Columns/Float/Create.php | 3 ++- .../Databases/Tables/Columns/Float/Update.php | 3 ++- .../Http/Databases/Tables/Columns/Get.php | 3 ++- .../Databases/Tables/Columns/IP/Create.php | 3 ++- .../Databases/Tables/Columns/IP/Update.php | 3 ++- .../Tables/Columns/Integer/Create.php | 3 ++- .../Tables/Columns/Integer/Update.php | 3 ++- .../Tables/Columns/Relationship/Create.php | 3 ++- .../Tables/Columns/Relationship/Update.php | 3 ++- .../Tables/Columns/String/Create.php | 3 ++- .../Tables/Columns/String/Update.php | 3 ++- .../Databases/Tables/Columns/URL/Create.php | 3 ++- .../Databases/Tables/Columns/URL/Update.php | 3 ++- .../Http/Databases/Tables/Columns/XList.php | 3 ++- .../Http/Databases/Tables/Create.php | 3 ++- .../Http/Databases/Tables/Delete.php | 3 ++- .../Databases/Http/Databases/Tables/Get.php | 3 ++- .../Http/Databases/Tables/Indexes/Create.php | 3 ++- .../Http/Databases/Tables/Indexes/Delete.php | 3 ++- .../Http/Databases/Tables/Indexes/Get.php | 3 ++- .../Http/Databases/Tables/Indexes/XList.php | 3 ++- .../Http/Databases/Tables/Logs/XList.php | 3 ++- .../Http/Databases/Tables/Rows/Create.php | 3 ++- .../Http/Databases/Tables/Rows/Delete.php | 3 ++- .../Http/Databases/Tables/Rows/Get.php | 3 ++- .../Http/Databases/Tables/Rows/Logs/XList.php | 3 ++- .../Http/Databases/Tables/Rows/Update.php | 3 ++- .../Http/Databases/Tables/Rows/XList.php | 3 ++- .../Http/Databases/Tables/Update.php | 3 ++- .../Http/Databases/Tables/Usage/Get.php | 3 ++- .../Databases/Http/Databases/Tables/XList.php | 3 ++- 46 files changed, 131 insertions(+), 89 deletions(-) delete mode 100644 src/Appwrite/Platform/Modules/Databases/Constants.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Context.php diff --git a/src/Appwrite/Platform/Modules/Databases/Constants.php b/src/Appwrite/Platform/Modules/Databases/Constants.php deleted file mode 100644 index b17248bf4d..0000000000 --- a/src/Appwrite/Platform/Modules/Databases/Constants.php +++ /dev/null @@ -1,23 +0,0 @@ -context = $context; @@ -52,7 +53,7 @@ abstract class Action extends UtopiaAction */ final protected function isCollectionsAPI(): bool { - return $this->getContext() === DATABASE_COLLECTIONS_CONTEXT; + return $this->getContext() === Context::DATABASE_COLLECTIONS; } /** diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 088490ad02..2ee265a18d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -5,6 +5,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attribu use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response as UtopiaResponse; use Throwable; @@ -28,7 +29,7 @@ abstract class Action extends UtopiaAction /** * @var string|null The current context (either 'column' or 'attribute') */ - private ?string $context = DATABASE_ATTRIBUTES_CONTEXT; + private ?string $context = Context::DATABASE_ATTRIBUTES; /** * Get the correct response model. @@ -42,8 +43,8 @@ abstract class Action extends UtopiaAction */ final protected function setContext(string $context): void { - if (!\in_array($context, [DATABASE_COLUMNS_CONTEXT, DATABASE_ATTRIBUTES_CONTEXT], true)) { - throw new \InvalidArgumentException("Invalid context '$context'. Use `DATABASE_COLUMNS_CONTEXT` or `DATABASE_ATTRIBUTES_CONTEXT`"); + if (!\in_array($context, [Context::DATABASE_COLUMNS, Context::DATABASE_ATTRIBUTES], true)) { + throw new \InvalidArgumentException("Invalid context '$context'. Use `Context::DATABASE_COLUMNS` or `Context::DATABASE_ATTRIBUTES`"); } $this->context = $context; @@ -64,7 +65,7 @@ abstract class Action extends UtopiaAction { // columns in tables context // attributes in collections context - return $this->getContext() === DATABASE_ATTRIBUTES_CONTEXT; + return $this->getContext() === Context::DATABASE_ATTRIBUTES; } /** diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index c4e41d415f..341302f779 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents; use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Context; use Utopia\Platform\Action as UtopiaAction; abstract class Action extends UtopiaAction @@ -10,18 +11,13 @@ abstract class Action extends UtopiaAction /** * @var string|null The current context (either 'row' or 'document') */ - private ?string $context = DATABASE_DOCUMENTS_CONTEXT; + private ?string $context = Context::DATABASE_DOCUMENTS; /** * Get the response model used in the SDK and HTTP responses. */ abstract protected function getResponseModel(): string; - /** - * Get the response model used in the SDK and HTTP responses for bulk action. - */ - abstract protected function getBulkResponseModel(): string; - /** * Set the context to either `row` or `document`. * @@ -29,8 +25,8 @@ abstract class Action extends UtopiaAction */ final protected function setContext(string $context): void { - if (!\in_array($context, [DATABASE_ROWS_CONTEXT, DATABASE_DOCUMENTS_CONTEXT], true)) { - throw new \InvalidArgumentException("Invalid context '$context'. Use `DATABASE_ROWS_CONTEXT` or `DATABASE_DOCUMENTS_CONTEXT`"); + if (!\in_array($context, [Context::DATABASE_ROWS, Context::DATABASE_DOCUMENTS], true)) { + throw new \InvalidArgumentException("Invalid context '$context'. Use `Context::DATABASE_ROWS` or `Context::DATABASE_DOCUMENTS`"); } $this->context = $context; @@ -61,7 +57,7 @@ abstract class Action extends UtopiaAction { // rows in tables api context // documents in collections api context - return $this->getContext() === DATABASE_DOCUMENTS_CONTEXT; + return $this->getContext() === Context::DATABASE_DOCUMENTS; } /** diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php index 07a32ce122..4a40ea6b5f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes; use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Databases\Context; use Utopia\Platform\Action as UtopiaAction; abstract class Action extends UtopiaAction @@ -10,7 +11,7 @@ abstract class Action extends UtopiaAction /** * The current API context (either 'columnIndex' or 'index'). */ - private ?string $context = DATABASE_INDEX_CONTEXT; + private ?string $context = Context::DATABASE_INDEX; /** * Get the response model used in the SDK and HTTP responses. @@ -20,12 +21,12 @@ abstract class Action extends UtopiaAction /** * Set the current API context. * - * @param string $context Must be either `DATABASE_INDEX_CONTEXT` or `DATABASE_COLUMN_INDEX_CONTEXT`. + * @param string $context Must be either `DATABASE_INDEX` or `DATABASE_COLUMN_INDEX`. */ final protected function setContext(string $context): void { - if (!\in_array($context, [DATABASE_INDEX_CONTEXT, DATABASE_COLUMN_INDEX_CONTEXT], true)) { - throw new \InvalidArgumentException("Invalid context '$context'. Must be either `DATABASE_COLUMN_INDEX_CONTEXT` or `DATABASE_INDEX_CONTEXT`."); + if (!\in_array($context, [Context::DATABASE_INDEX, Context::DATABASE_COLUMN_INDEX], true)) { + throw new \InvalidArgumentException("Invalid context '$context'. Must be either `Context::DATABASE_COLUMN_INDEX` or `Context::DATABASE_INDEX`."); } $this->context = $context; @@ -36,9 +37,9 @@ abstract class Action extends UtopiaAction */ final protected function getParentContext(): string { - return $this->getContext() === DATABASE_INDEX_CONTEXT - ? DATABASE_ATTRIBUTES_CONTEXT - : DATABASE_COLUMNS_CONTEXT; + return $this->getContext() === Context::DATABASE_INDEX + ? Context::DATABASE_ATTRIBUTES + : Context::DATABASE_COLUMNS; } /** @@ -54,7 +55,7 @@ abstract class Action extends UtopiaAction */ final protected function isCollectionsAPI(): bool { - return $this->getParentContext() === DATABASE_ATTRIBUTES_CONTEXT; + return $this->getParentContext() === Context::DATABASE_ATTRIBUTES; } /** diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php index ada1d83424..e1633da062 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Boolean; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Boolean\Create as BooleanCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -29,7 +30,7 @@ class Create extends BooleanCreate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php index 5316677adc..deead5e1d7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Boolean; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Boolean\Update as BooleanUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -31,7 +32,7 @@ class Update extends BooleanUpdate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php index a0731f0767..4710031c63 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Datetime; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Datetime\Create as DatetimeCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -31,7 +32,7 @@ class Create extends DatetimeCreate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php index 495e96f025..f30e627553 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Datetime; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Datetime\Update as DatetimeUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -33,7 +34,7 @@ class Update extends DatetimeUpdate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php index 68cb00e18b..d2f0c54839 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Delete as AttributesDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -30,7 +31,7 @@ class Delete extends AttributesDelete public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php index 569d641118..fc64c3b215 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Email; use Appwrite\Network\Validator\Email; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Email\Create as EmailCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -30,7 +31,7 @@ class Create extends EmailCreate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php index bb3abb10d3..c6425043b5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Email; use Appwrite\Network\Validator\Email; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Email\Update as EmailUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -32,7 +33,7 @@ class Update extends EmailUpdate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php index 47d06d4a53..338cec4f05 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Enum; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Enum\Create as EnumCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -32,7 +33,7 @@ class Create extends EnumCreate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php index 18c1db0683..6a35b955d2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Enum; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Enum\Update as EnumUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -34,7 +35,7 @@ class Update extends EnumUpdate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php index 217378e274..7e1a502f2e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Float; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Float\Create as FloatCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -30,7 +31,7 @@ class Create extends FloatCreate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php index be9e2f6b09..05983a8153 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Float; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Float\Update as FloatUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -32,7 +33,7 @@ class Update extends FloatUpdate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php index 630ac01e0f..a0d8a3ce76 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Get as AttributesGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -39,7 +40,7 @@ class Get extends AttributesGet public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php index 4da949dd74..1bae06a360 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\IP; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\IP\Create as IPCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -30,7 +31,7 @@ class Create extends IPCreate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php index 7adda8a4d5..8174ad7860 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\IP; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\IP\Update as IPUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -32,7 +33,7 @@ class Update extends IPUpdate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php index 2172b5067b..2c6b7a84e7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Integer; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Integer\Create as IntegerCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -30,7 +31,7 @@ class Create extends IntegerCreate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php index 26f7e8625c..8375853e83 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Integer; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Integer\Update as IntegerUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -32,7 +33,7 @@ class Update extends IntegerUpdate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php index 76dd80cec9..6d3f26902d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Relationship; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Relationship\Create as RelationshipCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -31,7 +32,7 @@ class Create extends RelationshipCreate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php index b2229bb32d..8bed5013a9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Relationship; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Relationship\Update as RelationshipUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -31,7 +32,7 @@ class Update extends RelationshipUpdate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php index cf12e6582d..529f4f270d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\String; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\String\Create as StringCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -32,7 +33,7 @@ class Create extends StringCreate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php index 968b15bbef..7450af9eff 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\String; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\String\Update as StringUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -34,7 +35,7 @@ class Update extends StringUpdate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php index 8c9865cde0..07295b2d93 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\URL; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\URL\Create as URLCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -30,7 +31,7 @@ class Create extends URLCreate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php index e461befe0b..990fbee742 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\URL; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\URL\Update as URLUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -32,7 +33,7 @@ class Update extends URLUpdate public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php index 3dde78441d..41b1aee5c9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\XList as AttributesXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -28,7 +29,7 @@ class XList extends AttributesXList public function __construct() { - $this->setContext(DATABASE_COLUMNS_CONTEXT); + $this->setContext(Context::DATABASE_COLUMNS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php index fcd52d4854..95ef8bea4a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Create as CollectionCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -32,7 +33,7 @@ class Create extends CollectionCreate public function __construct() { - $this->setContext(DATABASE_TABLES_CONTEXT); + $this->setContext(Context::DATABASE_TABLES); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php index c24fad28ef..bb9b859a78 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Delete as CollectionDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -28,7 +29,7 @@ class Delete extends CollectionDelete public function __construct() { - $this->setContext(DATABASE_TABLES_CONTEXT); + $this->setContext(Context::DATABASE_TABLES); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php index e277db6d3d..cdf7950a1c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Get as CollectionGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -28,7 +29,7 @@ class Get extends CollectionGet public function __construct() { - $this->setContext(DATABASE_TABLES_CONTEXT); + $this->setContext(Context::DATABASE_TABLES); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php index b8e22cec71..33692b7a0c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Create as IndexCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -32,7 +33,7 @@ class Create extends IndexCreate public function __construct() { - $this->setContext(DATABASE_COLUMN_INDEX_CONTEXT); + $this->setContext(Context::DATABASE_COLUMN_INDEX); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php index ed8c355075..80581f7a6f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Delete as IndexDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -33,7 +34,7 @@ class Delete extends IndexDelete public function __construct() { - $this->setContext(DATABASE_COLUMN_INDEX_CONTEXT); + $this->setContext(Context::DATABASE_COLUMN_INDEX); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php index cd689316e6..d78761459a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Get as IndexGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -29,7 +30,7 @@ class Get extends IndexGet public function __construct() { - $this->setContext(DATABASE_COLUMN_INDEX_CONTEXT); + $this->setContext(Context::DATABASE_COLUMN_INDEX); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php index 3d0e7d5139..b16e328f27 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\XList as IndexXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -29,7 +30,7 @@ class XList extends IndexXList public function __construct() { - $this->setContext(DATABASE_COLUMN_INDEX_CONTEXT); + $this->setContext(Context::DATABASE_COLUMN_INDEX); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php index 967e53539c..99fbe99a34 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Logs; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Logs\XList as CollectionLogXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -25,7 +26,7 @@ class XList extends CollectionLogXList public function __construct() { - $this->setContext(DATABASE_TABLES_CONTEXT); + $this->setContext(Context::DATABASE_TABLES); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php index 881e562c10..5eb36598b2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Create as DocumentCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -39,7 +40,7 @@ class Create extends DocumentCreate public function __construct() { - $this->setContext(DATABASE_ROWS_CONTEXT); + $this->setContext(Context::DATABASE_ROWS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php index e40046bdf9..799f3cde05 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Delete as DocumentDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -34,7 +35,7 @@ class Delete extends DocumentDelete public function __construct() { - $this->setContext(DATABASE_ROWS_CONTEXT); + $this->setContext(Context::DATABASE_ROWS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php index 5ff02e96e8..8a8f9f3062 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Get as DocumentGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -30,7 +31,7 @@ class Get extends DocumentGet public function __construct() { - $this->setContext(DATABASE_ROWS_CONTEXT); + $this->setContext(Context::DATABASE_ROWS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php index 29a92413f9..62466eac13 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Logs; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Logs\XList as DocumentLogXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -25,7 +26,7 @@ class XList extends DocumentLogXList public function __construct() { - $this->setContext(DATABASE_ROWS_CONTEXT); + $this->setContext(Context::DATABASE_ROWS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php index 3c98d3c499..798bfddf51 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Update as DocumentUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -31,7 +32,7 @@ class Update extends DocumentUpdate public function __construct() { - $this->setContext(DATABASE_ROWS_CONTEXT); + $this->setContext(Context::DATABASE_ROWS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php index c74a87c842..1175515e5c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\XList as DocumentXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -30,7 +31,7 @@ class XList extends DocumentXList public function __construct() { - $this->setContext(DATABASE_ROWS_CONTEXT); + $this->setContext(Context::DATABASE_ROWS); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php index 70ac9d7b7c..14798f8513 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Update as CollectionUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -31,7 +32,7 @@ class Update extends CollectionUpdate public function __construct() { - $this->setContext(DATABASE_TABLES_CONTEXT); + $this->setContext(Context::DATABASE_TABLES); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php index e67850e361..1baebb23f2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Usage; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Usage\Get as CollectionUsageGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -29,7 +30,7 @@ class Get extends CollectionUsageGet public function __construct() { - $this->setContext(DATABASE_TABLES_CONTEXT); + $this->setContext(Context::DATABASE_TABLES); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php index b2f102cc55..1086f8f80e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\XList as CollectionXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -30,7 +31,7 @@ class XList extends CollectionXList public function __construct() { - $this->setContext(DATABASE_TABLES_CONTEXT); + $this->setContext(Context::DATABASE_TABLES); $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) From 95bc85f18d455111a80ebfb268ef788e1230123e Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 14:31:28 +0530 Subject: [PATCH 144/343] add: upsert for collections and tables. --- .../Collections/Documents/Upsert.php | 297 ++++++++++++++++++ .../Http/Databases/Tables/Rows/Upsert.php | 78 +++++ .../Services/Registry/Collections.php | 2 + .../Databases/Services/Registry/Tables.php | 2 + 4 files changed, 379 insertions(+) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php new file mode 100644 index 0000000000..efd950e846 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php @@ -0,0 +1,297 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') + ->desc('Upsert document') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].upsert') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'document.upsert') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{response.$id}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', [ + new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/upsert-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_CREATED, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + ), + ]) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('documentId', '', new CustomId(), 'Document ID.') + ->param('data', [], new JSON(), 'Document data as JSON object. Include all required attributes of the document to be created or updated.') + ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->inject('requestTimestamp') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->callback($this->action(...)); + } + + public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): void + { + $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array + + if (empty($data) && \is_null($permissions)) { + throw new Exception($this->getMissingPayloadException()); + } + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception($this->getParentNotFoundException()); + } + + // Map aggregate permissions into the multiple permissions they represent. + $permissions = Permission::aggregate($permissions, [ + Database::PERMISSION_READ, + Database::PERMISSION_UPDATE, + Database::PERMISSION_DELETE, + ]); + + // Users can only manage their own roles, API keys and Admin users can manage any + $roles = Authorization::getRoles(); + if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { + foreach (Database::PERMISSIONS as $type) { + foreach ($permissions as $permission) { + $permission = Permission::parse($permission); + if ($permission->getPermission() != $type) { + continue; + } + $role = (new Role( + $permission->getRole(), + $permission->getIdentifier(), + $permission->getDimension() + ))->toString(); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); + } + } + } + } + + $data['$id'] = $documentId; + $data['$permissions'] = $permissions; + $newDocument = new Document($data); + + $operations = 0; + + $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, &$operations) { + + $operations++; + + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + + $isList = \is_array($related) && \array_values($related) === $related; + + if ($isList) { + $relations = $related; + } else { + $relations = [$related]; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) + ); + + foreach ($relations as &$relation) { + // If the relation is an array it can be either update or create a child document. + if ( + \is_array($relation) + && \array_values($relation) !== $relation + && !isset($relation['$id']) + ) { + $relation['$id'] = ID::unique(); + $relation = new Document($relation); + } + if ($relation instanceof Document) { + $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), + $relation->getId() + )); + $relation->removeAttribute('$collectionId'); + $relation->removeAttribute('$databaseId'); + // Attribute $collection is required for Utopia. + $relation->setAttribute( + '$collection', + 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence() + ); + + if ($oldDocument->isEmpty()) { + if (isset($relation['$id']) && $relation['$id'] === 'unique()') { + $relation['$id'] = ID::unique(); + } + } + $setCollection($relatedCollection, $relation); + } + } + + if ($isList) { + $document->setAttribute($relationship->getAttribute('key'), \array_values($relations)); + } else { + $document->setAttribute($relationship->getAttribute('key'), \reset($relations)); + } + } + }); + + $setCollection($collection, $newDocument); + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); + + $upserted = []; + try { + $dbForProject->createOrUpdateDocuments( + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + [$newDocument], + onNext: function (Document $document) use (&$upserted) { + $upserted[] = $document; + }, + ); + } catch (ConflictException) { + throw new Exception($this->getConflictException()); + } catch (DuplicateException) { + throw new Exception($this->getDuplicateException()); + } catch (RelationshipException $e) { + throw new Exception(Exception::RELATIONSHIP_VALUE_INVALID, $e->getMessage()); + } catch (StructureException $e) { + throw new Exception($this->getInvalidStructureException(), $e->getMessage()); + } + + $document = $upserted[0]; + // Add $collectionId and $databaseId for all documents + $processDocument = function (Document $table, Document $document) use (&$processDocument, $dbForProject, $database) { + $document->setAttribute('$databaseId', $database->getId()); + $document->setAttribute('$collectionId', $table->getId()); + + $relationships = \array_filter( + $table->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + if (!\is_array($related)) { + $related = [$related]; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) + ); + + foreach ($related as $relation) { + if ($relation instanceof Document) { + $processDocument($relatedCollection, $relation); + } + } + } + }; + + $processDocument($collection, $document); + + $relationships = \array_map( + fn ($document) => $document->getAttribute('key'), + \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ) + ); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setContext('database', $database) + ->setParam('collectionId', $collection->getId()) + ->setParam('tableId', $collection->getId()) + ->setParam('documentId', $document->getId()) + ->setParam('rowId', $document->getId()) + ->setContext($this->getCollectionsEventsContext(), $collection) + ->setPayload($response->getPayload(), sensitive: $relationships); + + $response->dynamic( + $document, + $this->getResponseModel() + ); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php new file mode 100644 index 0000000000..b0be7350b7 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php @@ -0,0 +1,78 @@ +setContext(Context::DATABASE_ROWS); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') + ->desc('Upsert row') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].upsert') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'row.upsert') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}/row/{response.$id}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', [ + new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/upsert-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_CREATED, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + ), + ]) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('rowId', '', new UID(), 'Row ID.') + ->param('data', [], new JSON(), 'Row data as JSON object. Include all required columns of the row to be created or updated.', true) + ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->inject('requestTimestamp') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->callback($this->action(...)); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php index 7b629bca44..33d972e0f1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php @@ -31,6 +31,7 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Cre use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Delete as DeleteDocument; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Get as GetDocument; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Update as UpdateDocument; +use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Upsert as UpsertDocument; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\XList as ListDocuments; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Get as GetCollection; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Create as CreateIndex; @@ -78,6 +79,7 @@ class Collections extends Base $service->addAction(CreateDocument::getName(), new CreateDocument()); $service->addAction(GetDocument::getName(), new GetDocument()); $service->addAction(UpdateDocument::getName(), new UpdateDocument()); + $service->addAction(UpsertDocument::getName(), new UpsertDocument()); $service->addAction(DeleteDocument::getName(), new DeleteDocument()); $service->addAction(ListDocuments::getName(), new ListDocuments()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php index d881303c1e..0a8d8c0cfd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php @@ -38,6 +38,7 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Delete as Del use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Get as GetRow; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Logs\XList as ListRowLogs; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Update as UpdateRow; +use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Upsert as UpsertRow; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\XList as ListRows; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Update as UpdateTable; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Usage\Get as GetTableUsage; @@ -135,6 +136,7 @@ class Tables extends Base $service->addAction(CreateRow::getName(), new CreateRow()); $service->addAction(GetRow::getName(), new GetRow()); $service->addAction(UpdateRow::getName(), new UpdateRow()); + $service->addAction(UpsertRow::getName(), new UpsertRow()); $service->addAction(DeleteRow::getName(), new DeleteRow()); $service->addAction(ListRows::getName(), new ListRows()); $service->addAction(ListRowLogs::getName(), new ListRowLogs()); From db128d1fb4fed8d657f5a1313ce4b0697cc47ef0 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 14:39:47 +0530 Subject: [PATCH 145/343] update: better syntax for callbacks. --- .../Http/Databases/Collections/Attributes/Boolean/Create.php | 2 +- .../Http/Databases/Collections/Attributes/Boolean/Update.php | 2 +- .../Http/Databases/Collections/Attributes/Datetime/Create.php | 2 +- .../Http/Databases/Collections/Attributes/Datetime/Update.php | 2 +- .../Databases/Http/Databases/Collections/Attributes/Delete.php | 2 +- .../Http/Databases/Collections/Attributes/Email/Create.php | 2 +- .../Http/Databases/Collections/Attributes/Email/Update.php | 2 +- .../Http/Databases/Collections/Attributes/Enum/Create.php | 2 +- .../Http/Databases/Collections/Attributes/Enum/Update.php | 2 +- .../Http/Databases/Collections/Attributes/Float/Create.php | 2 +- .../Http/Databases/Collections/Attributes/Float/Update.php | 2 +- .../Databases/Http/Databases/Collections/Attributes/Get.php | 2 +- .../Http/Databases/Collections/Attributes/IP/Create.php | 2 +- .../Http/Databases/Collections/Attributes/IP/Update.php | 2 +- .../Http/Databases/Collections/Attributes/Integer/Create.php | 2 +- .../Http/Databases/Collections/Attributes/Integer/Update.php | 2 +- .../Databases/Collections/Attributes/Relationship/Create.php | 2 +- .../Databases/Collections/Attributes/Relationship/Update.php | 2 +- .../Http/Databases/Collections/Attributes/String/Create.php | 2 +- .../Http/Databases/Collections/Attributes/String/Update.php | 2 +- .../Http/Databases/Collections/Attributes/URL/Create.php | 2 +- .../Http/Databases/Collections/Attributes/URL/Update.php | 2 +- .../Databases/Http/Databases/Collections/Attributes/XList.php | 2 +- .../Modules/Databases/Http/Databases/Collections/Create.php | 2 +- .../Modules/Databases/Http/Databases/Collections/Delete.php | 2 +- .../Databases/Http/Databases/Collections/Documents/Create.php | 2 +- .../Databases/Http/Databases/Collections/Documents/Delete.php | 2 +- .../Databases/Http/Databases/Collections/Documents/Get.php | 2 +- .../Http/Databases/Collections/Documents/Logs/XList.php | 2 +- .../Databases/Http/Databases/Collections/Documents/Update.php | 2 +- .../Databases/Http/Databases/Collections/Documents/XList.php | 2 +- .../Modules/Databases/Http/Databases/Collections/Get.php | 2 +- .../Databases/Http/Databases/Collections/Indexes/Create.php | 2 +- .../Databases/Http/Databases/Collections/Indexes/Delete.php | 2 +- .../Databases/Http/Databases/Collections/Indexes/Get.php | 2 +- .../Databases/Http/Databases/Collections/Indexes/XList.php | 2 +- .../Modules/Databases/Http/Databases/Collections/Logs/XList.php | 2 +- .../Modules/Databases/Http/Databases/Collections/Update.php | 2 +- .../Modules/Databases/Http/Databases/Collections/Usage/Get.php | 2 +- .../Modules/Databases/Http/Databases/Collections/XList.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Create.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Delete.php | 2 +- src/Appwrite/Platform/Modules/Databases/Http/Databases/Get.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Logs/XList.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Boolean/Create.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Boolean/Update.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Datetime/Create.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Datetime/Update.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Columns/Delete.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Email/Create.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Email/Update.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Enum/Create.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Enum/Update.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Float/Create.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Float/Update.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Columns/Get.php | 2 +- .../Databases/Http/Databases/Tables/Columns/IP/Create.php | 2 +- .../Databases/Http/Databases/Tables/Columns/IP/Update.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Integer/Create.php | 2 +- .../Databases/Http/Databases/Tables/Columns/Integer/Update.php | 2 +- .../Http/Databases/Tables/Columns/Relationship/Create.php | 2 +- .../Http/Databases/Tables/Columns/Relationship/Update.php | 2 +- .../Databases/Http/Databases/Tables/Columns/String/Create.php | 2 +- .../Databases/Http/Databases/Tables/Columns/String/Update.php | 2 +- .../Databases/Http/Databases/Tables/Columns/URL/Create.php | 2 +- .../Databases/Http/Databases/Tables/Columns/URL/Update.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Columns/XList.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Tables/Create.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Tables/Delete.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Tables/Get.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Indexes/Create.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Indexes/Delete.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Indexes/Get.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Indexes/XList.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Logs/XList.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Rows/Create.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Rows/Delete.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Rows/Get.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Rows/Update.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Rows/XList.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Tables/Update.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Usage/Get.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Tables/XList.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Update.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Usage/Get.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Usage/XList.php | 2 +- .../Platform/Modules/Databases/Http/Databases/XList.php | 2 +- src/Appwrite/Platform/Modules/Databases/Workers/Databases.php | 2 +- 89 files changed, 89 insertions(+), 89 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php index 7eb6a109c0..b1fddc0371 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php @@ -66,7 +66,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php index 9930ebdd8a..7aa2360fb8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php @@ -66,7 +66,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php index e3e0cc359b..fd54fe0843 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php @@ -67,7 +67,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php index eac9ba278c..17818fec2d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php @@ -67,7 +67,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 242f6a4ea0..4582500091 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -66,7 +66,7 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php index 80309609b8..80f0270ea3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php @@ -67,7 +67,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php index 5c35084508..2f14d8a361 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php @@ -67,7 +67,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php index 8e4ad25f75..006de12e91 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php @@ -70,7 +70,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php index be04a1ef9a..c2f6d7696c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php @@ -69,7 +69,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php index 4e3a8adf75..35e9bb68a1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php @@ -71,7 +71,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php index 13a90310e1..2fdcf949f1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php @@ -69,7 +69,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index ba91af54a2..5ce63982b1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -66,7 +66,7 @@ class Get extends Action ->param('key', '', new Key(), 'Attribute Key.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php index 4bf5edc09d..c62e2add01 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php @@ -67,7 +67,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php index 380fa01123..a3e1ea5a61 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php @@ -67,7 +67,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php index dc28e41264..69272b6aea 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php @@ -71,7 +71,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php index 9e864e8b62..9c05382173 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php @@ -69,7 +69,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php index 0bbb3faa67..fa8d0ad750 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php @@ -80,7 +80,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $relatedCollectionId, string $type, bool $twoWay, ?string $key, ?string $twoWayKey, string $onDelete, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php index b489f92c3d..da2d0b9b08 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php @@ -68,7 +68,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php index 6463d2cedf..9b5201c1a8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php @@ -72,7 +72,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php index e746edb766..b3f4cf3f03 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php @@ -70,7 +70,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php index a802bbf8af..2d72533cf1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php @@ -67,7 +67,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php index 9ca1f372dc..e5c4288d92 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php @@ -67,7 +67,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 307cb98eff..b9f1450fa3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -60,7 +60,7 @@ class XList extends Action ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php index b5e7bf5415..84c18e9890 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -75,7 +75,7 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php index 67bddbc9ff..b8080ab471 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php @@ -62,7 +62,7 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index b55731a4f2..6a16644a2f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -117,7 +117,7 @@ class Create extends Action ->inject('user') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index 9944de4e36..dc307071e4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -75,7 +75,7 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $documentId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index da730246bf..3f7f74ee75 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -65,7 +65,7 @@ class Get extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php index 2856d9ddd0..4f4dad9882 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php @@ -71,7 +71,7 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index f69dfb3f98..3bc97e817b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -80,7 +80,7 @@ class Update extends Action ->inject('dbForProject') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 02e2900ac8..0012b8339a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -66,7 +66,7 @@ class XList extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php index 9ff9e3e442..0359025fc5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php @@ -55,7 +55,7 @@ class Get extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index e688088640..30753a9434 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -74,7 +74,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index 6fe3e3f42c..bb0b7bc4ca 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -68,7 +68,7 @@ class Delete extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php index 8d5513e1c0..e29bbf6647 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php @@ -57,7 +57,7 @@ class Get extends Action ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index caf6c72559..13717034ce 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -62,7 +62,7 @@ class XList extends Action ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php index 6e9f86260c..2f9ac2c8c0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php @@ -70,7 +70,7 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php index e1e8da7017..cc41d716d4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php @@ -68,7 +68,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php index 5d49be7723..0c565806cc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php @@ -61,7 +61,7 @@ class Get extends Action ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $range, string $collectionId, UtopiaResponse $response, Database $dbForProject): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index 15705e835e..06a6d2cd39 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -63,7 +63,7 @@ class XList extends Action ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php index 6e4dc5e136..3b9efa2fca 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php @@ -65,7 +65,7 @@ class Create extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $name, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php index 60df83bb77..b9b475f699 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php @@ -57,7 +57,7 @@ class Delete extends Action ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Get.php index 67b61bceb2..c2c6a57da1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Get.php @@ -49,7 +49,7 @@ class Get extends Action ->param('databaseId', '', new UID(), 'Database ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, UtopiaResponse $response, Database $dbForProject): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php index 56358aa723..a531110398 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php @@ -64,7 +64,7 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php index e1633da062..b8675877f3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php @@ -65,6 +65,6 @@ class Create extends BooleanCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php index deead5e1d7..09d01cae21 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php @@ -67,6 +67,6 @@ class Update extends BooleanUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php index 4710031c63..34ead7c33d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php @@ -67,6 +67,6 @@ class Create extends DatetimeCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php index f30e627553..5b026cd373 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php @@ -69,6 +69,6 @@ class Update extends DatetimeUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php index d2f0c54839..567cb02169 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php @@ -64,6 +64,6 @@ class Delete extends AttributesDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php index fc64c3b215..f5bb2f5220 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php @@ -66,6 +66,6 @@ class Create extends EmailCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php index c6425043b5..faba9279b5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php @@ -68,6 +68,6 @@ class Update extends EmailUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php index 338cec4f05..ec1d36a916 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php @@ -69,6 +69,6 @@ class Create extends EnumCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php index 6a35b955d2..ef2c829e0a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php @@ -71,6 +71,6 @@ class Update extends EnumUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php index 7e1a502f2e..32579017c6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php @@ -68,6 +68,6 @@ class Create extends FloatCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php index 05983a8153..4ed420cfa0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php @@ -70,6 +70,6 @@ class Update extends FloatUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php index a0d8a3ce76..ed28f96535 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php @@ -67,6 +67,6 @@ class Get extends AttributesGet ->param('key', '', new Key(), 'Column Key.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php index 1bae06a360..8acc47f051 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php @@ -66,6 +66,6 @@ class Create extends IPCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php index 8174ad7860..c43f132c13 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php @@ -68,6 +68,6 @@ class Update extends IPUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php index 2c6b7a84e7..7694e9d74f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php @@ -68,6 +68,6 @@ class Create extends IntegerCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php index 8375853e83..b3ce988830 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php @@ -70,6 +70,6 @@ class Update extends IntegerUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php index 6d3f26902d..133f772605 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php @@ -78,6 +78,6 @@ class Create extends RelationshipCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php index 8bed5013a9..ef1d8c7a33 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php @@ -70,6 +70,6 @@ class Update extends RelationshipUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php index 529f4f270d..e1914bed65 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php @@ -70,6 +70,6 @@ class Create extends StringCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php index 7450af9eff..f7ec773e3c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php @@ -71,6 +71,6 @@ class Update extends StringUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php index 07295b2d93..0e6fe7cff3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php @@ -66,6 +66,6 @@ class Create extends URLCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php index 990fbee742..6f3698c0cf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php @@ -68,6 +68,6 @@ class Update extends URLUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php index 41b1aee5c9..c6ceb35f48 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php @@ -56,6 +56,6 @@ class XList extends AttributesXList ->param('queries', [], new Columns(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Columns::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php index 95ef8bea4a..c20865d110 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php @@ -68,6 +68,6 @@ class Create extends CollectionCreate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php index bb9b859a78..85e52ac37d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php @@ -61,6 +61,6 @@ class Delete extends CollectionDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php index cdf7950a1c..473dfb6273 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php @@ -56,6 +56,6 @@ class Get extends CollectionGet ->param('tableId', '', new UID(), 'Table ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php index 33692b7a0c..3605afd985 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php @@ -69,6 +69,6 @@ class Create extends IndexCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php index 80581f7a6f..7cda1ce471 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php @@ -67,6 +67,6 @@ class Delete extends IndexDelete ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php index d78761459a..3bee87de4a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php @@ -58,6 +58,6 @@ class Get extends IndexGet ->param('key', null, new Key(), 'Index Key.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php index b16e328f27..1af13dc82e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php @@ -58,6 +58,6 @@ class XList extends IndexXList ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php index 99fbe99a34..244cebe3ad 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php @@ -56,6 +56,6 @@ class XList extends CollectionLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php index 5eb36598b2..81d90a7708 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php @@ -108,6 +108,6 @@ class Create extends DocumentCreate ->inject('user') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php index 799f3cde05..5edf4e0b73 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php @@ -72,6 +72,6 @@ class Delete extends DocumentDelete ->inject('dbForProject') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php index 8a8f9f3062..74e1f90497 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php @@ -61,6 +61,6 @@ class Get extends DocumentGet ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php index 62466eac13..1cc5202152 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php @@ -57,6 +57,6 @@ class XList extends DocumentLogXList ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php index 798bfddf51..dfe77c9075 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php @@ -71,6 +71,6 @@ class Update extends DocumentUpdate ->inject('dbForProject') ->inject('queueForEvents') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php index 1175515e5c..9d03603a0e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php @@ -60,6 +60,6 @@ class XList extends DocumentXList ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php index 14798f8513..ab71634fb2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php @@ -67,6 +67,6 @@ class Update extends CollectionUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php index 1baebb23f2..9fb5fc8c17 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php @@ -58,6 +58,6 @@ class Get extends CollectionUsageGet ->param('tableId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php index 1086f8f80e..f6f48ace40 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php @@ -59,6 +59,6 @@ class XList extends CollectionXList ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Update.php index 49c92a65a2..a0e440c657 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Update.php @@ -58,7 +58,7 @@ class Update extends Action ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $name, bool $enabled, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php index fab12a9735..1a85380767 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -55,7 +55,7 @@ class Get extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $databaseId, string $range, UtopiaResponse $response, Database $dbForProject): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php index 48533935b3..2d551465db 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -52,7 +52,7 @@ class XList extends Action ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(string $range, UtopiaResponse $response, Database $dbForProject): void diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php index 8bb9184baa..dcf7e2d724 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php @@ -56,7 +56,7 @@ class XList extends Action ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->callback([$this, 'action']); + ->callback($this->action(...)); } public function action(array $queries, string $search, UtopiaResponse $response, Database $dbForProject): void diff --git a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php index 0cbddd2a52..2576765445 100644 --- a/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php +++ b/src/Appwrite/Platform/Modules/Databases/Workers/Databases.php @@ -38,7 +38,7 @@ class Databases extends Action ->inject('dbForProject') ->inject('queueForRealtime') ->inject('log') - ->callback([$this, 'action']); + ->callback($this->action(...)); } /** From 9334b98308b16918b7e70145c68225c4bcc8c8dd Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 14:40:33 +0530 Subject: [PATCH 146/343] fix: duplicate call to collection creation. --- .../Modules/Databases/Http/Databases/Collections/Create.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php index 84c18e9890..5edce7715f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -102,8 +102,6 @@ class Create extends Action 'name' => $name, 'search' => \implode(' ', [$collectionId, $name]), ])); - - $dbForProject->createCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), permissions: $permissions, documentSecurity: $documentSecurity); } catch (DuplicateException) { throw new Exception($this->getDuplicateException()); } catch (LimitException) { From d6b55730eb8b377b4f19a5b5c58ec4ef80467f9e Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 15:10:28 +0530 Subject: [PATCH 147/343] fix: string encryption attribute in model. --- .../Collections/Attributes/String/Create.php | 17 ++++++++++++++++- .../Databases/Tables/Columns/String/Create.php | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php index 9b5201c1a8..cc989f6687 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php @@ -72,6 +72,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('plan') ->callback($this->action(...)); } @@ -87,8 +88,20 @@ class Create extends Action UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, - Event $queueForEvents + Event $queueForEvents, + array $plan ): void { + if ($encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string ' . $this->getSdkGroup() . ' are not available on your plan. Please upgrade to create encrypted string ' . $this->getSdkGroup() . '.'); + } + + if ($encrypt && $size < APP_DATABASE_ENCRYPT_SIZE_MIN) { + throw new Exception( + Exception::GENERAL_BAD_REQUEST, + "Size too small. Encrypted strings require a minimum size of " . APP_DATABASE_ENCRYPT_SIZE_MIN . " characters." + ); + } + // Ensure default fits in the given size $validator = new Text($size, 0); if (!is_null($default) && !$validator->isValid($default)) { @@ -118,6 +131,8 @@ class Create extends Action $queueForEvents ); + $attribute->setAttribute('encrypt', $encrypt); + $response ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) ->dynamic($attribute, $this->getResponseModel()); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php index e1914bed65..ed7989fbc3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php @@ -70,6 +70,7 @@ class Create extends StringCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('plan') ->callback($this->action(...)); } } From d502869c3d06f62be02da1384ba1c612fff8ec53 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 15:21:06 +0530 Subject: [PATCH 148/343] fix: index lengths. --- .../Http/Databases/Collections/Indexes/Create.php | 11 ++++++----- .../Http/Databases/Tables/Indexes/Create.php | 3 +++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index 30753a9434..1665549c92 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -22,6 +22,8 @@ use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; +use Utopia\Validator\Integer; +use Utopia\Validator\Nullable; use Utopia\Validator\WhiteList; class Create extends Action @@ -70,6 +72,7 @@ class Create extends Action ->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE]), 'Index type.') ->param('attributes', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' attributes are allowed, each 32 characters long.') ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true) + ->param('lengths', [], new ArrayList(new Nullable(new Integer()), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Length of index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE, optional: true) ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') @@ -77,7 +80,7 @@ class Create extends Action ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void + public function action(string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): void { $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -103,7 +106,7 @@ class Create extends Action throw new Exception($this->getLimitException(), 'Index limit exceeded'); } - // Convert Document[] to array of attribute metadata + // Convert Document array to array of attribute metadata $oldAttributes = \array_map(fn ($a) => $a->getArrayCopy(), $collection->getAttribute('attributes')); $oldAttributes[] = [ @@ -138,9 +141,6 @@ class Create extends Action 'size' => 0 ]; - // lengths hidden by default - $lengths = []; - $contextType = $this->getParentContext(); foreach ($attributes as $i => $attribute) { // find attribute metadata in collection document @@ -191,6 +191,7 @@ class Create extends Action $dbForProject->getAdapter()->getMaxIndexLength(), $dbForProject->getAdapter()->getInternalIndexesKeys(), ); + if (!$validator->isValid($index)) { throw new Exception($this->getInvalidTypeException(), $validator->getDescription()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php index 3605afd985..e57e962e87 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php @@ -15,6 +15,8 @@ use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; +use Utopia\Validator\Integer; +use Utopia\Validator\Nullable; use Utopia\Validator\WhiteList; class Create extends IndexCreate @@ -65,6 +67,7 @@ class Create extends IndexCreate ->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE]), 'Index type.') ->param('columns', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of columns to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' columns are allowed, each 32 characters long.') ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true) + ->param('lengths', [], new ArrayList(new Nullable(new Integer()), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Length of index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE, optional: true) ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') From b1f7f08b9a17216efde50ce028d7bf7dfdc7ec67 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 16:06:15 +0530 Subject: [PATCH 149/343] remove: duplicate events. --- .../Http/Databases/Collections/Documents/Create.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index 6a16644a2f..33406044f1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -367,12 +367,6 @@ class Create extends Action throw new Exception($this->getInvalidStructureException(), $e->getMessage()); } - $queueForEvents - ->setParam('databaseId', $databaseId) - ->setParam('collectionId', $collection->getId()) - ->setContext('collection', $collection) - ->setContext('database', $database); - $queueForEvents ->setParam('databaseId', $databaseId) ->setContext('database', $database) From ffec769f4ada9b6019e55385aea1871646802575 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 16:16:55 +0530 Subject: [PATCH 150/343] fix: index lengths. --- .../Databases/Http/Databases/Collections/Indexes/Create.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index 1665549c92..9dbd7924c6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -164,7 +164,7 @@ class Create extends Action throw new Exception($this->getParentNotAvailableException(), "$contextType not available: " . $oldAttributes[$attributeIndex]['key']); } - $lengths[$i] = null; + $lengths[$i] ??= null; if ($attributeArray === true) { $lengths[$i] = Database::ARRAY_INDEX_LENGTH; From ad34cf3a624f2d8a7ef302aa6ae86c33028e222c Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 16:17:27 +0530 Subject: [PATCH 151/343] add: lengths to column indexes. --- src/Appwrite/Utopia/Response/Model/ColumnIndex.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Appwrite/Utopia/Response/Model/ColumnIndex.php b/src/Appwrite/Utopia/Response/Model/ColumnIndex.php index 8c632266ef..bebc640fb2 100644 --- a/src/Appwrite/Utopia/Response/Model/ColumnIndex.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnIndex.php @@ -42,6 +42,13 @@ class ColumnIndex extends Model 'example' => [], 'array' => true, ]) + ->addRule('lengths', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Index columns length.', + 'default' => [], + 'example' => [], + 'array' => true, + ]) ->addRule('orders', [ 'type' => self::TYPE_STRING, 'description' => 'Index orders.', From 44b8054ed7e831d70415c2e76695e9781b1a3605 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 16:55:15 +0530 Subject: [PATCH 152/343] add: upsert documents/rows. --- .../Collections/Documents/Bulk/Upsert.php | 141 ++++++++++++++++++ .../Databases/Tables/Rows/Bulk/Upsert.php | 74 +++++++++ .../Services/Registry/Collections.php | 2 + .../Databases/Services/Registry/Tables.php | 2 + 4 files changed, 219 insertions(+) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php new file mode 100644 index 0000000000..1e7d838fba --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php @@ -0,0 +1,141 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents') + ->desc('Create or update documents') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].create') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'document.create') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', [ + new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/upsert-documents.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_CREATED, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON, + ) + ]) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('documents', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of document data as JSON objects. May contain partial documents.', false, ['plan']) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForStatsUsage') + ->inject('plan') + ->callback($this->action(...)); + } + + public function action(string $databaseId, string $collectionId, array $documents, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, array $plan): void + { + $database = $dbForProject->getDocument('databases', $databaseId); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + if ($collection->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + $hasRelationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + if ($hasRelationships) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk upsert is not supported for ' . $this->getSdkNamespace() . ' with relationship attributes'); + } + + foreach ($documents as $key => $document) { + $documents[$key] = new Document($document); + } + + $upserted = []; + + try { + $modified = $dbForProject->createOrUpdateDocuments( + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + $documents, + onNext: function (Document $document) use ($plan, &$upserted) { + if (\count($upserted) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) { + $upserted[] = $document; + } + }, + ); + } catch (ConflictException) { + throw new Exception($this->getConflictException()); + } catch (DuplicateException) { + throw new Exception($this->getDuplicateException()); + } catch (RelationshipException $e) { + throw new Exception(Exception::RELATIONSHIP_VALUE_INVALID, $e->getMessage()); + } catch (StructureException $e) { + throw new Exception($this->getInvalidStructureException(), $e->getMessage()); + } + + foreach ($upserted as $document) { + $document->setAttribute('$databaseId', $database->getId()); + $document->setAttribute('$collectionId', $collection->getId()); + } + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified)) + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); + + $response->dynamic(new Document([ + 'total' => $modified, + $this->getSdkGroup() => $upserted + ]), $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php new file mode 100644 index 0000000000..4a5b2a0fac --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php @@ -0,0 +1,74 @@ +setContext(Context::DATABASE_ROWS); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') + ->desc('Create or update rows') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].create') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'document.create') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', [ + new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/upsert-documents.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_CREATED, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON, + ) + ]) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('rows', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of row data as JSON objects. May contain partial rows.', false, ['plan']) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForStatsUsage') + ->inject('plan') + ->callback($this->action(...)); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php index 33d972e0f1..ca6796c3e9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php @@ -27,6 +27,7 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\UR use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\XList as ListAttributes; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Create as CreateCollection; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Delete as DeleteCollection; +use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Upsert as UpsertDocuments; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Create as CreateDocument; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Delete as DeleteDocument; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Get as GetDocument; @@ -80,6 +81,7 @@ class Collections extends Base $service->addAction(GetDocument::getName(), new GetDocument()); $service->addAction(UpdateDocument::getName(), new UpdateDocument()); $service->addAction(UpsertDocument::getName(), new UpsertDocument()); + $service->addAction(UpsertDocuments::getName(), new UpsertDocuments()); $service->addAction(DeleteDocument::getName(), new DeleteDocument()); $service->addAction(ListDocuments::getName(), new ListDocuments()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php index 0a8d8c0cfd..2bd596bb1a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php @@ -33,6 +33,7 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes\Delete as use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes\Get as GetColumnIndex; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes\XList as ListColumnIndexes; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Logs\XList as ListTableLogs; +use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Bulk\Upsert as UpsertRows; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Create as CreateRow; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Delete as DeleteRow; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Get as GetRow; @@ -137,6 +138,7 @@ class Tables extends Base $service->addAction(GetRow::getName(), new GetRow()); $service->addAction(UpdateRow::getName(), new UpdateRow()); $service->addAction(UpsertRow::getName(), new UpsertRow()); + $service->addAction(UpsertRows::getName(), new UpsertRows()); $service->addAction(DeleteRow::getName(), new DeleteRow()); $service->addAction(ListRows::getName(), new ListRows()); $service->addAction(ListRowLogs::getName(), new ListRowLogs()); From a6ae715e3a6b748ee794f3765259ff337e447a20 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 16:55:31 +0530 Subject: [PATCH 153/343] update: descriptions. --- .../Databases/Http/Databases/Collections/Documents/Upsert.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Rows/Upsert.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php index efd950e846..ebe30f6970 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php @@ -47,7 +47,7 @@ class Upsert extends Action $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') - ->desc('Upsert document') + ->desc('Create or update a document') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].upsert') ->label('scope', 'documents.write') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php index b0be7350b7..800efa9cde 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php @@ -37,7 +37,7 @@ class Upsert extends DocumentUpsert $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') - ->desc('Upsert row') + ->desc('Create or update a row') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].upsert') ->label('scope', 'documents.write') From 919f358f3fd5ded0363f8a34fe9b6bdd5a5c109b Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 16:58:18 +0530 Subject: [PATCH 154/343] fix: audit event. --- .../Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php index 4a5b2a0fac..9331e75aa8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php @@ -41,7 +41,7 @@ class Upsert extends DocumentsUpsert ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].create') ->label('scope', 'documents.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'document.create') + ->label('audits.event', 'row.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) From 1c87e765de8c563d7c6da1ecd739b1d75d3a76fc Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 17:12:43 +0530 Subject: [PATCH 155/343] add: delete documents/rows --- .../Collections/Documents/Bulk/Delete.php | 136 ++++++++++++++++++ .../Databases/Tables/Rows/Bulk/Delete.php | 71 +++++++++ .../Services/Registry/Collections.php | 2 + .../Databases/Services/Registry/Tables.php | 2 + 4 files changed, 211 insertions(+) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php new file mode 100644 index 0000000000..bee3b35599 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php @@ -0,0 +1,136 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents') + ->desc('Delete documents') + ->groups(['api', 'database']) + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'documents.delete') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/delete-documents.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForStatsUsage') + ->inject('plan') + ->callback($this->action(...)); + } + + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, array $plan): void + { + $database = $dbForProject->getDocument('databases', $databaseId); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + if ($collection->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + $hasRelationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + if ($hasRelationships) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk delete is not supported for ' . $this->getSdkNamespace() . ' with relationship attributes'); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + $documents = []; + + try { + $modified = $dbForProject->deleteDocuments( + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + $queries, + onNext: function (Document $document) use ($plan, &$documents) { + if (\count($documents) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) { + $documents[] = $document; + } + }, + ); + } catch (ConflictException) { + throw new Exception($this->getConflictException()); + } catch (RestrictedException) { + throw new Exception($this->getRestrictedException()); + } + + foreach ($documents as $document) { + $document->setAttribute('$databaseId', $database->getId()); + $document->setAttribute('$collectionId', $collection->getId()); + } + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified)) + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); + + $response->dynamic(new Document([ + 'total' => $modified, + $this->getSdkGroup() => $documents, + ]), $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php new file mode 100644 index 0000000000..73f3016936 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php @@ -0,0 +1,71 @@ +setContext(Context::DATABASE_ROWS); + + $this + ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/databases/:databaseId/tables/:collectionId/rows') + ->desc('Delete rows') + ->groups(['api', 'database']) + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'rows.delete') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/delete-documents.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForStatsUsage') + ->inject('plan') + ->callback($this->action(...)); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php index ca6796c3e9..65953c7992 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php @@ -27,6 +27,7 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\UR use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\XList as ListAttributes; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Create as CreateCollection; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Delete as DeleteCollection; +use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Delete as DeleteDocuments; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Upsert as UpsertDocuments; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Create as CreateDocument; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Delete as DeleteDocument; @@ -83,6 +84,7 @@ class Collections extends Base $service->addAction(UpsertDocument::getName(), new UpsertDocument()); $service->addAction(UpsertDocuments::getName(), new UpsertDocuments()); $service->addAction(DeleteDocument::getName(), new DeleteDocument()); + $service->addAction(DeleteDocuments::getName(), new DeleteDocuments()); $service->addAction(ListDocuments::getName(), new ListDocuments()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php index 2bd596bb1a..87bf51512e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php @@ -33,6 +33,7 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes\Delete as use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes\Get as GetColumnIndex; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes\XList as ListColumnIndexes; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Logs\XList as ListTableLogs; +use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Bulk\Delete as DeleteRows; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Bulk\Upsert as UpsertRows; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Create as CreateRow; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Delete as DeleteRow; @@ -140,6 +141,7 @@ class Tables extends Base $service->addAction(UpsertRow::getName(), new UpsertRow()); $service->addAction(UpsertRows::getName(), new UpsertRows()); $service->addAction(DeleteRow::getName(), new DeleteRow()); + $service->addAction(DeleteRows::getName(), new DeleteRows()); $service->addAction(ListRows::getName(), new ListRows()); $service->addAction(ListRowLogs::getName(), new ListRowLogs()); } From 2994cdf874b3975a678b7db9e893cdd446e5b89b Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 17:14:50 +0530 Subject: [PATCH 156/343] update: model. --- src/Appwrite/Utopia/Response/Model/Row.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Utopia/Response/Model/Row.php b/src/Appwrite/Utopia/Response/Model/Row.php index c30984ab7a..b7750feccd 100644 --- a/src/Appwrite/Utopia/Response/Model/Row.php +++ b/src/Appwrite/Utopia/Response/Model/Row.php @@ -36,6 +36,12 @@ class Row extends Any 'default' => '', 'example' => '5e5ea5c16897e', ]) + ->addRule('$sequence', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Row automatically incrementing ID.', + 'default' => 0, + 'example' => 1, + ]) ->addRule('$tableId', [ 'type' => self::TYPE_STRING, 'description' => 'Table ID.', @@ -71,7 +77,6 @@ class Row extends Any public function filter(DatabaseDocument $document): DatabaseDocument { - $document->removeAttribute('$internalId'); $document->removeAttribute('$collection'); $document->removeAttribute('$tenant'); From 710b8bda565c411ecb23e8b670d0ba7f45d2b3f3 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Thu, 12 Jun 2025 17:27:21 +0530 Subject: [PATCH 157/343] Use _APP_CONSOLE_DOMAIN, if not found, then use _APP_DOMAIN --- app/config/templates/site.php | 2 +- app/controllers/api/console.php | 4 ++-- app/controllers/general.php | 10 +++++----- app/views/general/error.phtml | 2 +- .../Modules/Functions/Http/Executions/Create.php | 2 +- .../Platform/Modules/Functions/Workers/Builds.php | 4 ++-- .../Platform/Modules/Proxy/Http/Rules/API/Create.php | 2 +- .../Modules/Proxy/Http/Rules/Function/Create.php | 2 +- .../Modules/Proxy/Http/Rules/Redirect/Create.php | 2 +- .../Platform/Modules/Proxy/Http/Rules/Site/Create.php | 2 +- src/Appwrite/Platform/Workers/Functions.php | 2 +- src/Appwrite/Vcs/Comment.php | 4 ++-- src/Executor/Executor.php | 2 +- .../e2e/Services/Projects/ProjectsCustomServerTest.php | 2 +- 14 files changed, 21 insertions(+), 21 deletions(-) diff --git a/app/config/templates/site.php b/app/config/templates/site.php index a853955a97..725e6fa918 100644 --- a/app/config/templates/site.php +++ b/app/config/templates/site.php @@ -7,7 +7,7 @@ use Utopia\System\System; */ $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; -$hostname = System::getEnv('_APP_DOMAIN'); +$hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); // TODO: Development override if (System::getEnv('_APP_ENV') === 'development') { diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index 558dc0e4ef..d78924028c 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -43,8 +43,8 @@ App::get('/v1/console/variables') )) ->inject('response') ->action(function (Response $response) { - $validator = new Domain(System::getEnv('_APP_DOMAIN')); - $isDomainValid = !empty(System::getEnv('_APP_DOMAIN', '')) && $validator->isKnown() && !$validator->isTest(); + $validator = new Domain(System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', ''))); + $isDomainValid = !empty(System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', ''))) && $validator->isKnown() && !$validator->isTest(); $validator = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME')); $isCNAMEValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')) && $validator->isKnown() && !$validator->isTest(); diff --git a/app/controllers/general.php b/app/controllers/general.php index 5beac9e1e8..632c735133 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -76,7 +76,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $errorView = __DIR__ . '/../views/general/error.phtml'; - $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . '://' . System::getEnv('_APP_DOMAIN', ''); + $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . '://' . System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); if ($rule->isEmpty()) { $appDomainFunctionsFallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''); @@ -262,7 +262,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } if (!$authorized) { - $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . "://" . System::getEnv('_APP_DOMAIN'); + $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . "://" . System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $response ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') ->addHeader('Pragma', 'no-cache') @@ -448,7 +448,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_DOMAIN'); + $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $endpoint = $protocol . '://' . $hostname . "/v1"; // Appwrite vars @@ -809,7 +809,7 @@ App::init() * Appwrite Router */ $host = $request->getHostname() ?? ''; - $mainDomain = System::getEnv('_APP_DOMAIN', ''); + $mainDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); // Only run Router when external domain if ($host !== $mainDomain || !empty($previewHostname)) { if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { @@ -858,7 +858,7 @@ App::init() } else { Authorization::disable(); - $envDomain = System::getEnv('_APP_DOMAIN', ''); + $envDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $mainDomain = null; if (!empty($envDomain) && $envDomain !== 'localhost') { $mainDomain = $envDomain; diff --git a/app/views/general/error.phtml b/app/views/general/error.phtml index a427f1d5e8..de859a9c86 100644 --- a/app/views/general/error.phtml +++ b/app/views/general/error.phtml @@ -15,7 +15,7 @@ $labelClass = ''; $buttons = []; $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; -$hostname = System::getEnv('_APP_DOMAIN'); +$hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); // TODO: remove this later if (System::getEnv('_APP_ENV') === 'development') { $hostname = 'localhost'; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index fd1b2076a8..7838826136 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -351,7 +351,7 @@ class Create extends Base } $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_DOMAIN'); + $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $endpoint = $protocol . '://' . $hostname . "/v1"; // Appwrite vars diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 399a4d5c44..263d67f000 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -594,7 +594,7 @@ class Builds extends Action ]); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_DOMAIN'); + $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $endpoint = $protocol . '://' . $hostname . "/v1"; // Appwrite vars @@ -1441,7 +1441,7 @@ class Builds extends Action $name = "{$resourceName} ({$projectName})"; $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_DOMAIN'); + $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $projectId = $project->getId(); $resourceId = $resource->getId(); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php index e4d0d2899f..a4d4980384 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php @@ -76,7 +76,7 @@ class Create extends Action APP_HOSTNAME_INTERNAL ]; - $mainDomain = System::getEnv('_APP_DOMAIN', ''); + $mainDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $deniedDomains[] = $mainDomain; $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php index 6c5a87a68d..66465a0a97 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php @@ -81,7 +81,7 @@ class Create extends Action APP_HOSTNAME_INTERNAL ]; - $mainDomain = System::getEnv('_APP_DOMAIN', ''); + $mainDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $deniedDomains[] = $mainDomain; $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php index 3396a9c6fd..66a186993c 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php @@ -84,7 +84,7 @@ class Create extends Action APP_HOSTNAME_INTERNAL ]; - $mainDomain = System::getEnv('_APP_DOMAIN', ''); + $mainDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $deniedDomains[] = $mainDomain; $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php index 894c954a32..b466b1774b 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php @@ -81,7 +81,7 @@ class Create extends Action APP_HOSTNAME_INTERNAL ]; - $mainDomain = System::getEnv('_APP_DOMAIN', ''); + $mainDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $deniedDomains[] = $mainDomain; $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index c8c68a58ba..cf815198fa 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -484,7 +484,7 @@ class Functions extends Action } $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_DOMAIN'); + $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $endpoint = $protocol . '://' . $hostname . "/v1"; // Appwrite vars diff --git a/src/Appwrite/Vcs/Comment.php b/src/Appwrite/Vcs/Comment.php index 5f528e660f..5b303efe44 100644 --- a/src/Appwrite/Vcs/Comment.php +++ b/src/Appwrite/Vcs/Comment.php @@ -87,7 +87,7 @@ class Comment $i = 0; foreach ($projects as $projectId => $project) { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN')); + $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $text .= "## {$project['name']}\n\n"; $text .= "Project ID: `{$projectId}`\n\n"; @@ -201,7 +201,7 @@ class Comment public function generatImage(string $pathLight, string $pathDark, string $alt, int $width): string { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN')); + $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $imageLight = $protocol . '://' . $hostname . $pathLight; $imageDark = $protocol . '://' . $hostname . $pathDark; diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index 5b204c1910..955f3851fa 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -200,7 +200,7 @@ class Executor int $requestTimeout = null ) { if (empty($headers['host'])) { - $headers['host'] = System::getEnv('_APP_DOMAIN', ''); + $headers['host'] = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); } $runtimeId = "$projectId-$deploymentId"; diff --git a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php index a01073f3a3..9146d0636f 100644 --- a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php +++ b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php @@ -83,7 +83,7 @@ class ProjectsCustomServerTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - $mainDomain = System::getEnv('_APP_DOMAIN', ''); + $mainDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); From 3426847b177b080f44375b4ce5f85ed1622de181 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 17:31:37 +0530 Subject: [PATCH 158/343] add: update documents/rows. --- .../Collections/Documents/Bulk/Update.php | 158 ++++++++++++++++++ .../Databases/Tables/Rows/Bulk/Update.php | 70 ++++++++ .../Services/Registry/Collections.php | 2 + .../Databases/Services/Registry/Tables.php | 2 + 4 files changed, 232 insertions(+) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Update.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Update.php new file mode 100644 index 0000000000..23c8d5d58e --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Update.php @@ -0,0 +1,158 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents') + ->desc('Update documents') + ->groups(['api', 'database']) + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'documents.update') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-documents.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.', true) + ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForStatsUsage') + ->inject('plan') + ->callback($this->action(...)); + } + + public function action(string $databaseId, string $collectionId, string|array $data, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, array $plan): void + { + $data = \is_string($data) + ? \json_decode($data, true) + : $data; + + if (empty($data)) { + throw new Exception($this->getMissingPayloadException()); + } + + $database = $dbForProject->getDocument('databases', $databaseId); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + if ($collection->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + $hasRelationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + if ($hasRelationships) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk update is not supported for ' . $this->getSdkNamespace() . ' with relationship attributes'); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + if ($data['$permissions']) { + $validator = new Permissions(); + if (!$validator->isValid($data['$permissions'])) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, $validator->getDescription()); + } + } + + $documents = []; + + try { + $modified = $dbForProject->updateDocuments( + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + new Document($data), + $queries, + onNext: function (Document $document) use ($plan, &$documents) { + if (\count($documents) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) { + $documents[] = $document; + } + }, + ); + } catch (ConflictException) { + throw new Exception($this->getConflictException()); + } catch (RelationshipException $e) { + throw new Exception(Exception::RELATIONSHIP_VALUE_INVALID, $e->getMessage()); + } catch (StructureException $e) { + throw new Exception($this->getInvalidStructureException(), $e->getMessage()); + } + + foreach ($documents as $document) { + $document->setAttribute('$databaseId', $database->getId()); + $document->setAttribute('$collectionId', $collection->getId()); + } + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified)) + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); + + $response->dynamic(new Document([ + 'total' => $modified, + $this->getSdkGroup() => $documents + ]), $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php new file mode 100644 index 0000000000..95a0819dfd --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php @@ -0,0 +1,70 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') + ->desc('Update rows') + ->groups(['api', 'database']) + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'rows.update') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/update-documents.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('data', [], new JSON(), 'Row data as JSON object. Include only column and value pairs to be updated.', true) + ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForStatsUsage') + ->inject('plan') + ->callback($this->action(...)); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php index 65953c7992..415eaeaf85 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php @@ -28,6 +28,7 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\XL use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Create as CreateCollection; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Delete as DeleteCollection; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Delete as DeleteDocuments; +use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Update as UpdateDocuments; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Upsert as UpsertDocuments; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Create as CreateDocument; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Delete as DeleteDocument; @@ -81,6 +82,7 @@ class Collections extends Base $service->addAction(CreateDocument::getName(), new CreateDocument()); $service->addAction(GetDocument::getName(), new GetDocument()); $service->addAction(UpdateDocument::getName(), new UpdateDocument()); + $service->addAction(UpdateDocuments::getName(), new UpdateDocuments()); $service->addAction(UpsertDocument::getName(), new UpsertDocument()); $service->addAction(UpsertDocuments::getName(), new UpsertDocuments()); $service->addAction(DeleteDocument::getName(), new DeleteDocument()); diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php index 87bf51512e..87e5f80e3f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php @@ -34,6 +34,7 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes\Get as Get use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes\XList as ListColumnIndexes; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Logs\XList as ListTableLogs; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Bulk\Delete as DeleteRows; +use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Bulk\Update as UpdateRows; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Bulk\Upsert as UpsertRows; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Create as CreateRow; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Delete as DeleteRow; @@ -138,6 +139,7 @@ class Tables extends Base $service->addAction(CreateRow::getName(), new CreateRow()); $service->addAction(GetRow::getName(), new GetRow()); $service->addAction(UpdateRow::getName(), new UpdateRow()); + $service->addAction(UpdateRows::getName(), new UpdateRows()); $service->addAction(UpsertRow::getName(), new UpsertRow()); $service->addAction(UpsertRows::getName(), new UpsertRows()); $service->addAction(DeleteRow::getName(), new DeleteRow()); From 90d18a9bd5949760c12aed6bfe687778b81cea9e Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 18:24:54 +0530 Subject: [PATCH 159/343] add: increment, decrement document/row attribute/column; fixes: misc. --- .../Databases/Collections/Attributes/Get.php | 12 +- .../Collections/Documents/Action.php | 20 +++ .../Documents/Attribute/Decrement.php | 125 +++++++++++++++++ .../Documents/Attribute/Increment.php | 126 ++++++++++++++++++ .../Databases/Tables/Rows/Bulk/Delete.php | 2 +- .../Tables/Rows/Column/Decrement.php | 72 ++++++++++ .../Tables/Rows/Column/Increment.php | 72 ++++++++++ .../Services/Registry/Collections.php | 5 + .../Databases/Services/Registry/Tables.php | 4 + .../Utopia/Response/Model/ColumnString.php | 7 + 10 files changed, 440 insertions(+), 5 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index 5ce63982b1..d49639e049 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -86,14 +86,18 @@ class Get extends Action throw new Exception($this->getNotFoundException()); } - foreach ($attribute->getAttribute('options', []) as $optKey => $optVal) { - $attribute->setAttribute($optKey, $optVal); - } - $type = $attribute->getAttribute('type'); $format = $attribute->getAttribute('format'); + $options = $attribute->getAttribute('options', []); + $filters = $attribute->getAttribute('filters', []); + foreach ($options as $key => $option) { + $attribute->setAttribute($key, $option); + } + $model = $this->getCorrectModel($type, $format); + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + $response->dynamic($attribute, $model); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index 341302f779..c0e71d3730 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -96,6 +96,16 @@ abstract class Action extends UtopiaAction : Exception::TABLE_NOT_FOUND; } + /** + * Get the appropriate attribute/column not found exception. + */ + final protected function getStructureNotFoundException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_NOT_FOUND + : Exception::COLUMN_NOT_FOUND; + } + /** * Get the appropriate not found exception. */ @@ -156,6 +166,16 @@ abstract class Action extends UtopiaAction : Exception::ROW_MISSING_DATA; } + /** + * Get the exception to throw when the resource limit is exceeded. + */ + final protected function getLimitException(): string + { + return $this->isCollectionsAPI() + ? Exception::ATTRIBUTE_LIMIT_EXCEEDED + : Exception::COLUMN_LIMIT_EXCEEDED; + } + /** * Get the appropriate missing payload exception. */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php new file mode 100644 index 0000000000..9a8da5858c --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php @@ -0,0 +1,125 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId/:attribute/decrement') + ->desc('Decrement document attribute') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].decrement') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'documents.decrement') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/decrement-document-attribute.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('documentId', '', new UID(), 'Document ID.') + ->param('attribute', '', new Key(), 'Attribute key.') + ->param('value', 1, new Numeric(), 'Value to increment the attribute by. The value must be a number.', true) + ->param('min', null, new Numeric(), 'Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->callback($this->action(...)); + } + + public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + if ($collection->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + try { + $document = $dbForProject->decreaseDocumentAttribute( + collection: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + id: $documentId, + attribute: $attribute, + value: $value, + min: $min + ); + } catch (ConflictException) { + throw new Exception($this->getConflictException()); + } catch (NotFoundException) { + throw new Exception($this->getStructureNotFoundException()); + } catch (LimitException) { + throw new Exception($this->getLimitException(), $this->getSdkNamespace() . ' "' . $attribute . '" has reached the minimum value of ' . $min); + } catch (TypeException) { + throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, $this->getSdkNamespace() . ' "' . $attribute . '" is not a number'); + } + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setContext('database', $database) + ->setParam('collectionId', $collectionId) + ->setParam('tableId', $collectionId) + ->setContext($this->getCollectionsEventsContext(), $collection); + + $response->dynamic($document, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php new file mode 100644 index 0000000000..b65ca3c285 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php @@ -0,0 +1,126 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId/:attribute/increment') + ->desc('Increment document attribute') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].increment') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'documents.increment') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/increment-document-attribute.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('documentId', '', new UID(), 'Document ID.') + ->param('attribute', '', new Key(), 'Attribute key.') + ->param('value', 1, new Numeric(), 'Value to increment the attribute by. The value must be a number.', true) + ->param('max', null, new Numeric(), 'Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->callback($this->action(...)); + } + + public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): void + { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + if ($collection->isEmpty()) { + throw new Exception($this->getParentNotFoundException()); + } + + try { + $document = $dbForProject->increaseDocumentAttribute( + collection: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + id: $documentId, + attribute: $attribute, + value: $value, + max: $max + ); + } catch (ConflictException) { + throw new Exception($this->getConflictException()); + } catch (NotFoundException) { + // todo: @itznotabug what do we name this exception now? + throw new Exception($this->getStructureNotFoundException()); + } catch (LimitException) { + throw new Exception($this->getLimitException(), $this->getSdkNamespace() . ' "' . $attribute . '" has reached the maximum value of ' . $max); + } catch (TypeException) { + throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, $this->getSdkNamespace() . ' "' . $attribute . '" is not a number'); + } + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setContext('database', $database) + ->setParam('collectionId', $collectionId) + ->setParam('tableId', $collectionId) + ->setContext($this->getCollectionsEventsContext(), $collection); + + $response->dynamic($document, $this->getResponseModel()); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php index 73f3016936..9ddff818e3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php @@ -35,7 +35,7 @@ class Delete extends DocumentsDelete $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) - ->setHttpPath('/v1/databases/:databaseId/tables/:collectionId/rows') + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') ->desc('Delete rows') ->groups(['api', 'database']) ->label('scope', 'documents.write') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php new file mode 100644 index 0000000000..5b2cf17f91 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php @@ -0,0 +1,72 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId/:column/decrement') + ->desc('Decrement row column') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].decrement') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'rows.decrement') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/decrement-document-attribute.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('rowId', '', new UID(), 'Row ID.') + ->param('column', '', new Key(), 'Column key.') + ->param('value', 1, new Numeric(), 'Value to increment the column by. The value must be a number.', true) + ->param('min', null, new Numeric(), 'Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->callback($this->action(...)); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php new file mode 100644 index 0000000000..4dcd05cc25 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php @@ -0,0 +1,72 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId/:column/increment') + ->desc('Increment row column') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].increment') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'rows.increment') + ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: $this->getSdkNamespace(), + group: $this->getSdkGroup(), + name: self::getName(), + description: '/docs/references/databases/increment-document-attribute.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: SwooleResponse::STATUS_CODE_OK, + model: $this->getResponseModel(), + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('tableId', '', new UID(), 'Table ID.') + ->param('rowId', '', new UID(), 'Row ID.') + ->param('column', '', new Key(), 'Column key.') + ->param('value', 1, new Numeric(), 'Value to increment the column by. The value must be a number.', true) + ->param('max', null, new Numeric(), 'Maximum value for the column. If the current value is greater than this value, an error will be thrown.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->callback($this->action(...)); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php index 415eaeaf85..d036d2fd7b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php @@ -27,6 +27,8 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\UR use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\XList as ListAttributes; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Create as CreateCollection; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Delete as DeleteCollection; +use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Attribute\Decrement as DecrementDocumentAttribute; +use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Attribute\Increment as IncrementDocumentAttribute; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Delete as DeleteDocuments; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Update as UpdateDocuments; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Upsert as UpsertDocuments; @@ -88,6 +90,9 @@ class Collections extends Base $service->addAction(DeleteDocument::getName(), new DeleteDocument()); $service->addAction(DeleteDocuments::getName(), new DeleteDocuments()); $service->addAction(ListDocuments::getName(), new ListDocuments()); + $service->addAction(IncrementDocumentAttribute::getName(), new IncrementDocumentAttribute()); + $service->addAction(DecrementDocumentAttribute::getName(), new DecrementDocumentAttribute()); + } private function registerAttributeActions(Service $service): void diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php index 87e5f80e3f..4ddadeece6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php @@ -36,6 +36,8 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Logs\XList as List use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Bulk\Delete as DeleteRows; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Bulk\Update as UpdateRows; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Bulk\Upsert as UpsertRows; +use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Column\Decrement as DecrementRowColumn; +use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Column\Increment as IncrementRowColumn; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Create as CreateRow; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Delete as DeleteRow; use Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Get as GetRow; @@ -146,5 +148,7 @@ class Tables extends Base $service->addAction(DeleteRows::getName(), new DeleteRows()); $service->addAction(ListRows::getName(), new ListRows()); $service->addAction(ListRowLogs::getName(), new ListRowLogs()); + $service->addAction(IncrementRowColumn::getName(), new IncrementRowColumn()); + $service->addAction(DecrementRowColumn::getName(), new DecrementRowColumn()); } } diff --git a/src/Appwrite/Utopia/Response/Model/ColumnString.php b/src/Appwrite/Utopia/Response/Model/ColumnString.php index f962e51c37..f3a876b7a9 100644 --- a/src/Appwrite/Utopia/Response/Model/ColumnString.php +++ b/src/Appwrite/Utopia/Response/Model/ColumnString.php @@ -24,6 +24,13 @@ class ColumnString extends Column 'required' => false, 'example' => 'default', ]) + ->addRule('encrypt', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Defines whether this column is encrypted or not.', + 'default' => false, + 'required' => false, + 'example' => false, + ]) ; } From 1f31998092ce4c03fc078cac14066fd3fc25fe69 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 19:48:28 +0530 Subject: [PATCH 160/343] =?UTF-8?q?fix:=20route=20name=20=F0=9F=98=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Databases/Http/Databases/Tables/Rows/Bulk/Update.php | 2 +- .../Modules/Databases/Http/Databases/Tables/Rows/Update.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php index 95a0819dfd..53e7c3c152 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php @@ -21,7 +21,7 @@ class Update extends DocumentsUpdate public static function getName(): string { - return 'updateRow'; + return 'updateRows'; } protected function getResponseModel(): string diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php index dfe77c9075..d37f5cc92f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php @@ -62,7 +62,7 @@ class Update extends DocumentUpdate contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('tableId', '', new UID(), 'Collection ID.') + ->param('tableId', '', new UID(), 'Table ID.') ->param('rowId', '', new UID(), 'Row ID.') ->param('data', [], new JSON(), 'Row data as JSON object. Include only columns and value pairs to be updated.', true) ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) From b248c9b640f6ecca22e81684c58a4f29efdb418d Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 19:58:28 +0530 Subject: [PATCH 161/343] =?UTF-8?q?fix:=20a=20bunch=20of=20tests=20?= =?UTF-8?q?=F0=9F=9A=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Databases/Collections/DatabasesBase.php | 12 +- .../Collections/DatabasesCustomServerTest.php | 4 +- .../Databases/Tables/DatabasesBase.php | 681 ++++++++- .../Tables/DatabasesCustomServerTest.php | 1231 +++++++++++++++-- 4 files changed, 1782 insertions(+), 146 deletions(-) diff --git a/tests/e2e/Services/Databases/Collections/DatabasesBase.php b/tests/e2e/Services/Databases/Collections/DatabasesBase.php index 956b87e13d..6b0aca1512 100644 --- a/tests/e2e/Services/Databases/Collections/DatabasesBase.php +++ b/tests/e2e/Services/Databases/Collections/DatabasesBase.php @@ -1421,7 +1421,6 @@ trait DatabasesBase return $data; } - /** * @depends testCreateAttributes */ @@ -2079,7 +2078,6 @@ trait DatabasesBase return ['documents' => $documents['body']['documents'], 'databaseId' => $databaseId]; } - /** * @depends testListDocuments */ @@ -2830,7 +2828,7 @@ trait DatabasesBase return $data; } - public function testInvalidDocumentStructure() + public function testInvalidDocumentStructure(): void { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -3693,7 +3691,7 @@ trait DatabasesBase $this->assertCount(1, $documentsUser2['body']['documents']); } - public function testEnforceCollectionPermissions() + public function testEnforceCollectionPermissions(): void { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -3986,7 +3984,7 @@ trait DatabasesBase /** * @depends testUniqueIndexDuplicate */ - public function testPersistantCreatedAt(array $data): array + public function testPersistentCreatedAt(array $data): array { $headers = $this->getSide() === 'client' ? array_merge([ 'content-type' => 'application/json', @@ -5498,13 +5496,11 @@ trait DatabasesBase ]), ['min' => 7]); $this->assertEquals(400, $err['headers']['status-code']); - // Test type error on non-numeric attribut + // Test type error on non-numeric attribute $typeErr = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId . '/count/decrement', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]), ['value' => 'not-a-number']); $this->assertEquals(400, $typeErr['headers']['status-code']); } - - } diff --git a/tests/e2e/Services/Databases/Collections/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/Collections/DatabasesCustomServerTest.php index 84f7d43593..21382b8302 100644 --- a/tests/e2e/Services/Databases/Collections/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/Collections/DatabasesCustomServerTest.php @@ -3651,7 +3651,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $doc3['headers']['status-code']); } - public function createRelationshipCollections() + public function createRelationshipCollections(): void { // Prepare the database with collections and relationships $database = $this->client->call(Client::METHOD_POST, '/databases', [ @@ -3700,7 +3700,7 @@ class DatabasesCustomServerTest extends Scope \sleep(2); } - public function cleanupRelationshipCollection() + public function cleanupRelationshipCollection(): void { $this->client->call(Client::METHOD_DELETE, '/databases/database1', [ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Databases/Tables/DatabasesBase.php b/tests/e2e/Services/Databases/Tables/DatabasesBase.php index ef35d3c962..a0b6be2fbe 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesBase.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesBase.php @@ -39,7 +39,7 @@ trait DatabasesBase /** * @depends testCreateDatabase */ - public function testCreateCollection(array $data): array + public function testCreateTable(array $data): array { $databaseId = $data['databaseId']; /** @@ -85,9 +85,9 @@ trait DatabasesBase } /** - * @depends testCreateCollection + * @depends testCreateTable */ - public function testConsoleProject(array $data) + public function testConsoleProject(array $data): void { if ($this->getSide() === 'server') { // Server side can't get past the invalid key check anyway @@ -121,9 +121,9 @@ trait DatabasesBase } /** - * @depends testCreateCollection + * @depends testCreateTable */ - public function testDisableCollection(array $data): void + public function testDisableTable(array $data): void { $databaseId = $data['databaseId']; /** @@ -190,9 +190,9 @@ trait DatabasesBase } /** - * @depends testCreateCollection + * @depends testCreateTable */ - public function testCreateAttributes(array $data): array + public function testCreateColumns(array $data): array { $databaseId = $data['databaseId']; @@ -375,9 +375,9 @@ trait DatabasesBase } /** - * @depends testCreateAttributes + * @depends testCreateColumns */ - public function testListAttributes(array $data): void + public function testListColumns(array $data): void { $databaseId = $data['databaseId']; $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/columns', array_merge([ @@ -407,7 +407,7 @@ trait DatabasesBase /** * @depends testCreateDatabase */ - public function testPatchAttribute(array $data): void + public function testPatchColumn(array $data): void { $databaseId = $data['databaseId']; @@ -471,7 +471,7 @@ trait DatabasesBase $this->assertStringContainsString('Index length is longer than the maximum: 76', $attribute['body']['message']); } - public function testUpdateAttributeEnum(): void + public function testUpdateColumnEnum(): void { $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', @@ -529,9 +529,9 @@ trait DatabasesBase } /** - * @depends testCreateAttributes + * @depends testCreateColumns */ - public function testAttributeResponseModels(array $data): array + public function testColumnResponseModels(array $data): array { $databaseId = $data['databaseId']; $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ @@ -1196,7 +1196,7 @@ trait DatabasesBase } /** - * @depends testCreateAttributes + * @depends testCreateColumns */ public function testCreateIndexes(array $data): array { @@ -1421,6 +1421,99 @@ trait DatabasesBase return $data; } + /** + * @depends testCreateColumns + */ + public function testGetIndexByKeyWithLengths(array $data): void + { + $databaseId = $data['databaseId']; + $tableId = $data['moviesId']; + + // Test case for valid lengths + $create = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$tableId}/indexes", [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'key' => 'lengthTestIndex', + 'type' => 'key', + 'attributes' => ['title','description'], + 'lengths' => [128,200] + ]); + $this->assertEquals(202, $create['headers']['status-code']); + + // Fetch index and check correct lengths + $index = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/tables/{$tableId}/indexes/lengthTestIndex", [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + $this->assertEquals(200, $index['headers']['status-code']); + $this->assertEquals('lengthTestIndex', $index['body']['key']); + $this->assertEquals([128, 200], $index['body']['lengths']); + + // Test case for lengths array overriding + // set a length for an array attribute, it should get overriden with Database::ARRAY_INDEX_LENGTH + $create = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$tableId}/indexes", [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'key' => 'lengthOverrideTestIndex', + 'type' => 'key', + 'attributes' => ['actors'], + 'lengths' => [120] + ]); + $this->assertEquals(202, $create['headers']['status-code']); + + $index = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/tables/{$tableId}/indexes/lengthOverrideTestIndex", [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]); + $this->assertEquals([Database::ARRAY_INDEX_LENGTH], $index['body']['lengths']); + + // Test case for count of lengths greater than attributes (should throw 400) + $create = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$tableId}/indexes", [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'key' => 'lengthCountExceededIndex', + 'type' => 'key', + 'attributes' => ['title'], + 'lengths' => [128, 128] + ]); + $this->assertEquals(400, $create['headers']['status-code']); + + // Test case for lengths exceeding total of 768 + $create = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$tableId}/indexes", [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'key' => 'lengthTooLargeIndex', + 'type' => 'key', + 'attributes' => ['title','description','tagline','actors'], + 'lengths' => [256,256,256,20] + ]); + + $this->assertEquals(400, $create['headers']['status-code']); + + // Test case for negative length values + $create = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$tableId}/indexes", [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'key' => 'negativeLengthIndex', + 'type' => 'key', + 'attributes' => ['title'], + 'lengths' => [-1] + ]); + $this->assertEquals(400, $create['headers']['status-code']); + } + /** * @depends testCreateIndexes */ @@ -1455,7 +1548,7 @@ trait DatabasesBase /** * @depends testCreateIndexes */ - public function testCreateDocument(array $data): array + public function testCreateRow(array $data): array { $databaseId = $data['databaseId']; $row1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ @@ -1596,9 +1689,311 @@ trait DatabasesBase } /** - * @depends testCreateDocument + * @depends testCreateIndexes */ - public function testListDocuments(array $data): array + public function testUpsertRow(array $data): void + { + $databaseId = $data['databaseId']; + $rowId = ID::unique(); + $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Ragnarok', + 'releaseYear' => 2000 + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + ]); + + $this->assertEquals(200, $document['headers']['status-code']); + $this->assertCount(3, $document['body']['$permissions']); + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Thor: Ragnarok', $document['body']['title']); + + $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Love and Thunder', + 'releaseYear' => 2000 + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + ]); + + $this->assertEquals(200, $document['headers']['status-code']); + $this->assertEquals('Thor: Love and Thunder', $document['body']['title']); + + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Thor: Love and Thunder', $document['body']['title']); + + // removing permission to read and delete + $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Love and Thunder', + 'releaseYear' => 2000 + ], + 'permissions' => [ + Permission::update(Role::users()) + ], + ]); + // shouldn't be able to read as no read permission + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + switch ($this->getSide()) { + case 'client': + $this->assertEquals(404, $document['headers']['status-code']); + break; + case 'server': + $this->assertEquals(200, $document['headers']['status-code']); + break; + } + // shouldn't be able to delete as no delete permission + $document = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + // simulating for the client + // the document should not be allowed to be deleted as needed downward + if ($this->getSide() === 'client') { + $this->assertEquals(401, $document['headers']['status-code']); + } + // giving the delete permission + $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Love and Thunder', + 'releaseYear' => 2000 + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()) + ], + ]); + $document = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(204, $document['headers']['status-code']); + + // relationship behaviour + $person = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'person-upsert', + 'name' => 'person', + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + Permission::create(Role::users()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $person['headers']['status-code']); + + $library = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'library-upsert', + 'name' => 'library', + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::create(Role::users()), + Permission::delete(Role::users()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $library['headers']['status-code']); + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'fullName', + 'size' => 255, + 'required' => false, + ]); + + sleep(1); // Wait for worker + + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedtableId' => 'library-upsert', + 'type' => Database::RELATION_ONE_TO_ONE, + 'key' => 'library', + 'twoWay' => true, + 'onDelete' => Database::RELATION_MUTATE_CASCADE, + ]); + + sleep(1); // Wait for worker + + $libraryName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $library['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'libraryName', + 'size' => 255, + 'required' => true, + ]); + + sleep(1); // Wait for worker + + $this->assertEquals(202, $libraryName['headers']['status-code']); + + // upserting values + $rowId = ID::unique(); + $person1 = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/rows/'.$rowId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'library' => [ + '$id' => 'library1', + '$permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + 'libraryName' => 'Library 1', + ], + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ] + ]); + + $this->assertEquals('Library 1', $person1['body']['library']['libraryName']); + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['fullName', 'library.*'])->toString(), + Query::equal('library', ['library1'])->toString(), + ], + ]); + + $this->assertEquals(1, $documents['body']['total']); + $this->assertEquals('Library 1', $documents['body']['documents'][0]['library']['libraryName']); + + + $person1 = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/rows/'.$rowId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'library' => [ + '$id' => 'library1', + '$permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + 'libraryName' => 'Library 2', + ], + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ] + ]); + + // data should get updated + $this->assertEquals('Library 2', $person1['body']['library']['libraryName']); + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['fullName', 'library.*'])->toString(), + Query::equal('library', ['library1'])->toString(), + ], + ]); + + $this->assertEquals(1, $documents['body']['total']); + $this->assertEquals('Library 2', $documents['body']['documents'][0]['library']['libraryName']); + + + // data should get added + $person1 = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/rows/'.ID::unique(), array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'library' => [ + '$id' => 'library2', + '$permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + 'libraryName' => 'Library 2', + ], + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ] + ]); + + $this->assertEquals('Library 2', $person1['body']['library']['libraryName']); + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['fullName', 'library.*'])->toString() + ], + ]); + $this->assertEquals(2, $documents['body']['total']); + } + + /** + * @depends testCreateRow + */ + public function testListRows(array $data): array { $databaseId = $data['databaseId']; $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ @@ -1687,11 +2082,10 @@ trait DatabasesBase return ['rows' => $rows['body']['rows'], 'databaseId' => $databaseId]; } - /** - * @depends testListDocuments + * @depends testListRows */ - public function testGetDocument(array $data): void + public function testGetRow(array $data): void { $databaseId = $data['databaseId']; foreach ($data['rows'] as $row) { @@ -1715,9 +2109,9 @@ trait DatabasesBase } /** - * @depends testListDocuments + * @depends testListRows */ - public function testGetDocumentWithQueries(array $data): void + public function testGetRowWithQueries(array $data): void { $databaseId = $data['databaseId']; $row = $data['rows'][0]; @@ -1738,9 +2132,9 @@ trait DatabasesBase } /** - * @depends testCreateDocument + * @depends testCreateRow */ - public function testListDocumentsAfterPagination(array $data): array + public function testListRowsAfterPagination(array $data): array { $databaseId = $data['databaseId']; /** @@ -1880,9 +2274,9 @@ trait DatabasesBase } /** - * @depends testCreateDocument + * @depends testCreateRow */ - public function testListDocumentsBeforePagination(array $data): array + public function testListRowsBeforePagination(array $data): array { $databaseId = $data['databaseId']; /** @@ -1993,9 +2387,9 @@ trait DatabasesBase } /** - * @depends testCreateDocument + * @depends testCreateRow */ - public function testListDocumentsLimitAndOffset(array $data): array + public function testListRowsLimitAndOffset(array $data): array { $databaseId = $data['databaseId']; $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ @@ -2032,9 +2426,9 @@ trait DatabasesBase } /** - * @depends testCreateDocument + * @depends testCreateRow */ - public function testDocumentsListQueries(array $data): array + public function testRowsListQueries(array $data): array { $databaseId = $data['databaseId']; $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ @@ -2277,9 +2671,9 @@ trait DatabasesBase } /** - * @depends testCreateDocument + * @depends testCreateRow */ - public function testUpdateDocument(array $data): array + public function testUpdateRow(array $data): array { $databaseId = $data['databaseId']; $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ @@ -2403,9 +2797,9 @@ trait DatabasesBase } /** - * @depends testCreateDocument + * @depends testCreateRow */ - public function testDeleteDocument(array $data): array + public function testDeleteRow(array $data): array { $databaseId = $data['databaseId']; $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ @@ -2454,7 +2848,7 @@ trait DatabasesBase return $data; } - public function testInvalidDocumentStructure() + public function testInvalidRowStructure(): void { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -3005,7 +3399,7 @@ trait DatabasesBase } /** - * @depends testDeleteDocument + * @depends testDeleteRow */ public function testDefaultPermissions(array $data): array { @@ -3124,7 +3518,7 @@ trait DatabasesBase return $data; } - public function testEnforceCollectionAndDocumentPermissions(): void + public function testEnforceTableAndRowPermissions(): void { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -3317,7 +3711,7 @@ trait DatabasesBase $this->assertCount(1, $rowsUser2['body']['rows']); } - public function testEnforceCollectionPermissions() + public function testEnforceTablePermissions(): void { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -3610,7 +4004,7 @@ trait DatabasesBase /** * @depends testUniqueIndexDuplicate */ - public function testPersistantCreatedAt(array $data): array + public function testPersistentCreatedAt(array $data): array { $headers = $this->getSide() === 'client' ? array_merge([ 'content-type' => 'application/json', @@ -3789,7 +4183,7 @@ trait DatabasesBase /** * @depends testCreateDatabase */ - public function testAttributeBooleanDefault(array $data): void + public function testColumnBooleanDefault(array $data): void { $databaseId = $data['databaseId']; @@ -4916,4 +5310,211 @@ trait DatabasesBase $this->assertEquals(408, $response['headers']['status-code']); } + + /** + * @throws \Exception + */ + public function testIncrementColumn(): void + { + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'CounterDatabase' + ]); + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'CounterCollection', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + ], + ]); + $tableId = $collection['body']['$id']; + + // Add integer attribute + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'count', + 'required' => true, + ]); + + \sleep(3); + + // Create document with initial count = 5 + $doc = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'count' => 5 + ], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + $this->assertEquals(201, $doc['headers']['status-code']); + + $docId = $doc['body']['$id']; + + // Increment by default 1 + $inc = $this->client->call(Client::METHOD_PATCH, "/databases/$databaseId/tables/$tableId/rows/$docId/count/increment", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + $this->assertEquals(200, $inc['headers']['status-code']); + $this->assertEquals(6, $inc['body']['count']); + + // Verify count = 6 + $get = $this->client->call(Client::METHOD_GET, "/databases/$databaseId/tables/$tableId/rows/$docId", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(6, $get['body']['count']); + + // Increment by custom value 4 + $inc2 = $this->client->call(Client::METHOD_PATCH, "/databases/$databaseId/tables/$tableId/rows/$docId/count/increment", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'value' => 4 + ]); + $this->assertEquals(200, $inc2['headers']['status-code']); + $this->assertEquals(10, $inc2['body']['count']); + + $get2 = $this->client->call(Client::METHOD_GET, "/databases/$databaseId/tables/$tableId/rows/$docId", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(10, $get2['body']['count']); + + // Test max limit exceeded + $err = $this->client->call(Client::METHOD_PATCH, "/databases/$databaseId/tables/$tableId/rows/$docId/count/increment", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), ['max' => 8]); + $this->assertEquals(400, $err['headers']['status-code']); + + // Test attribute not found + $notFound = $this->client->call(Client::METHOD_PATCH, "/databases/$databaseId/tables/$tableId/rows/$docId/unknown/increment", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + $this->assertEquals(404, $notFound['headers']['status-code']); + } + + public function testDecrementColumn(): void + { + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'CounterDatabase' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'CounterCollection', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + ], + ]); + + $tableId = $collection['body']['$id']; + + // Add integer attribute + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'count', + 'required' => true, + ]); + + \sleep(2); + + // Create document with initial count = 10 + $doc = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => ['count' => 10], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $rowId = $doc['body']['$id']; + + // Decrement by default 1 (count = 10 -> 9) + $dec = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $rowId . '/count/decrement', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + $this->assertEquals(200, $dec['headers']['status-code']); + $this->assertEquals(9, $dec['body']['count']); + + $get = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $rowId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(9, $get['body']['count']); + + // Decrement by custom value 3 (count 9 -> 6) + $dec2 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $rowId . '/count/decrement', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'value' => 3 + ]); + $this->assertEquals(200, $dec2['headers']['status-code']); + $this->assertEquals(6, $dec2['body']['count']); + + $get2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $rowId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(6, $get2['body']['count']); + + // Test min limit exceeded + $err = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $rowId . '/count/decrement', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), ['min' => 7]); + $this->assertEquals(400, $err['headers']['status-code']); + + // Test type error on non-numeric attribute + $typeErr = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $rowId . '/count/decrement', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), ['value' => 'not-a-number']); + $this->assertEquals(400, $typeErr['headers']['status-code']); + } } diff --git a/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php index a92f1decf1..e2aebf4969 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php @@ -866,13 +866,13 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($table['body']['indexes'][0]['key'], $index['body']['key']); // Delete attribute - $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/columns/' . $unneededId, array_merge([ + $column = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/columns/' . $unneededId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertEquals(204, $attribute['headers']['status-code']); + $this->assertEquals(204, $column['headers']['status-code']); sleep(2); @@ -938,7 +938,7 @@ class DatabasesCustomServerTest extends Scope public function testDeleteIndexOnDeleteAttribute($data) { $databaseId = $data['databaseId']; - $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/string', array_merge([ + $column1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -948,7 +948,7 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/string', array_merge([ + $column2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -958,10 +958,10 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - $this->assertEquals(202, $attribute1['headers']['status-code']); - $this->assertEquals(202, $attribute2['headers']['status-code']); - $this->assertEquals('attribute1', $attribute1['body']['key']); - $this->assertEquals('attribute2', $attribute2['body']['key']); + $this->assertEquals(202, $column1['headers']['status-code']); + $this->assertEquals(202, $column2['headers']['status-code']); + $this->assertEquals('attribute1', $column1['body']['key']); + $this->assertEquals('attribute2', $column2['body']['key']); sleep(2); @@ -994,7 +994,7 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Expected behavior: deleting attribute2 will cause index2 to be dropped, and index1 rebuilt with a single key - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/' . $attribute2['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/' . $column2['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1017,10 +1017,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($index1['body']['key'], $table['body']['indexes'][0]['key']); $this->assertIsArray($table['body']['indexes'][0]['columns']); $this->assertCount(1, $table['body']['indexes'][0]['columns']); - $this->assertEquals($attribute1['body']['key'], $table['body']['indexes'][0]['columns'][0]); + $this->assertEquals($column1['body']['key'], $table['body']['indexes'][0]['columns'][0]); // Delete attribute - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/' . $attribute1['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/' . $column1['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1066,7 +1066,7 @@ class DatabasesCustomServerTest extends Scope $tableId = $table['body']['$id']; - $attribute1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + $column1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1076,7 +1076,7 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - $attribute2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + $column2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1086,10 +1086,10 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - $this->assertEquals(202, $attribute1['headers']['status-code']); - $this->assertEquals(202, $attribute2['headers']['status-code']); - $this->assertEquals('attribute1', $attribute1['body']['key']); - $this->assertEquals('attribute2', $attribute2['body']['key']); + $this->assertEquals(202, $column1['headers']['status-code']); + $this->assertEquals(202, $column2['headers']['status-code']); + $this->assertEquals('attribute1', $column1['body']['key']); + $this->assertEquals('attribute2', $column2['body']['key']); sleep(2); @@ -1122,7 +1122,7 @@ class DatabasesCustomServerTest extends Scope sleep(2); // Expected behavior: deleting attribute1 would cause index1 to be a duplicate of index2 and automatically removed - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $attribute1['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $column1['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1145,10 +1145,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($index2['body']['key'], $table['body']['indexes'][0]['key']); $this->assertIsArray($table['body']['indexes'][0]['columns']); $this->assertCount(1, $table['body']['indexes'][0]['columns']); - $this->assertEquals($attribute2['body']['key'], $table['body']['indexes'][0]['columns'][0]); + $this->assertEquals($column2['body']['key'], $table['body']['indexes'][0]['columns'][0]); // Delete attribute - $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $attribute2['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $column2['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1336,7 +1336,7 @@ class DatabasesCustomServerTest extends Scope // Add wide string attributes to approach row width limit for ($i = 0; $i < 15; $i++) { - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1346,7 +1346,7 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - $this->assertEquals(202, $attribute['headers']['status-code']); + $this->assertEquals(202, $column['headers']['status-code']); } sleep(5); @@ -1403,7 +1403,7 @@ class DatabasesCustomServerTest extends Scope // add unique attributes for indexing for ($i = 0; $i < 64; $i++) { // $this->assertEquals(true, static::getDatabase()->createAttribute('indexLimit', "test{$i}", Database::VAR_STRING, 16, true)); - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1413,7 +1413,7 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - $this->assertEquals(202, $attribute['headers']['status-code']); + $this->assertEquals(202, $column['headers']['status-code']); } sleep(10); @@ -1431,8 +1431,8 @@ class DatabasesCustomServerTest extends Scope $this->assertCount(64, $table['body']['columns']); $this->assertCount(0, $table['body']['indexes']); - foreach ($table['body']['columns'] as $attribute) { - $this->assertEquals('available', $attribute['status'], 'attribute: ' . $attribute['key']); + foreach ($table['body']['columns'] as $column) { + $this->assertEquals('available', $column['status'], 'attribute: ' . $column['key']); } // Test indexLimit = 64 @@ -1519,7 +1519,7 @@ class DatabasesCustomServerTest extends Scope /** * Create String Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1529,12 +1529,12 @@ class DatabasesCustomServerTest extends Scope 'required' => false ]); - $this->assertEquals(202, $attribute['headers']['status-code']); + $this->assertEquals(202, $column['headers']['status-code']); /** * Create Email Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email', array_merge([ + $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1543,12 +1543,12 @@ class DatabasesCustomServerTest extends Scope 'required' => false ]); - $this->assertEquals(202, $attribute['headers']['status-code']); + $this->assertEquals(202, $column['headers']['status-code']); /** * Create IP Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip', array_merge([ + $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1557,12 +1557,12 @@ class DatabasesCustomServerTest extends Scope 'required' => false ]); - $this->assertEquals(202, $attribute['headers']['status-code']); + $this->assertEquals(202, $column['headers']['status-code']); /** * Create URL Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url', array_merge([ + $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1571,12 +1571,12 @@ class DatabasesCustomServerTest extends Scope 'required' => false ]); - $this->assertEquals(202, $attribute['headers']['status-code']); + $this->assertEquals(202, $column['headers']['status-code']); /** * Create Integer Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ + $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1585,12 +1585,12 @@ class DatabasesCustomServerTest extends Scope 'required' => false ]); - $this->assertEquals(202, $attribute['headers']['status-code']); + $this->assertEquals(202, $column['headers']['status-code']); /** * Create Float Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float', array_merge([ + $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1602,7 +1602,7 @@ class DatabasesCustomServerTest extends Scope /** * Create Boolean Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean', array_merge([ + $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1614,7 +1614,7 @@ class DatabasesCustomServerTest extends Scope /** * Create Datetime Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime', array_merge([ + $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1626,7 +1626,7 @@ class DatabasesCustomServerTest extends Scope /** * Create Enum Attribute */ - $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum', array_merge([ + $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -1636,7 +1636,7 @@ class DatabasesCustomServerTest extends Scope 'elements' => ['lorem', 'ipsum'] ]); - $this->assertEquals(202, $attribute['headers']['status-code']); + $this->assertEquals(202, $column['headers']['status-code']); sleep(5); @@ -1681,10 +1681,10 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; - $this->assertNotNull($attribute); - $this->assertFalse($attribute['required']); - $this->assertEquals('lorem', $attribute['default']); + $column = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($column); + $this->assertFalse($column['required']); + $this->assertEquals('lorem', $column['default']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ 'content-type' => 'application/json', @@ -1823,10 +1823,10 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; - $this->assertNotNull($attribute); - $this->assertFalse($attribute['required']); - $this->assertEquals('torsten@appwrite.io', $attribute['default']); + $column = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($column); + $this->assertFalse($column['required']); + $this->assertEquals('torsten@appwrite.io', $column['default']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email/' . $key, array_merge([ @@ -1966,10 +1966,10 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; - $this->assertNotNull($attribute); - $this->assertFalse($attribute['required']); - $this->assertEquals('127.0.0.1', $attribute['default']); + $column = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($column); + $this->assertFalse($column['required']); + $this->assertEquals('127.0.0.1', $column['default']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2108,10 +2108,10 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; - $this->assertNotNull($attribute); - $this->assertFalse($attribute['required']); - $this->assertEquals('http://appwrite.io', $attribute['default']); + $column = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($column); + $this->assertFalse($column['required']); + $this->assertEquals('http://appwrite.io', $column['default']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2254,12 +2254,12 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; - $this->assertNotNull($attribute); - $this->assertFalse($attribute['required']); - $this->assertEquals(123, $attribute['default']); - $this->assertEquals(0, $attribute['min']); - $this->assertEquals(1000, $attribute['max']); + $column = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($column); + $this->assertFalse($column['required']); + $this->assertEquals(123, $column['default']); + $this->assertEquals(0, $column['min']); + $this->assertEquals(1000, $column['max']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2515,12 +2515,12 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; - $this->assertNotNull($attribute); - $this->assertFalse($attribute['required']); - $this->assertEquals(123.456, $attribute['default']); - $this->assertEquals(0, $attribute['min']); - $this->assertEquals(1000, $attribute['max']); + $column = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($column); + $this->assertFalse($column['required']); + $this->assertEquals(123.456, $column['default']); + $this->assertEquals(0, $column['min']); + $this->assertEquals(1000, $column['max']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2772,10 +2772,10 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; - $this->assertNotNull($attribute); - $this->assertFalse($attribute['required']); - $this->assertEquals(true, $attribute['default']); + $column = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($column); + $this->assertFalse($column['required']); + $this->assertEquals(true, $column['default']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean/' . $key, array_merge([ 'content-type' => 'application/json', @@ -2914,10 +2914,10 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; - $this->assertNotNull($attribute); - $this->assertFalse($attribute['required']); - $this->assertEquals('1975-06-12 14:12:55+02:00', $attribute['default']); + $column = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($column); + $this->assertFalse($column['required']); + $this->assertEquals('1975-06-12 14:12:55+02:00', $column['default']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime/' . $key, array_merge([ 'content-type' => 'application/json', @@ -3061,14 +3061,14 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $attribute = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; - $this->assertNotNull($attribute); - $this->assertFalse($attribute['required']); - $this->assertEquals('lorem', $attribute['default']); - $this->assertCount(3, $attribute['elements']); - $this->assertContains('lorem', $attribute['elements']); - $this->assertContains('ipsum', $attribute['elements']); - $this->assertContains('dolor', $attribute['elements']); + $column = array_values(array_filter($new['body']['columns'], fn (array $a) => $a['key'] === $key))[0] ?? null; + $this->assertNotNull($column); + $this->assertFalse($column['required']); + $this->assertEquals('lorem', $column['default']); + $this->assertCount(3, $column['elements']); + $this->assertContains('lorem', $column['elements']); + $this->assertContains('ipsum', $column['elements']); + $this->assertContains('dolor', $column['elements']); $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum/' . $key, array_merge([ 'content-type' => 'application/json', @@ -3264,7 +3264,7 @@ class DatabasesCustomServerTest extends Scope ); // Test Resize Up - $attribute = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + $column = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -3274,8 +3274,8 @@ class DatabasesCustomServerTest extends Scope 'required' => false ]); - $this->assertEquals(200, $attribute['headers']['status-code']); - $this->assertEquals(2048, $attribute['body']['size']); + $this->assertEquals(200, $column['headers']['status-code']); + $this->assertEquals(2048, $column['body']['size']); // Test create new document with new size $newDoc = $this->client->call( @@ -3313,7 +3313,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(2048, strlen($row['body']['string'])); // Test Exception on resize down with data that is too large - $attribute = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + $column = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -3323,8 +3323,8 @@ class DatabasesCustomServerTest extends Scope 'required' => false ]); - $this->assertEquals(400, $attribute['headers']['status-code']); - $this->assertEquals(AppwriteException::COLUMN_INVALID_RESIZE, $attribute['body']['type']); + $this->assertEquals(400, $column['headers']['status-code']); + $this->assertEquals(AppwriteException::COLUMN_INVALID_RESIZE, $column['body']['type']); // original documents to original size, remove new document $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row['body']['$id'], array_merge([ @@ -3350,7 +3350,7 @@ class DatabasesCustomServerTest extends Scope // Test Resize Down - $attribute = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ + $column = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -3360,8 +3360,8 @@ class DatabasesCustomServerTest extends Scope 'required' => false ]); - $this->assertEquals(200, $attribute['headers']['status-code']); - $this->assertEquals(10, $attribute['body']['size']); + $this->assertEquals(200, $column['headers']['status-code']); + $this->assertEquals(10, $column['body']['size']); // Test create new document with new size $newDoc = $this->client->call( @@ -3611,7 +3611,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $doc3['headers']['status-code']); } - public function createRelationshipCollections() + public function createRelationshipCollections(): void { // Prepare the database with collections and relationships $database = $this->client->call(Client::METHOD_POST, '/databases', [ @@ -3660,7 +3660,7 @@ class DatabasesCustomServerTest extends Scope \sleep(2); } - public function cleanupRelationshipCollection() + public function cleanupRelationshipCollection(): void { $this->client->call(Client::METHOD_DELETE, '/databases/database1', [ 'content-type' => 'application/json', @@ -4110,4 +4110,1043 @@ class DatabasesCustomServerTest extends Scope $this->cleanupRelationshipCollection(); } + + public function testBulkCreate(): void + { + // Create database + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Bulk Create Perms', + ]); + + $this->assertNotEmpty($database['body']['$id']); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Bulk Create Perms', + 'rowSecurity' => true, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::delete(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $data = [ + '$id' => $collection['body']['$id'], + 'databaseId' => $collection['body']['databaseId'] + ]; + + // Await attribute + $numberAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'number', + 'required' => true, + ]); + + $this->assertEquals(202, $numberAttribute['headers']['status-code']); + + sleep(1); + + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rows' => [ + [ + '$id' => ID::unique(), + 'number' => 1, + ], + [ + '$id' => ID::unique(), + 'number' => 2, + ], + [ + '$id' => ID::unique(), + 'number' => 3, + ], + ], + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertCount(3, $response['body']['rows']); + + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(1, $response['body']['rows'][0]['number']); + $this->assertEquals(2, $response['body']['rows'][1]['number']); + $this->assertEquals(3, $response['body']['rows'][2]['number']); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(3, $response['body']['rows']); + + // TEST SUCCESS - $id is auto-assigned if not included in bulk documents + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rows' => [ + [ + 'number' => 1, + ] + ], + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // TEST FAIL - Can't use data and document together + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'number' => 5 + ], + 'rows' => [ + [ + '$id' => ID::unique(), + 'number' => 1, + ] + ], + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // TEST FAIL - Can't use $rowId and create bulk documents + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'rows' => [ + [ + '$id' => ID::unique(), + 'number' => 1, + ] + ], + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // TEST FAIL - Can't include invalid ID in bulk documents + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rows' => [ + [ + '$id' => '$invalid', + 'number' => 1, + ] + ], + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // TEST FAIL - Can't miss number in bulk documents + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rows' => [ + [ + '$id' => ID::unique(), + 'number' => 1, + ], + [ + '$id' => ID::unique(), + ], + ], + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // TEST FAIL - Can't push more than APP_LIMIT_DATABASE_BATCH documents + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rows' => array_fill(0, APP_LIMIT_DATABASE_BATCH + 1, [ + '$id' => ID::unique(), + 'number' => 1, + ]), + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // TEST FAIL - Can't include invalid permissions in nested documents + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rows' => [ + [ + '$id' => ID::unique(), + '$permissions' => ['invalid'], + 'number' => 1, + ], + ], + ]); + + // TEST FAIL - Can't bulk create in a collection with relationships + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Bulk Related', + 'rowSecurity' => true, + 'permissions' => [], + ]); + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], $this->getHeaders()), [ + 'relatedTableId' => $collection2['body']['$id'], + 'type' => 'manyToOne', + 'twoWay' => true, + 'onDelete' => 'cascade', + 'key' => 'level2', + 'twoWayKey' => 'level1' + ]); + + $this->assertEquals(202, $response['headers']['status-code']); + + sleep(1); + + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rows' => [ + ['$id' => ID::unique(), 'number' => 1,], + ['$id' => ID::unique(), 'number' => 2,], + ], + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } + + public function testBulkUpdate(): void + { + // Create database + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Bulk Updates' + ]); + + $this->assertNotEmpty($database['body']['$id']); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Bulk Updates', + 'rowSecurity' => true, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::delete(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $data = [ + '$id' => $collection['body']['$id'], + 'databaseId' => $collection['body']['databaseId'] + ]; + + // Await attribute + $numberAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'number', + 'required' => true, + ]); + + $this->assertEquals(202, $numberAttribute['headers']['status-code']); + + // Wait for database worker to create attributes + sleep(2); + + // Create documents + $createBulkDocuments = function ($amount = 10) use ($data) { + $documents = []; + + for ($x = 1; $x <= $amount; $x++) { + $documents[] = [ + '$id' => ID::unique(), + 'number' => $x, + ]; + } + + $doc = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rows' => $documents, + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + }; + + $createBulkDocuments(); + + // TEST: Update all documents + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'number' => 100, + '$permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ] + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(10, $response['body']['rows']); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + Query::equal('number', [100])->toString(), + ]); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(10, $documents['body']['total']); + + $returnedDocuments = $response['body']['rows']; + $refetchedDocuments = $documents['body']['rows']; + + $this->assertEquals($returnedDocuments, $refetchedDocuments); + + foreach ($documents['body']['rows'] as $document) { + $this->assertEquals([ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ], $document['$permissions']); + $this->assertEquals($collection['body']['$id'], $document['$tableId']); + $this->assertEquals($data['databaseId'], $document['$databaseId']); + $this->assertEquals(100, $document['number']); + } + + // TEST: Check permissions persist + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'number' => 200 + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(10, $response['body']['rows']); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + Query::equal('number', [200])->toString(), + ]); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(10, $documents['body']['total']); + + foreach ($documents['body']['rows'] as $document) { + $this->assertEquals([ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ], $document['$permissions']); + } + + // TEST: Update documents with limit + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'number' => 300 + ], + 'queries' => [ + Query::limit(5)->toString(), + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(5, $response['body']['rows']); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('number', [200])->toString()] + ]); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(5, $documents['body']['total']); + + // TEST: Update documents with offset + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'number' => 300 + ], + 'queries' => [ + Query::offset(5)->toString(), + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(5, $response['body']['rows']); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('number', [300])->toString()] + ]); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(10, $documents['body']['total']); + + // TEST: Update documents with equals filter + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'number' => 400 + ], + 'queries' => [ + Query::equal('number', [300])->toString(), + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(10, $response['body']['rows']); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('number', [400])->toString()] + ]); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(10, $documents['body']['total']); + + // TEST: Fail - Can't bulk update in a collection with relationships + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Bulk Related', + 'rowSecurity' => true, + 'permissions' => [], + ]); + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], $this->getHeaders()), [ + 'relatedTableId' => $collection2['body']['$id'], + 'type' => 'manyToOne', + 'twoWay' => true, + 'onDelete' => 'cascade', + 'key' => 'level2', + 'twoWayKey' => 'level1' + ]); + + $this->assertEquals(202, $response['headers']['status-code']); + + sleep(1); + + $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'number' => 500 + ], + 'queries' => [ + Query::equal('number', [300])->toString(), + ], + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } + + public function testBulkUpsert(): void + { + // Create database + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Bulk Upserts' + ]); + + $this->assertNotEmpty($database['body']['$id']); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Bulk Upserts', + 'rowSecurity' => true, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::delete(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $data = [ + '$id' => $collection['body']['$id'], + 'databaseId' => $collection['body']['databaseId'] + ]; + + // Await attribute + $numberAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'number', + 'required' => true, + ]); + + $this->assertEquals(202, $numberAttribute['headers']['status-code']); + + // Wait for database worker to create attributes + sleep(2); + + // Create documents + $createBulkDocuments = function ($amount = 10) use ($data) { + $documents = []; + + for ($x = 1; $x <= $amount; $x++) { + $documents[] = [ + '$id' => "$x", + 'number' => $x, + ]; + } + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rows' => $documents, + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + return $documents; + }; + + $documents = $createBulkDocuments(); + + // Update 1 document + $documents[\array_key_last($documents)]['number'] = 1000; + + // Add 1 document + $documents[] = ['number' => 11]; + + // TEST: Upsert all documents + $response = $this->client->call(Client::METHOD_PUT, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rows' => $documents, + ]); + + // Unchanged docs are skipped. 2 documents should be returned, 1 updated and 1 inserted. + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(2, $response['body']['rows']); + $this->assertEquals(1000, $response['body']['rows'][0]['number']); + $this->assertEquals(11, $response['body']['rows'][1]['number']); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(11, $documents['body']['total']); + + foreach ($documents['body']['rows'] as $index => $document) { + $this->assertEquals($collection['body']['$id'], $document['$tableId']); + $this->assertEquals($data['databaseId'], $document['$databaseId']); + switch ($index) { + case 9: + $this->assertEquals(1000, $document['number']); + break; + default: + $this->assertEquals($index + 1, $document['number']); + } + } + + // TEST: Upsert permissions + $response = $this->client->call(Client::METHOD_PUT, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rows' => [ + [ + '$id' => '1', + 'number' => 1000, + ], + [ + '$id' => '10', + '$permissions' => [ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ], + 'number' => 10, + ], + ], + ]); + + $this->assertEquals(1000, $response['body']['rows'][0]['number']); + $this->assertEquals([], $response['body']['rows'][0]['$permissions']); + $this->assertEquals([ + Permission::read(Role::user($this->getUser()['$id'])), + Permission::update(Role::user($this->getUser()['$id'])), + Permission::delete(Role::user($this->getUser()['$id'])), + ], $response['body']['rows'][1]['$permissions']); + + // TEST: Fail - Can't bulk upsert in a collection with relationships + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Bulk Related', + 'rowSecurity' => true, + 'permissions' => [], + ]); + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], $this->getHeaders()), [ + 'relatedTableId' => $collection2['body']['$id'], + 'type' => 'manyToOne', + 'twoWay' => true, + 'onDelete' => 'cascade', + 'key' => 'level2', + 'twoWayKey' => 'level1' + ]); + + $this->assertEquals(202, $response['headers']['status-code']); + + sleep(1); + + $response = $this->client->call(Client::METHOD_PUT, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rows' => [ + [ + '$id' => '1', + 'number' => 1000, + ], + ], + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } + + public function testBulkDelete(): void + { + // Create database + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'Bulk Deletes' + ]); + + $this->assertNotEmpty($database['body']['$id']); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Bulk Deletes', + 'rowSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $data = [ + '$id' => $collection['body']['$id'], + 'databaseId' => $collection['body']['databaseId'] + ]; + + // Await attribute + $numberAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'number', + 'required' => true, + ]); + + $this->assertEquals(202, $numberAttribute['headers']['status-code']); + + // wait for database worker to create attributes + sleep(2); + + // Create documents + $createBulkDocuments = function ($amount = 11) use ($data) { + $documents = []; + + for ($x = 0; $x < $amount; $x++) { + $documents[] = [ + '$id' => ID::unique(), + 'number' => $x, + ]; + } + + $doc = $this->client->call(Client::METHOD_POST, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rows' => $documents, + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + }; + + $createBulkDocuments(); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(11, $documents['body']['total']); + + // TEST: Delete all documents + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(11, $response['body']['total']); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(0, $documents['body']['total']); + + // TEST: Delete documents with query + $createBulkDocuments(); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(11, $documents['body']['total']); + + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::lessThan('number', 5)->toString(), + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(5, $response['body']['total']); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(6, $documents['body']['total']); + + foreach ($documents['body']['rows'] as $document) { + $this->assertGreaterThanOrEqual(5, $document['number']); + } + + // Cleanup + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(6, $response['body']['total']); + + // SUCCESS: Delete documents with query + $createBulkDocuments(); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(11, $documents['body']['total']); + + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::lessThan('number', 5)->toString(), + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(5, $response['body']['total']); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(6, $documents['body']['total']); + + // Cleanup + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(6, $response['body']['total']); + + // SUCCESS: Delete Documents with limit query + $createBulkDocuments(); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(11, $documents['body']['total']); + + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::limit(2)->toString(), + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(2, $response['body']['total']); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(9, $documents['body']['total']); + + // Cleanup + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(9, $response['body']['total']); + + // SUCCESS: Delete Documents with offset query + $createBulkDocuments(); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(11, $documents['body']['total']); + + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::offset(5)->toString(), + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(6, $response['body']['total']); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(5, $documents['body']['total']); + + $lastDoc = end($documents['body']['rows']); + + $this->assertNotEmpty($lastDoc); + $this->assertEquals(4, $lastDoc['number']); + + // Cleanup + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(5, $response['body']['total']); + + // SUCCESS: Delete 100 documents + $createBulkDocuments(100); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(100, $documents['body']['total']); + + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(100, $response['body']['total']); + + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(0, $documents['body']['total']); + + // TEST: Fail - Can't bulk delete in a collection with relationships + $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'Bulk Related', + 'rowSecurity' => true, + 'permissions' => [], + ]); + + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], $this->getHeaders()), [ + 'relatedTableId' => $collection2['body']['$id'], + 'type' => 'manyToOne', + 'twoWay' => true, + 'onDelete' => 'cascade', + 'key' => 'level2', + 'twoWayKey' => 'level1' + ]); + + $this->assertEquals(202, $response['headers']['status-code']); + + sleep(1); + + $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(400, $response['headers']['status-code']); + } } From 58e878653e105c724415d3dd2f04000a46d05f00 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 20:00:53 +0530 Subject: [PATCH 162/343] =?UTF-8?q?fix:=20one=20more=20test=20before=20I?= =?UTF-8?q?=20sign=20out=20=F0=9F=91=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Modules/Databases/Http/Databases/Tables/Rows/Create.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php index 81d90a7708..5af7fe5dc2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php @@ -98,7 +98,7 @@ class Create extends DocumentCreate ) ]) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('rowId', '', new CustomId(), 'Row ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') + ->param('rowId', '', new CustomId(), 'Row ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', true) ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define columns before creating rows.') ->param('data', [], new JSON(), 'Row data as JSON object.') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) From 018aad5339e73559ac78e9f2604a135c4bd048af Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 20:03:41 +0530 Subject: [PATCH 163/343] fix: one more test... --- app/controllers/api/databases.php | 0 .../Modules/Databases/Http/Databases/Tables/Rows/Create.php | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 app/controllers/api/databases.php diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php index 5af7fe5dc2..881d2b28ed 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php @@ -100,7 +100,7 @@ class Create extends DocumentCreate ->param('databaseId', '', new UID(), 'Database ID.') ->param('rowId', '', new CustomId(), 'Row ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', true) ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define columns before creating rows.') - ->param('data', [], new JSON(), 'Row data as JSON object.') + ->param('data', [], new JSON(), 'Row data as JSON object.', true) ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('rows', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of documents data as JSON objects.', true, ['plan']) ->inject('response') From 5f8c811f15837f4db680f2813c9fc16997f86672 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 13 Jun 2025 10:08:07 +0530 Subject: [PATCH 164/343] fix: missing context. --- .../Databases/Http/Databases/Tables/Rows/Bulk/Update.php | 3 +++ .../Databases/Http/Databases/Tables/Rows/Column/Decrement.php | 3 +++ .../Databases/Http/Databases/Tables/Rows/Column/Increment.php | 3 +++ 3 files changed, 9 insertions(+) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php index 53e7c3c152..1b9ddb60ab 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Bulk; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Update as DocumentsUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -31,6 +32,8 @@ class Update extends DocumentsUpdate public function __construct() { + $this->setContext(Context::DATABASE_ROWS); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php index 5b2cf17f91..128d578cde 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Column; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Attribute\Decrement as DecrementDocumentAttribute; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -30,6 +31,8 @@ class Decrement extends DecrementDocumentAttribute public function __construct() { + $this->setContext(Context::DATABASE_ROWS); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId/:column/decrement') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php index 4dcd05cc25..a3e256d561 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Column; +use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Attribute\Increment as IncrementDocumentAttribute; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -30,6 +31,8 @@ class Increment extends IncrementDocumentAttribute public function __construct() { + $this->setContext(Context::DATABASE_ROWS); + $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId/:column/increment') From 44870b9810b3d7c2a63e58d710b099ff3c0f44c0 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 13 Jun 2025 10:26:05 +0530 Subject: [PATCH 165/343] fix: pending tests. --- .github/workflows/tests.yml | 6 +- .../Databases/Tables/DatabasesBase.php | 154 +++++++++--------- .../Tables/DatabasesPermissionsGuestTest.php | 84 +++++----- .../Tables/DatabasesPermissionsMemberTest.php | 10 +- .../Tables/DatabasesPermissionsTeamTest.php | 62 +++---- 5 files changed, 159 insertions(+), 157 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 97f3696e67..cf1e55f7ec 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -145,7 +145,8 @@ jobs: Account, Avatars, Console, - Databases, + Databases/Collections, + Databases/Tables, Functions, FunctionsSchedule, GraphQL, @@ -213,7 +214,8 @@ jobs: Account, Avatars, Console, - Databases, + Databases/Collections, + Databases/Tables, Functions, FunctionsSchedule, GraphQL, diff --git a/tests/e2e/Services/Databases/Tables/DatabasesBase.php b/tests/e2e/Services/Databases/Tables/DatabasesBase.php index a0b6be2fbe..12426d78b2 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesBase.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesBase.php @@ -1437,7 +1437,7 @@ trait DatabasesBase ], [ 'key' => 'lengthTestIndex', 'type' => 'key', - 'attributes' => ['title','description'], + 'columns' => ['title','description'], 'lengths' => [128,200] ]); $this->assertEquals(202, $create['headers']['status-code']); @@ -1461,7 +1461,7 @@ trait DatabasesBase ], [ 'key' => 'lengthOverrideTestIndex', 'type' => 'key', - 'attributes' => ['actors'], + 'columns' => ['actors'], 'lengths' => [120] ]); $this->assertEquals(202, $create['headers']['status-code']); @@ -1481,7 +1481,7 @@ trait DatabasesBase ], [ 'key' => 'lengthCountExceededIndex', 'type' => 'key', - 'attributes' => ['title'], + 'columns' => ['title'], 'lengths' => [128, 128] ]); $this->assertEquals(400, $create['headers']['status-code']); @@ -1494,7 +1494,7 @@ trait DatabasesBase ], [ 'key' => 'lengthTooLargeIndex', 'type' => 'key', - 'attributes' => ['title','description','tagline','actors'], + 'columns' => ['title','description','tagline','actors'], 'lengths' => [256,256,256,20] ]); @@ -1508,7 +1508,7 @@ trait DatabasesBase ], [ 'key' => 'negativeLengthIndex', 'type' => 'key', - 'attributes' => ['title'], + 'columns' => ['title'], 'lengths' => [-1] ]); $this->assertEquals(400, $create['headers']['status-code']); @@ -1679,12 +1679,6 @@ trait DatabasesBase $this->assertEquals(400, $row4['headers']['status-code']); - // Delete document 4 with incomplete path - $this->assertEquals(404, $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()))['headers']['status-code']); - return $data; } @@ -1695,7 +1689,7 @@ trait DatabasesBase { $databaseId = $data['databaseId']; $rowId = ID::unique(); - $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + $row = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1710,16 +1704,16 @@ trait DatabasesBase ], ]); - $this->assertEquals(200, $document['headers']['status-code']); - $this->assertCount(3, $document['body']['$permissions']); - $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertCount(3, $row['body']['$permissions']); + $row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals('Thor: Ragnarok', $document['body']['title']); + $this->assertEquals('Thor: Ragnarok', $row['body']['title']); - $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + $row = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1734,18 +1728,18 @@ trait DatabasesBase ], ]); - $this->assertEquals(200, $document['headers']['status-code']); - $this->assertEquals('Thor: Love and Thunder', $document['body']['title']); + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals('Thor: Love and Thunder', $row['body']['title']); - $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + $row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals('Thor: Love and Thunder', $document['body']['title']); + $this->assertEquals('Thor: Love and Thunder', $row['body']['title']); // removing permission to read and delete - $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + $row = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1758,30 +1752,30 @@ trait DatabasesBase ], ]); // shouldn't be able to read as no read permission - $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + $row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); switch ($this->getSide()) { case 'client': - $this->assertEquals(404, $document['headers']['status-code']); + $this->assertEquals(404, $row['headers']['status-code']); break; case 'server': - $this->assertEquals(200, $document['headers']['status-code']); + $this->assertEquals(200, $row['headers']['status-code']); break; } // shouldn't be able to delete as no delete permission - $document = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + $row = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); // simulating for the client - // the document should not be allowed to be deleted as needed downward + // the row should not be allowed to be deleted as needed downward if ($this->getSide() === 'client') { - $this->assertEquals(401, $document['headers']['status-code']); + $this->assertEquals(401, $row['headers']['status-code']); } // giving the delete permission - $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + $row = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1795,11 +1789,12 @@ trait DatabasesBase Permission::delete(Role::users()) ], ]); - $document = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ + + $row = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $rowId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(204, $document['headers']['status-code']); + $this->assertEquals(204, $row['headers']['status-code']); // relationship behaviour $person = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ @@ -1815,7 +1810,7 @@ trait DatabasesBase Permission::delete(Role::users()), Permission::create(Role::users()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $person['headers']['status-code']); @@ -1833,7 +1828,7 @@ trait DatabasesBase Permission::create(Role::users()), Permission::delete(Role::users()), ], - 'documentSecurity' => true, + 'rowSecurity' => true, ]); $this->assertEquals(201, $library['headers']['status-code']); @@ -1855,7 +1850,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'relatedtableId' => 'library-upsert', + 'relatedTableId' => 'library-upsert', 'type' => Database::RELATION_ONE_TO_ONE, 'key' => 'library', 'twoWay' => true, @@ -1903,7 +1898,7 @@ trait DatabasesBase ]); $this->assertEquals('Library 1', $person1['body']['library']['libraryName']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/documents', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1913,8 +1908,8 @@ trait DatabasesBase ], ]); - $this->assertEquals(1, $documents['body']['total']); - $this->assertEquals('Library 1', $documents['body']['documents'][0]['library']['libraryName']); + $this->assertEquals(1, $rows['body']['total']); + $this->assertEquals('Library 1', $rows['body']['rows'][0]['library']['libraryName']); $person1 = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/rows/'.$rowId, array_merge([ @@ -1941,7 +1936,7 @@ trait DatabasesBase // data should get updated $this->assertEquals('Library 2', $person1['body']['library']['libraryName']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/documents', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1951,9 +1946,8 @@ trait DatabasesBase ], ]); - $this->assertEquals(1, $documents['body']['total']); - $this->assertEquals('Library 2', $documents['body']['documents'][0]['library']['libraryName']); - + $this->assertEquals(1, $rows['body']['total']); + $this->assertEquals('Library 2', $rows['body']['rows'][0]['library']['libraryName']); // data should get added $person1 = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/rows/'.ID::unique(), array_merge([ @@ -1979,7 +1973,8 @@ trait DatabasesBase ]); $this->assertEquals('Library 2', $person1['body']['library']['libraryName']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/documents', array_merge([ + + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $person['body']['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -1987,7 +1982,8 @@ trait DatabasesBase Query::select(['fullName', 'library.*'])->toString() ], ]); - $this->assertEquals(2, $documents['body']['total']); + + $this->assertEquals(2, $rows['body']['total']); } /** @@ -2044,6 +2040,7 @@ trait DatabasesBase 'default' => null, 'required' => false, ]); + // creating a dummy doc with null description $row1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ 'content-type' => 'application/json', @@ -2242,7 +2239,7 @@ trait DatabasesBase $this->assertCount(1, $rows['body']['rows']); /** - * Test after with unknown document. + * Test after with unknown row. */ $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ 'content-type' => 'application/json', @@ -3066,6 +3063,7 @@ trait DatabasesBase $this->assertEquals('Minimum value must be lesser than maximum value', $invalidRange['body']['message']); $this->assertEquals('Cannot set default value for array columns', $defaultArray['body']['message']); $this->assertEquals(400, $datetimeDefault['headers']['status-code']); + // wait for worker to add attributes sleep(3); @@ -3073,7 +3071,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], - ]), []); + ])); $this->assertCount(10, $table['body']['columns']); @@ -3387,6 +3385,8 @@ trait DatabasesBase $this->assertEquals(400, $tooHigh['headers']['status-code']); $this->assertEquals(400, $tooLow['headers']['status-code']); $this->assertEquals(400, $badTime['headers']['status-code']); + + // TODO: @itznotabug - database library needs to throw error based on context! $this->assertEquals('Invalid document structure: Attribute "email" has invalid format. Value must be a valid email address', $badEmail['body']['message']); $this->assertEquals('Invalid document structure: Attribute "enum" has invalid format. Value must be one of (yes, no, maybe)', $badEnum['body']['message']); $this->assertEquals('Invalid document structure: Attribute "ip" has invalid format. Value must be a valid IP address', $badIp['body']['message']); @@ -3457,7 +3457,7 @@ trait DatabasesBase $this->assertEquals($row['body']['releaseYear'], 1945); // This differs from the old permissions model because we don't inherit - // existing document permissions on update, unless none were supplied, + // existing row permissions on update, unless none were supplied, // so that specific types can be removed if wanted. $this->assertCount(2, $row['body']['$permissions']); $this->assertEquals([ @@ -3500,7 +3500,7 @@ trait DatabasesBase $this->assertCount(0, $row['body']['$permissions']); $this->assertEquals([], $row['body']['$permissions']); - // Check client side can no longer read the document. + // Check client side can no longer read the row. $row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -3644,7 +3644,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - // Current user has read permission on the collection so can get any document + // Current user has read permission on the table so can get any row $this->assertEquals(3, $rowsUser1['body']['total']); $this->assertCount(3, $rowsUser1['body']['rows']); @@ -3653,7 +3653,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - // Current user has read permission on the collection so can get any document + // Current user has read permission on the table so can get any row $this->assertEquals(200, $row3GetWithCollectionRead['headers']['status-code']); $email = uniqid() . 'user@localhost.test'; @@ -3686,7 +3686,7 @@ trait DatabasesBase 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); - // Current user has no collection permissions but has read permission for this document + // Current user has no table permissions but has read permission for this row $this->assertEquals(200, $row3GetWithDocumentRead['headers']['status-code']); $row2GetFailure = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row2['body']['$id'], [ @@ -3696,7 +3696,7 @@ trait DatabasesBase 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); - // Current user has no collection or document permissions for this document + // Current user has no table or row permissions for this row $this->assertEquals(404, $row2GetFailure['headers']['status-code']); $rowsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', [ @@ -3706,7 +3706,7 @@ trait DatabasesBase 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); - // Current user has no collection permissions but has read permission for one document + // Current user has no table permissions but has read permission for one row $this->assertEquals(1, $rowsUser2['body']['total']); $this->assertCount(1, $rowsUser2['body']['rows']); } @@ -3832,7 +3832,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - // Current user has read permission on the collection so can get any document + // Current user has read permission on the table so can get any row $this->assertEquals(3, $rowsUser1['body']['total']); $this->assertCount(3, $rowsUser1['body']['rows']); @@ -3841,7 +3841,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - // Current user has read permission on the collection so can get any document + // Current user has read permission on the table so can get any row $this->assertEquals(200, $row3GetWithCollectionRead['headers']['status-code']); $email = uniqid() . 'user2@localhost.test'; @@ -3874,7 +3874,7 @@ trait DatabasesBase 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); - // other2 has no collection permissions and document permissions are disabled + // other2 has no table permissions and row permissions are disabled $this->assertEquals(404, $row3GetWithDocumentRead['headers']['status-code']); $rowsUser2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', [ @@ -3884,11 +3884,11 @@ trait DatabasesBase 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); - // other2 has no collection permissions and document permissions are disabled + // other2 has no table permissions and row permissions are disabled $this->assertEquals(401, $rowsUser2['headers']['status-code']); - // Enable document permissions - $table = $this->client->call(CLient::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $tableId, [ + // Enable row permissions + $this->client->call(CLient::METHOD_PUT, '/databases/' . $databaseId . '/tables/' . $tableId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -3904,7 +3904,7 @@ trait DatabasesBase 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session2, ]); - // Current user has no collection permissions read access to one document + // Current user has no table permissions read access to one row $this->assertEquals(1, $rowsUser2['body']['total']); $this->assertCount(1, $rowsUser2['body']['rows']); } @@ -3952,7 +3952,7 @@ trait DatabasesBase $this->assertEquals(409, $duplicate['headers']['status-code']); - // Test for exception when updating document to conflict + // Test for exception when updating row to conflict $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -3975,7 +3975,7 @@ trait DatabasesBase $this->assertEquals(201, $row['headers']['status-code']); - // Test for exception when updating document to conflict + // Test for exception when updating row to conflict $duplicate = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows/' . $row['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4078,7 +4078,7 @@ trait DatabasesBase $databaseId = $database['body']['$id']; - // Create collection + // Create table $movies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4116,7 +4116,7 @@ trait DatabasesBase // wait for database worker to create attributes sleep(2); - // add document + // add row $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $moviesId . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4171,7 +4171,7 @@ trait DatabasesBase $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $row['body']['$permissions']); } - // remove collection + // remove table $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $moviesId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4624,7 +4624,7 @@ trait DatabasesBase { $databaseId = $data['databaseId']; - // Create album collection + // Create album table $albums = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4650,7 +4650,7 @@ trait DatabasesBase 'required' => true, ]); - // Create artist collection + // Create artist table $artists = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4768,7 +4768,7 @@ trait DatabasesBase { $databaseId = $data['databaseId']; - // Create sports collection + // Create sports table $sports = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4794,7 +4794,7 @@ trait DatabasesBase 'required' => true, ]); - // Create player collection + // Create player table $players = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -5326,20 +5326,20 @@ trait DatabasesBase ]); $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'tableId' => ID::unique(), 'name' => 'CounterCollection', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), ], ]); - $tableId = $collection['body']['$id']; + $tableId = $table['body']['$id']; // Add integer attribute $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ @@ -5353,7 +5353,7 @@ trait DatabasesBase \sleep(3); - // Create document with initial count = 5 + // Create row with initial count = 5 $doc = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -5430,21 +5430,21 @@ trait DatabasesBase $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'tableId' => ID::unique(), 'name' => 'CounterCollection', - 'documentSecurity' => true, + 'rowSecurity' => true, 'permissions' => [ Permission::create(Role::user($this->getUser()['$id'])), Permission::read(Role::user($this->getUser()['$id'])), ], ]); - $tableId = $collection['body']['$id']; + $tableId = $table['body']['$id']; // Add integer attribute $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ @@ -5458,8 +5458,8 @@ trait DatabasesBase \sleep(2); - // Create document with initial count = 10 - $doc = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/documents', array_merge([ + // Create row with initial count = 10 + $doc = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ diff --git a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsGuestTest.php index fde6041219..f404cc1bd5 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsGuestTest.php @@ -17,7 +17,7 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; - public function createCollection(): array + public function createTable(): array { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -25,10 +25,10 @@ class DatabasesPermissionsGuestTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), - 'name' => 'InvalidDocumentDatabase', + 'name' => 'InvalidRowDatabase', ]); $this->assertEquals(201, $database['headers']['status-code']); - $this->assertEquals('InvalidDocumentDatabase', $database['body']['name']); + $this->assertEquals('InvalidRowDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; $publicMovies = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', $this->getServerHeader(), [ @@ -48,15 +48,15 @@ class DatabasesPermissionsGuestTest extends Scope 'rowSecurity' => true, ]); - $publicCollection = ['id' => $publicMovies['body']['$id']]; - $privateCollection = ['id' => $privateMovies['body']['$id']]; + $publicTable = ['id' => $publicMovies['body']['$id']]; + $privateTable = ['id' => $privateMovies['body']['$id']]; - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $publicCollection['id'] . '/columns/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $publicTable['id'] . '/columns/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, ]); - $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $privateCollection['id'] . '/columns/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $privateTable['id'] . '/columns/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -66,8 +66,8 @@ class DatabasesPermissionsGuestTest extends Scope return [ 'databaseId' => $databaseId, - 'publicCollectionId' => $publicCollection['id'], - 'privateCollectionId' => $privateCollection['id'], + 'publicTableId' => $publicTable['id'], + 'privateTableId' => $privateTable['id'], ]; } @@ -86,21 +86,21 @@ class DatabasesPermissionsGuestTest extends Scope /** * @dataProvider permissionsProvider */ - public function testReadDocuments($permissions) + public function testReadRows($permissions) { - $data = $this->createCollection(); - $publicCollectionId = $data['publicCollectionId']; - $privateCollectionId = $data['privateCollectionId']; + $data = $this->createTable(); + $publicTableId = $data['publicTableId']; + $privateTableId = $data['privateTableId']; $databaseId = $data['databaseId']; - $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $publicCollectionId . '/rows', $this->getServerHeader(), [ + $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $publicTableId . '/rows', $this->getServerHeader(), [ 'rowId' => ID::unique(), 'data' => [ 'title' => 'Lorem', ], 'permissions' => $permissions, ]); - $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $privateCollectionId . '/rows', $this->getServerHeader(), [ + $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $privateTableId . '/rows', $this->getServerHeader(), [ 'rowId' => ID::unique(), 'data' => [ 'title' => 'Lorem', @@ -114,23 +114,23 @@ class DatabasesPermissionsGuestTest extends Scope $roles = Authorization::getRoles(); Authorization::cleanRoles(); - $publicDocuments = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $publicCollectionId . '/rows', [ + $publicRows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $publicTableId . '/rows', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); - $privateDocuments = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $privateCollectionId . '/rows', [ + $privateRows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $privateTableId . '/rows', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); - $this->assertEquals(1, $publicDocuments['body']['total']); - $this->assertEquals($permissions, $publicDocuments['body']['rows'][0]['$permissions']); + $this->assertEquals(1, $publicRows['body']['total']); + $this->assertEquals($permissions, $publicRows['body']['rows'][0]['$permissions']); if (\in_array(Permission::read(Role::any()), $permissions)) { - $this->assertEquals(1, $privateDocuments['body']['total']); - $this->assertEquals($permissions, $privateDocuments['body']['rows'][0]['$permissions']); + $this->assertEquals(1, $privateRows['body']['total']); + $this->assertEquals($permissions, $privateRows['body']['rows'][0]['$permissions']); } else { - $this->assertEquals(0, $privateDocuments['body']['total']); + $this->assertEquals(0, $privateRows['body']['total']); } foreach ($roles as $role) { @@ -138,17 +138,17 @@ class DatabasesPermissionsGuestTest extends Scope } } - public function testWriteDocument() + public function testWriteRow() { - $data = $this->createCollection(); - $publicCollectionId = $data['publicCollectionId']; - $privateCollectionId = $data['privateCollectionId']; + $data = $this->createTable(); + $publicTableId = $data['publicTableId']; + $privateTableId = $data['privateTableId']; $databaseId = $data['databaseId']; $roles = Authorization::getRoles(); Authorization::cleanRoles(); - $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $publicCollectionId . '/rows', [ + $publicResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $publicTableId . '/rows', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -158,10 +158,10 @@ class DatabasesPermissionsGuestTest extends Scope ] ]); - $publicDocumentId = $publicResponse['body']['$id']; + $publicRowId = $publicResponse['body']['$id']; $this->assertEquals(201, $publicResponse['headers']['status-code']); - $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $privateCollectionId . '/rows', [ + $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $privateTableId . '/rows', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -173,8 +173,8 @@ class DatabasesPermissionsGuestTest extends Scope $this->assertEquals(401, $privateResponse['headers']['status-code']); - // Create a document in private collection with API key so we can test that update and delete are also not allowed - $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $privateCollectionId . '/rows', $this->getServerHeader(), [ + // Create a row in private collection with API key so we can test that update and delete are also not allowed + $privateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $privateTableId . '/rows', $this->getServerHeader(), [ 'rowId' => ID::unique(), 'data' => [ 'title' => 'Lorem', @@ -182,9 +182,9 @@ class DatabasesPermissionsGuestTest extends Scope ]); $this->assertEquals(201, $privateResponse['headers']['status-code']); - $privateDocumentId = $privateResponse['body']['$id']; + $privateRowId = $privateResponse['body']['$id']; - $publicDocument = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $publicCollectionId . '/rows/' . $publicDocumentId, [ + $publicRow = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $publicTableId . '/rows/' . $publicRowId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -193,10 +193,10 @@ class DatabasesPermissionsGuestTest extends Scope ], ]); - $this->assertEquals(200, $publicDocument['headers']['status-code']); - $this->assertEquals('Thor: Ragnarok', $publicDocument['body']['title']); + $this->assertEquals(200, $publicRow['headers']['status-code']); + $this->assertEquals('Thor: Ragnarok', $publicRow['body']['title']); - $privateDocument = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $privateCollectionId . '/rows/' . $privateDocumentId, [ + $privateRow = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $privateTableId . '/rows/' . $privateRowId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -205,28 +205,28 @@ class DatabasesPermissionsGuestTest extends Scope ], ]); - $this->assertEquals(401, $privateDocument['headers']['status-code']); + $this->assertEquals(401, $privateRow['headers']['status-code']); - $publicDocument = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $publicCollectionId . '/rows/' . $publicDocumentId, [ + $publicRow = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $publicTableId . '/rows/' . $publicRowId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); - $this->assertEquals(204, $publicDocument['headers']['status-code']); + $this->assertEquals(204, $publicRow['headers']['status-code']); - $privateDocument = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $privateCollectionId . '/rows/' . $privateDocumentId, [ + $privateRow = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $privateTableId . '/rows/' . $privateRowId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]); - $this->assertEquals(401, $privateDocument['headers']['status-code']); + $this->assertEquals(401, $privateRow['headers']['status-code']); foreach ($roles as $role) { Authorization::setRole($role); } } - public function testWriteDocumentWithPermissions() + public function testWriteRowWithPermissions() { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php index 32a97aeadf..f1e5c35482 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsMemberTest.php @@ -168,7 +168,7 @@ class DatabasesPermissionsMemberTest extends Scope $doconly = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', $this->getServerHeader(), [ 'tableId' => ID::unique(), - 'name' => 'Document Only Movies', + 'name' => 'Row Only Movies', 'permissions' => [], 'rowSecurity' => true, ]); @@ -196,7 +196,7 @@ class DatabasesPermissionsMemberTest extends Scope * @dataProvider permissionsProvider * @depends testSetupDatabase */ - public function testReadDocuments($permissions, $anyCount, $usersCount, $docOnlyCount, $data) + public function testReadRows($permissions, $anyCount, $usersCount, $docOnlyCount, $data) { $users = $data['users']; $tables = $data['tables']; @@ -230,7 +230,7 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); /** - * Check "any" permission collection + * Check "any" permission table */ $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tables['public'] . '/rows', [ 'origin' => 'http://localhost', @@ -243,7 +243,7 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals($anyCount, $rows['body']['total']); /** - * Check "users" permission collection + * Check "users" permission table */ $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tables['private'] . '/rows', [ 'origin' => 'http://localhost', @@ -256,7 +256,7 @@ class DatabasesPermissionsMemberTest extends Scope $this->assertEquals($usersCount, $rows['body']['total']); /** - * Check "user:user1" document only permission collection + * Check "user:user1" row only permission table */ $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tables['doconly'] . '/rows', [ 'origin' => 'http://localhost', diff --git a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsTeamTest.php b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsTeamTest.php index c62583f76c..406ca79371 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesPermissionsTeamTest.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesPermissionsTeamTest.php @@ -36,7 +36,7 @@ class DatabasesPermissionsTeamTest extends Scope ]; } - public function createCollections($teams) + public function createTables($teams) { $db = $this->client->call(Client::METHOD_POST, '/databases', $this->getServerHeader(), [ 'databaseId' => $this->databaseId, @@ -45,8 +45,8 @@ class DatabasesPermissionsTeamTest extends Scope $this->assertEquals(201, $db['headers']['status-code']); $table1 = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables', $this->getServerHeader(), [ - 'tableId' => ID::custom('collection1'), - 'name' => 'Collection 1', + 'tableId' => ID::custom('table1'), + 'name' => 'Table 1', 'permissions' => [ Permission::read(Role::team($teams['team1']['$id'])), Permission::create(Role::team($teams['team1']['$id'], 'admin')), @@ -55,17 +55,17 @@ class DatabasesPermissionsTeamTest extends Scope ], ]); - $this->collections['collection1'] = $table1['body']['$id']; + $this->tables['table1'] = $table1['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $this->collections['collection1'] . '/columns/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $this->tables['table1'] . '/columns/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, ]); $table2 = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables', $this->getServerHeader(), [ - 'tableId' => ID::custom('collection2'), - 'name' => 'Collection 2', + 'tableId' => ID::custom('table2'), + 'name' => 'Table 2', 'permissions' => [ Permission::read(Role::team($teams['team2']['$id'])), Permission::create(Role::team($teams['team2']['$id'], 'owner')), @@ -74,9 +74,9 @@ class DatabasesPermissionsTeamTest extends Scope ] ]); - $this->collections['collection2'] = $table2['body']['$id']; + $this->tables['table2'] = $table2['body']['$id']; - $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $this->collections['collection2'] . '/columns/string', $this->getServerHeader(), [ + $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $this->tables['table2'] . '/columns/string', $this->getServerHeader(), [ 'key' => 'title', 'size' => 256, 'required' => true, @@ -84,22 +84,22 @@ class DatabasesPermissionsTeamTest extends Scope sleep(2); - return $this->collections; + return $this->tables; } /* * $success = can $user read from $table * [$user, $table, $success] */ - public function readDocumentsProvider(): array + public function readRowsProvider(): array { return [ - ['user1', 'collection1', true], - ['user2', 'collection1', false], - ['user3', 'collection1', true], - ['user1', 'collection2', false], - ['user2', 'collection2', true], - ['user3', 'collection2', true], + ['user1', 'table1', true], + ['user2', 'table1', false], + ['user3', 'table1', true], + ['user1', 'table2', false], + ['user2', 'table2', true], + ['user3', 'table2', true], ]; } @@ -107,15 +107,15 @@ class DatabasesPermissionsTeamTest extends Scope * $success = can $user write to $table * [$user, $table, $success] */ - public function writeDocumentsProvider(): array + public function writeRowsProvider(): array { return [ - ['user1', 'collection1', true], - ['user2', 'collection1', false], - ['user3', 'collection1', false], - ['user1', 'collection2', false], - ['user2', 'collection2', true], - ['user3', 'collection2', false], + ['user1', 'table1', true], + ['user2', 'table1', false], + ['user3', 'table1', false], + ['user1', 'table2', false], + ['user2', 'table2', true], + ['user3', 'table2', false], ]; } @@ -138,9 +138,9 @@ class DatabasesPermissionsTeamTest extends Scope $this->addToTeam('user3', 'team1'); $this->addToTeam('user3', 'team2'); - $this->createCollections($this->teams); + $this->createTables($this->teams); - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $this->collections['collection1'] . '/rows', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $this->tables['table1'] . '/rows', $this->getServerHeader(), [ 'rowId' => ID::unique(), 'data' => [ 'title' => 'Lorem', @@ -148,7 +148,7 @@ class DatabasesPermissionsTeamTest extends Scope ]); $this->assertEquals(201, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $this->collections['collection2'] . '/rows', $this->getServerHeader(), [ + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $this->tables['table2'] . '/rows', $this->getServerHeader(), [ 'rowId' => ID::unique(), 'data' => [ 'title' => 'Ipsum', @@ -162,9 +162,9 @@ class DatabasesPermissionsTeamTest extends Scope /** * Data provider params are passed before test dependencies * @depends testSetupDatabase - * @dataProvider readDocumentsProvider + * @dataProvider readRowsProvider */ - public function testReadDocuments($user, $table, $success, $users) + public function testReadRows($user, $table, $success, $users) { $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $this->databaseId . '/tables/' . $table . '/rows', [ 'origin' => 'http://localhost', @@ -182,9 +182,9 @@ class DatabasesPermissionsTeamTest extends Scope /** * @depends testSetupDatabase - * @dataProvider writeDocumentsProvider + * @dataProvider writeRowsProvider */ - public function testWriteDocuments($user, $table, $success, $users) + public function testWriteRows($user, $table, $success, $users) { $rows = $this->client->call(Client::METHOD_POST, '/databases/' . $this->databaseId . '/tables/' . $table . '/rows', [ 'origin' => 'http://localhost', From a13a6a6913d4e098d0cec8e6f353135e434a4bea Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 13 Jun 2025 11:06:51 +0530 Subject: [PATCH 166/343] update: naming convention for table tests. --- .../Tables/DatabasesCustomServerTest.php | 858 +++++++++--------- 1 file changed, 429 insertions(+), 429 deletions(-) diff --git a/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php index e2aebf4969..710b167b64 100644 --- a/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/Tables/DatabasesCustomServerTest.php @@ -239,7 +239,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - // This collection already exists + // This database already exists $response = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -325,7 +325,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEquals("", $response['body']); - // Try to get the collection and check if it has been deleted + // Try to get the database and check if it has been deleted $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'] @@ -334,7 +334,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(404, $response['headers']['status-code']); } - public function testListCollections(): array + public function testListTables(): array { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -342,10 +342,10 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), - 'name' => 'invalidDocumentDatabase', + 'name' => 'invalidRowDatabase', ]); $this->assertEquals(201, $database['headers']['status-code']); - $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); + $this->assertEquals('invalidRowDatabase', $database['body']['name']); $this->assertTrue($database['body']['enabled']); $databaseId = $database['body']['$id']; @@ -572,7 +572,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - // This collection already exists + // This table already exists $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -597,9 +597,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testListCollections + * @depends testListTables */ - public function testGetCollection(array $data): void + public function testGetTable(array $data): void { $databaseId = $data['databaseId']; $tableId = $data['tableId']; @@ -617,9 +617,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testListCollections + * @depends testListTables */ - public function testUpdateCollection(array $data) + public function testUpdateTable(array $data) { $databaseId = $data['databaseId']; $tableId = $data['tableId']; @@ -640,9 +640,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testListCollections + * @depends testListTables */ - public function testCreateEncryptedAttribute(array $data): void + public function testCreateEncryptedColumn(array $data): void { $databaseId = $data['databaseId']; @@ -651,7 +651,7 @@ class DatabasesCustomServerTest extends Scope * Test for SUCCESS */ - // Create collection + // Create table $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -669,10 +669,10 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(201, $actors['headers']['status-code']); - $this->assertEquals($actors['body']['name'], 'Encrypted Actors Data'); + $this->assertEquals('Encrypted Actors Data', $actors['body']['name']); /** - * Test for creating encrypted attributes + * Test for creating encrypted columns */ $columnsPath = '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/columns'; @@ -700,7 +700,7 @@ class DatabasesCustomServerTest extends Scope /** - * Check status of every attribute + * Check status of every column */ $this->assertEquals(202, $firstName['headers']['status-code']); $this->assertEquals('firstName', $firstName['body']['key']); @@ -710,10 +710,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals('lastName', $lastName['body']['key']); $this->assertEquals('string', $lastName['body']['type']); - // Wait for database worker to finish creating attributes + // Wait for database worker to finish creating columns sleep(2); - // Creating document to ensure cache is purged on schema change + // Creating row to ensure cache is purged on schema change $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -731,7 +731,7 @@ class DatabasesCustomServerTest extends Scope ], ]); - // Check document to ensure cache is purged on schema change + // Check row to ensure cache is purged on schema change $row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/rows/' . $row['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -743,7 +743,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals('Jameson', $row['body']['lastName']); } - public function testDeleteAttribute(): array + public function testDeleteColumn(): array { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -751,17 +751,17 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), - 'name' => 'invalidDocumentDatabase', + 'name' => 'invalidRowDatabase', ]); $this->assertEquals(201, $database['headers']['status-code']); - $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); + $this->assertEquals('invalidRowDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; /** * Test for SUCCESS */ - // Create collection + // Create table $actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -811,10 +811,10 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - // Wait for database worker to finish creating attributes + // Wait for database worker to finish creating columns sleep(2); - // Creating document to ensure cache is purged on schema change + // Creating row to ensure cache is purged on schema change $row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -865,7 +865,7 @@ class DatabasesCustomServerTest extends Scope $this->assertCount(1, $table['body']['indexes']); $this->assertEquals($table['body']['indexes'][0]['key'], $index['body']['key']); - // Delete attribute + // Delete column $column = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/columns/' . $unneededId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -876,7 +876,7 @@ class DatabasesCustomServerTest extends Scope sleep(2); - // Check document to ensure cache is purged on schema change + // Check row to ensure cache is purged on schema change $row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/rows/' . $row['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -905,7 +905,7 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testDeleteAttribute + * @depends testDeleteColumn */ public function testDeleteIndex($data): array { @@ -935,7 +935,7 @@ class DatabasesCustomServerTest extends Scope /** * @depends testDeleteIndex */ - public function testDeleteIndexOnDeleteAttribute($data) + public function testDeleteIndexOnDeleteColumn($data) { $databaseId = $data['databaseId']; $column1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/string', array_merge([ @@ -943,7 +943,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'key' => 'attribute1', + 'key' => 'column1', 'size' => 16, 'required' => true, ]); @@ -953,15 +953,15 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'key' => 'attribute2', + 'key' => 'column2', 'size' => 16, 'required' => true, ]); $this->assertEquals(202, $column1['headers']['status-code']); $this->assertEquals(202, $column2['headers']['status-code']); - $this->assertEquals('attribute1', $column1['body']['key']); - $this->assertEquals('attribute2', $column2['body']['key']); + $this->assertEquals('column1', $column1['body']['key']); + $this->assertEquals('column2', $column2['body']['key']); sleep(2); @@ -972,7 +972,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'index1', 'type' => 'key', - 'columns' => ['attribute1', 'attribute2'], + 'columns' => ['column1', 'column2'], 'orders' => ['ASC', 'ASC'], ]); @@ -983,7 +983,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'index2', 'type' => 'key', - 'columns' => ['attribute2'], + 'columns' => ['column2'], ]); $this->assertEquals(202, $index1['headers']['status-code']); @@ -993,7 +993,7 @@ class DatabasesCustomServerTest extends Scope sleep(2); - // Expected behavior: deleting attribute2 will cause index2 to be dropped, and index1 rebuilt with a single key + // Expected behavior: deleting column2 will cause index2 to be dropped, and index1 rebuilt with a single key $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/' . $column2['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1019,7 +1019,7 @@ class DatabasesCustomServerTest extends Scope $this->assertCount(1, $table['body']['indexes'][0]['columns']); $this->assertEquals($column1['body']['key'], $table['body']['indexes'][0]['columns'][0]); - // Delete attribute + // Delete column $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/' . $column1['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1031,7 +1031,7 @@ class DatabasesCustomServerTest extends Scope return $data; } - public function testCleanupDuplicateIndexOnDeleteAttribute() + public function testCleanupDuplicateIndexOnDeleteColumn() { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -1039,10 +1039,10 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), - 'name' => 'invalidDocumentDatabase', + 'name' => 'invalidRowDatabase', ]); $this->assertEquals(201, $database['headers']['status-code']); - $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); + $this->assertEquals('invalidRowDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ @@ -1051,7 +1051,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'tableId' => ID::unique(), - 'name' => 'TestCleanupDuplicateIndexOnDeleteAttribute', + 'name' => 'TestCleanupDuplicateIndexOnDeleteColumn', 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), @@ -1071,7 +1071,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'key' => 'attribute1', + 'key' => 'column1', 'size' => 16, 'required' => true, ]); @@ -1081,15 +1081,15 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'key' => 'attribute2', + 'key' => 'column2', 'size' => 16, 'required' => true, ]); $this->assertEquals(202, $column1['headers']['status-code']); $this->assertEquals(202, $column2['headers']['status-code']); - $this->assertEquals('attribute1', $column1['body']['key']); - $this->assertEquals('attribute2', $column2['body']['key']); + $this->assertEquals('column1', $column1['body']['key']); + $this->assertEquals('column2', $column2['body']['key']); sleep(2); @@ -1100,7 +1100,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'index1', 'type' => 'key', - 'columns' => ['attribute1', 'attribute2'], + 'columns' => ['column1', 'column2'], 'orders' => ['ASC', 'ASC'], ]); @@ -1111,7 +1111,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'index2', 'type' => 'key', - 'columns' => ['attribute2'], + 'columns' => ['column2'], ]); $this->assertEquals(202, $index1['headers']['status-code']); @@ -1121,7 +1121,7 @@ class DatabasesCustomServerTest extends Scope sleep(2); - // Expected behavior: deleting attribute1 would cause index1 to be a duplicate of index2 and automatically removed + // Expected behavior: deleting column1 would cause index1 to be a duplicate of index2 and automatically removed $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $column1['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1147,7 +1147,7 @@ class DatabasesCustomServerTest extends Scope $this->assertCount(1, $table['body']['indexes'][0]['columns']); $this->assertEquals($column2['body']['key'], $table['body']['indexes'][0]['columns'][0]); - // Delete attribute + // Delete column $deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $column2['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1158,14 +1158,14 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testDeleteIndexOnDeleteAttribute + * @depends testDeleteIndexOnDeleteColumn */ - public function testDeleteCollection($data) + public function testDeleteTable($data) { $databaseId = $data['databaseId']; $tableId = $data['tableId']; - // Add Documents to the collection + // Add Rows to the table $row1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1207,10 +1207,10 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(201, $row2['headers']['status-code']); $this->assertIsArray($row2['body']['$permissions']); $this->assertCount(3, $row2['body']['$permissions']); - $this->assertEquals($row2['body']['firstName'], 'Samuel'); - $this->assertEquals($row2['body']['lastName'], 'Jackson'); + $this->assertEquals('Samuel', $row2['body']['firstName']); + $this->assertEquals('Jackson', $row2['body']['lastName']); - // Delete the actors collection + // Delete the actors table $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1220,7 +1220,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEquals($response['body'], ""); - // Try to get the collection and check if it has been deleted + // Try to get the table and check if it has been deleted $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $tableId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'] @@ -1232,14 +1232,14 @@ class DatabasesCustomServerTest extends Scope /** * @throws Exception */ - public function testDeleteCollectionDeletesRelatedAttributes(): void + public function testDeleteTableDeletesRelatedColumns(): void { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'databaseId' => ID::unique(), - 'name' => 'TestDeleteCollectionDeletesRelatedAttributes', + 'name' => 'TestDeleteTableDeletesRelatedColumns', ]); $databaseId = $database['body']['$id']; @@ -1250,7 +1250,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'tableId' => ID::unique(), - 'name' => 'Collection1', + 'name' => 'Table1', 'rowSecurity' => false, 'permissions' => [], ]); @@ -1261,7 +1261,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'tableId' => ID::unique(), - 'name' => 'Collection2', + 'name' => 'Table2', 'rowSecurity' => false, 'permissions' => [], ]); @@ -1277,7 +1277,7 @@ class DatabasesCustomServerTest extends Scope 'relatedTableId' => $table2, 'type' => Database::RELATION_MANY_TO_ONE, 'twoWay' => false, - 'key' => 'collection2' + 'key' => 'table2' ]); sleep(2); @@ -1299,7 +1299,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(0, $columns['body']['total']); } - public function testAttributeRowWidthLimit() + public function testColumnRowWidthLimit() { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -1307,10 +1307,10 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), - 'name' => 'invalidDocumentDatabase', + 'name' => 'invalidRowDatabase', ]); $this->assertEquals(201, $database['headers']['status-code']); - $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); + $this->assertEquals('invalidRowDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ @@ -1318,8 +1318,8 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('attributeRowWidthLimit'), - 'name' => 'attributeRowWidthLimit', + 'tableId' => ID::custom('columnRowWidthLimit'), + 'name' => 'columnRowWidthLimit', 'permissions' => [ Permission::read(Role::any()), Permission::create(Role::any()), @@ -1330,18 +1330,18 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(201, $table['headers']['status-code']); - $this->assertEquals($table['body']['name'], 'attributeRowWidthLimit'); + $this->assertEquals('columnRowWidthLimit', $table['body']['name']); $tableId = $table['body']['$id']; - // Add wide string attributes to approach row width limit + // Add wide string columns to approach row width limit for ($i = 0; $i < 15; $i++) { $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'key' => "attribute{$i}", + 'key' => "column{$i}", 'size' => 1024, 'required' => true, ]); @@ -1373,10 +1373,10 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), - 'name' => 'invalidDocumentDatabase', + 'name' => 'invalidRowDatabase', ]); $this->assertEquals(201, $database['headers']['status-code']); - $this->assertEquals('invalidDocumentDatabase', $database['body']['name']); + $this->assertEquals('invalidRowDatabase', $database['body']['name']); $databaseId = $database['body']['$id']; $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ @@ -1400,15 +1400,15 @@ class DatabasesCustomServerTest extends Scope $tableId = $table['body']['$id']; - // add unique attributes for indexing + // add unique columns for indexing for ($i = 0; $i < 64; $i++) { - // $this->assertEquals(true, static::getDatabase()->createAttribute('indexLimit', "test{$i}", Database::VAR_STRING, 16, true)); + // $this->assertEquals(true, static::getDatabase()->createColumn('indexLimit', "test{$i}", Database::VAR_STRING, 16, true)); $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'key' => "attribute{$i}", + 'key' => "column{$i}", 'size' => 64, 'required' => true, ]); @@ -1425,18 +1425,18 @@ class DatabasesCustomServerTest extends Scope ])); $this->assertEquals(200, $table['headers']['status-code']); - $this->assertEquals($table['body']['name'], 'testLimitException'); + $this->assertEquals('testLimitException', $table['body']['name']); $this->assertIsArray($table['body']['columns']); $this->assertIsArray($table['body']['indexes']); $this->assertCount(64, $table['body']['columns']); $this->assertCount(0, $table['body']['indexes']); foreach ($table['body']['columns'] as $column) { - $this->assertEquals('available', $column['status'], 'attribute: ' . $column['key']); + $this->assertEquals('available', $column['status'], 'column: ' . $column['key']); } // Test indexLimit = 64 - // MariaDB, MySQL, and MongoDB create 6 indexes per new collection + // MariaDB, MySQL, and MongoDB create 6 indexes per new table // Add up to the limit, then check if the next index throws IndexLimitException for ($i = 0; $i < 58; $i++) { $index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/indexes', array_merge([ @@ -1444,13 +1444,13 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'key' => "key_attribute{$i}", + 'key' => "key_column{$i}", 'type' => 'key', - 'columns' => ["attribute{$i}"], + 'columns' => ["column{$i}"], ]); $this->assertEquals(202, $index['headers']['status-code']); - $this->assertEquals("key_attribute{$i}", $index['body']['key']); + $this->assertEquals("key_column{$i}", $index['body']['key']); } sleep(5); @@ -1475,7 +1475,7 @@ class DatabasesCustomServerTest extends Scope ]), [ 'key' => 'tooMany', 'type' => 'key', - 'columns' => ['attribute61'], + 'columns' => ['column61'], ]); $this->assertEquals(400, $tooMany['headers']['status-code']); @@ -1490,7 +1490,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(204, $table['headers']['status-code']); } - public function testAttributeUpdate(): array + public function testColumnUpdate(): array { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ 'content-type' => 'application/json', @@ -1498,7 +1498,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ 'databaseId' => ID::unique(), - 'name' => 'updateAttributes', + 'name' => 'updateColumns', ]); $this->assertEquals(201, $database['headers']['status-code']); @@ -1508,8 +1508,8 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => ID::custom('updateAttributes'), - 'name' => 'updateAttributes' + 'tableId' => ID::custom('updateColumns'), + 'name' => 'updateColumns' ]); $this->assertEquals(201, $table['headers']['status-code']); @@ -1517,7 +1517,7 @@ class DatabasesCustomServerTest extends Scope $tableId = $table['body']['$id']; /** - * Create String Attribute + * Create String Column */ $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ 'content-type' => 'application/json', @@ -1532,7 +1532,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(202, $column['headers']['status-code']); /** - * Create Email Attribute + * Create Email Column */ $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/email', array_merge([ 'content-type' => 'application/json', @@ -1546,7 +1546,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(202, $column['headers']['status-code']); /** - * Create IP Attribute + * Create IP Column */ $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/ip', array_merge([ 'content-type' => 'application/json', @@ -1560,7 +1560,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(202, $column['headers']['status-code']); /** - * Create URL Attribute + * Create URL Column */ $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/url', array_merge([ 'content-type' => 'application/json', @@ -1574,7 +1574,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(202, $column['headers']['status-code']); /** - * Create Integer Attribute + * Create Integer Column */ $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ 'content-type' => 'application/json', @@ -1588,7 +1588,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(202, $column['headers']['status-code']); /** - * Create Float Attribute + * Create Float Column */ $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/float', array_merge([ 'content-type' => 'application/json', @@ -1600,7 +1600,7 @@ class DatabasesCustomServerTest extends Scope ]); /** - * Create Boolean Attribute + * Create Boolean Column */ $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/boolean', array_merge([ 'content-type' => 'application/json', @@ -1612,7 +1612,7 @@ class DatabasesCustomServerTest extends Scope ]); /** - * Create Datetime Attribute + * Create Datetime Column */ $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/datetime', array_merge([ 'content-type' => 'application/json', @@ -1624,7 +1624,7 @@ class DatabasesCustomServerTest extends Scope ]); /** - * Create Enum Attribute + * Create Enum Column */ $column = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/enum', array_merge([ 'content-type' => 'application/json', @@ -1647,9 +1647,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testAttributeUpdate + * @depends testColumnUpdate */ - public function testAttributeUpdateString(array $data) + public function testColumnUpdateString(array $data) { $key = 'string'; $databaseId = $data['databaseId']; @@ -1789,9 +1789,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testAttributeUpdate + * @depends testColumnUpdate */ - public function testAttributeUpdateEmail(array $data) + public function testColumnUpdateEmail(array $data) { $key = 'email'; $databaseId = $data['databaseId']; @@ -1932,9 +1932,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testAttributeUpdate + * @depends testColumnUpdate */ - public function testAttributeUpdateIp(array $data) + public function testColumnUpdateIp(array $data) { $key = 'ip'; $databaseId = $data['databaseId']; @@ -2074,9 +2074,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testAttributeUpdate + * @depends testColumnUpdate */ - public function testAttributeUpdateUrl(array $data) + public function testColumnUpdateUrl(array $data) { $key = 'url'; $databaseId = $data['databaseId']; @@ -2216,9 +2216,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testAttributeUpdate + * @depends testColumnUpdate */ - public function testAttributeUpdateInteger(array $data) + public function testColumnUpdateInteger(array $data) { $key = 'integer'; $databaseId = $data['databaseId']; @@ -2477,9 +2477,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testAttributeUpdate + * @depends testColumnUpdate */ - public function testAttributeUpdateFloat(array $data) + public function testColumnUpdateFloat(array $data) { $key = 'float'; $databaseId = $data['databaseId']; @@ -2738,9 +2738,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testAttributeUpdate + * @depends testColumnUpdate */ - public function testAttributeUpdateBoolean(array $data) + public function testColumnUpdateBoolean(array $data) { $key = 'boolean'; $databaseId = $data['databaseId']; @@ -2880,9 +2880,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testAttributeUpdate + * @depends testColumnUpdate */ - public function testAttributeUpdateDatetime(array $data) + public function testColumnUpdateDatetime(array $data) { $key = 'datetime'; $databaseId = $data['databaseId']; @@ -3022,9 +3022,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testAttributeUpdate + * @depends testColumnUpdate */ - public function testAttributeUpdateEnum(array $data) + public function testColumnUpdateEnum(array $data) { $key = 'enum'; $databaseId = $data['databaseId']; @@ -3238,9 +3238,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testAttributeUpdate + * @depends testColumnUpdate */ - public function testAttributeUpdateStringResize(array $data) + public function testColumnUpdateStringResize(array $data) { $key = 'string'; $databaseId = $data['databaseId']; @@ -3277,7 +3277,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $column['headers']['status-code']); $this->assertEquals(2048, $column['body']['size']); - // Test create new document with new size + // Test create new row with new size $newDoc = $this->client->call( Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', @@ -3298,7 +3298,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(201, $newDoc['headers']['status-code']); $this->assertEquals(2048, strlen($newDoc['body']['string'])); - // Test update document with new size + // Test update row with new size $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -3326,7 +3326,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $column['headers']['status-code']); $this->assertEquals(AppwriteException::COLUMN_INVALID_RESIZE, $column['body']['type']); - // original documents to original size, remove new document + // original rows to original size, remove new row $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -3363,7 +3363,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $column['headers']['status-code']); $this->assertEquals(10, $column['body']['size']); - // Test create new document with new size + // Test create new row with new size $newDoc = $this->client->call( Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', @@ -3384,7 +3384,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(201, $newDoc['headers']['status-code']); $this->assertEquals(10, strlen($newDoc['body']['string'])); - // Test update document with new size + // Test update row with new size $row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows/' . $row['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -3398,7 +3398,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $row['headers']['status-code']); $this->assertEquals(10, strlen($row['body']['string'])); - // Try create document with string that is too large + // Try create row with string that is too large $newDoc = $this->client->call( Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', @@ -3421,9 +3421,9 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testAttributeUpdate + * @depends testColumnUpdate */ - public function testAttributeUpdateNotFound(array $data) + public function testColumnUpdateNotFound(array $data) { $databaseId = $data['databaseId']; $tableId = $data['tableId']; @@ -3482,7 +3482,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(AppwriteException::DATABASE_NOT_FOUND, $update['body']['type']); /** - * Check if Collection exists + * Check if Table exists */ $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/i_dont_exist/columns/' . $key . '/unknown_' . $key, array_merge([ 'content-type' => 'application/json', @@ -3494,7 +3494,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(AppwriteException::TABLE_NOT_FOUND, $update['body']['type']); /** - * Check if Attribute exists + * Check if Column exists */ $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $tableId . '/columns/' . $key . '/unknown_' . $key, array_merge([ 'content-type' => 'application/json', @@ -3508,15 +3508,15 @@ class DatabasesCustomServerTest extends Scope } /** - * @depends testAttributeUpdate + * @depends testColumnUpdate */ - public function testAttributeRename(array $data) + public function testColumnRename(array $data) { $key = 'string'; $databaseId = $data['databaseId']; $tableId = $data['tableId']; - // Create document to test against + // Create row to test against $row = $this->client->call( Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', @@ -3568,7 +3568,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals('string', $doc1['body']['new_string']); $this->assertArrayNotHasKey('string', $doc1['body']); - // Try and create a new document with the new attribute + // Try and create a new row with the new column $doc2 = $this->client->call( Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', @@ -3590,7 +3590,7 @@ class DatabasesCustomServerTest extends Scope $this->assertArrayHasKey('new_string', $doc2['body']); $this->assertEquals('string', $doc2['body']['new_string']); - // Expect fail, try and create a new document with the old attribute + // Expect fail, try and create a new row with the old column $doc3 = $this->client->call( Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $tableId . '/rows', @@ -3611,9 +3611,9 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $doc3['headers']['status-code']); } - public function createRelationshipCollections(): void + public function createRelationshipTables(): void { - // Prepare the database with collections and relationships + // Prepare the database with tables and relationships $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -3630,7 +3630,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => 'collection1', + 'tableId' => 'table1', 'name' => 'level1', 'rowSecurity' => false, 'permissions' => [ @@ -3646,7 +3646,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'tableId' => 'collection2', + 'tableId' => 'table2', 'name' => 'level2', 'rowSecurity' => false, 'permissions' => [ @@ -3660,7 +3660,7 @@ class DatabasesCustomServerTest extends Scope \sleep(2); } - public function cleanupRelationshipCollection(): void + public function cleanupRelationshipTable(): void { $this->client->call(Client::METHOD_DELETE, '/databases/database1', [ 'content-type' => 'application/json', @@ -3671,13 +3671,13 @@ class DatabasesCustomServerTest extends Scope \sleep(2); } - public function testAttributeRenameRelationshipOneToMany() + public function testColumnRenameRelationshipOneToMany() { $databaseId = 'database1'; - $table1Id = 'collection1'; - $table2Id = 'collection2'; + $table1Id = 'table1'; + $table2Id = 'table2'; - $this->createRelationshipCollections(); + $this->createRelationshipTables(); $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/relationship', array_merge([ 'content-type' => 'application/json', @@ -3694,20 +3694,20 @@ class DatabasesCustomServerTest extends Scope \sleep(3); - $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + $table1Columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $table1RelationAttribute = $table1Attributes['body']['columns'][0]; + $table1RelationColumn = $table1Columns['body']['columns'][0]; - $this->assertEquals($relation['body']['side'], $table1RelationAttribute['side']); - $this->assertEquals($relation['body']['twoWayKey'], $table1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedTable'], $table1RelationAttribute['relatedTable']); + $this->assertEquals($relation['body']['side'], $table1RelationColumn['side']); + $this->assertEquals($relation['body']['twoWayKey'], $table1RelationColumn['twoWayKey']); + $this->assertEquals($relation['body']['relatedTable'], $table1RelationColumn['relatedTable']); - // Create a document for checking later - $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows', array_merge([ + // Create a row for checking later + $originalRow = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -3722,9 +3722,9 @@ class DatabasesCustomServerTest extends Scope "permissions" => ["read(\"any\")"] ]); - $this->assertEquals(201, $originalDocument['headers']['status-code']); + $this->assertEquals(201, $originalRow['headers']['status-code']); - // Rename the attribute + // Rename the column $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/level2' . '/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -3735,59 +3735,59 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $update['headers']['status-code']); - // Check the document's key has been renamed - $newDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows/' . $originalDocument['body']['$id'], array_merge([ + // Check the row's key has been renamed + $newRow = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows/' . $originalRow['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertArrayHasKey('new_level_2', $newDocument['body']); - $this->assertEquals(1, count($newDocument['body']['new_level_2'])); - $this->assertArrayNotHasKey('level2', $newDocument['body']); + $this->assertArrayHasKey('new_level_2', $newRow['body']); + $this->assertEquals(1, count($newRow['body']['new_level_2'])); + $this->assertArrayNotHasKey('level2', $newRow['body']); - // Check level2 document has been renamed - $level2Document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id . '/rows/' . $newDocument['body']['new_level_2'][0]['$id'], array_merge([ + // Check level2 row has been renamed + $level2Row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id . '/rows/' . $newRow['body']['new_level_2'][0]['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertArrayHasKey('level1', $level2Document['body']); - $this->assertNotEmpty($level2Document['body']['level1']); + $this->assertArrayHasKey('level1', $level2Row['body']); + $this->assertNotEmpty($level2Row['body']['level1']); - // Check if attribute was renamed on the parent's side - $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + // Check if column was renamed on the parent's side + $table1Columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $this->assertEquals(200, $table1Attributes['headers']['status-code']); - $this->assertEquals(1, count($table1Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $table1Attributes['body']['columns'][0]['key']); + $this->assertEquals(200, $table1Columns['headers']['status-code']); + $this->assertEquals(1, count($table1Columns['body']['columns'])); + $this->assertEquals('new_level_2', $table1Columns['body']['columns'][0]['key']); - // Check if attribute was renamed on the child's side - $table2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id, [ + // Check if column was renamed on the child's side + $table2Columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $this->assertEquals(200, $table2Attributes['headers']['status-code']); - $this->assertEquals(1, count($table2Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $table2Attributes['body']['columns'][0]['twoWayKey']); + $this->assertEquals(200, $table2Columns['headers']['status-code']); + $this->assertEquals(1, count($table2Columns['body']['columns'])); + $this->assertEquals('new_level_2', $table2Columns['body']['columns'][0]['twoWayKey']); - $this->cleanupRelationshipCollection(); + $this->cleanupRelationshipTable(); } - public function testAttributeRenameRelationshipOneToOne() + public function testColumnRenameRelationshipOneToOne() { $databaseId = 'database1'; - $table1Id = 'collection1'; - $table2Id = 'collection2'; + $table1Id = 'table1'; + $table2Id = 'table2'; - $this->createRelationshipCollections(); + $this->createRelationshipTables(); $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/relationship', array_merge([ 'content-type' => 'application/json', @@ -3804,20 +3804,20 @@ class DatabasesCustomServerTest extends Scope \sleep(3); - $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + $table1Columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $table1RelationAttribute = $table1Attributes['body']['columns'][0]; + $table1RelationColumn = $table1Columns['body']['columns'][0]; - $this->assertEquals($relation['body']['side'], $table1RelationAttribute['side']); - $this->assertEquals($relation['body']['twoWayKey'], $table1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedTable'], $table1RelationAttribute['relatedTable']); + $this->assertEquals($relation['body']['side'], $table1RelationColumn['side']); + $this->assertEquals($relation['body']['twoWayKey'], $table1RelationColumn['twoWayKey']); + $this->assertEquals($relation['body']['relatedTable'], $table1RelationColumn['relatedTable']); - // Create a document for checking later - $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows', array_merge([ + // Create a row for checking later + $originalRow = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -3832,9 +3832,9 @@ class DatabasesCustomServerTest extends Scope "permissions" => ["read(\"any\")"] ]); - $this->assertEquals(201, $originalDocument['headers']['status-code']); + $this->assertEquals(201, $originalRow['headers']['status-code']); - // Rename the attribute + // Rename the column $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/level2' . '/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -3845,59 +3845,59 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $update['headers']['status-code']); - // Check the document's key has been renamed - $newDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows/' . $originalDocument['body']['$id'], array_merge([ + // Check the row's key has been renamed + $newRow = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows/' . $originalRow['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertArrayHasKey('new_level_2', $newDocument['body']); - $this->assertNotEmpty($newDocument['body']['new_level_2']); - $this->assertArrayNotHasKey('level2', $newDocument['body']); + $this->assertArrayHasKey('new_level_2', $newRow['body']); + $this->assertNotEmpty($newRow['body']['new_level_2']); + $this->assertArrayNotHasKey('level2', $newRow['body']); - // Check level2 document has been renamed - $level2Document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id . '/rows/' . $newDocument['body']['new_level_2']['$id'], array_merge([ + // Check level2 row has been renamed + $level2Row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id . '/rows/' . $newRow['body']['new_level_2']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertArrayHasKey('level1', $level2Document['body']); - $this->assertNotEmpty($level2Document['body']['level1']); + $this->assertArrayHasKey('level1', $level2Row['body']); + $this->assertNotEmpty($level2Row['body']['level1']); - // Check if attribute was renamed on the parent's side - $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + // Check if column was renamed on the parent's side + $table1Columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $this->assertEquals(200, $table1Attributes['headers']['status-code']); - $this->assertEquals(1, count($table1Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $table1Attributes['body']['columns'][0]['key']); + $this->assertEquals(200, $table1Columns['headers']['status-code']); + $this->assertEquals(1, count($table1Columns['body']['columns'])); + $this->assertEquals('new_level_2', $table1Columns['body']['columns'][0]['key']); - // Check if attribute was renamed on the child's side - $table2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id, [ + // Check if column was renamed on the child's side + $table2Columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $this->assertEquals(200, $table2Attributes['headers']['status-code']); - $this->assertEquals(1, count($table2Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $table2Attributes['body']['columns'][0]['twoWayKey']); + $this->assertEquals(200, $table2Columns['headers']['status-code']); + $this->assertEquals(1, count($table2Columns['body']['columns'])); + $this->assertEquals('new_level_2', $table2Columns['body']['columns'][0]['twoWayKey']); - $this->cleanupRelationshipCollection(); + $this->cleanupRelationshipTable(); } - public function testAttributeRenameRelationshipManyToOne() + public function testColumnRenameRelationshipManyToOne() { $databaseId = 'database1'; - $table1Id = 'collection1'; - $table2Id = 'collection2'; + $table1Id = 'table1'; + $table2Id = 'table2'; - $this->createRelationshipCollections(); + $this->createRelationshipTables(); $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/relationship', array_merge([ 'content-type' => 'application/json', @@ -3914,20 +3914,20 @@ class DatabasesCustomServerTest extends Scope \sleep(3); - $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + $table1Columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $table1RelationAttribute = $table1Attributes['body']['columns'][0]; + $table1RelationColumn = $table1Columns['body']['columns'][0]; - $this->assertEquals($relation['body']['side'], $table1RelationAttribute['side']); - $this->assertEquals($relation['body']['twoWayKey'], $table1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedTable'], $table1RelationAttribute['relatedTable']); + $this->assertEquals($relation['body']['side'], $table1RelationColumn['side']); + $this->assertEquals($relation['body']['twoWayKey'], $table1RelationColumn['twoWayKey']); + $this->assertEquals($relation['body']['relatedTable'], $table1RelationColumn['relatedTable']); - // Create a document for checking later - $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows', array_merge([ + // Create a row for checking later + $originalRow = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -3942,9 +3942,9 @@ class DatabasesCustomServerTest extends Scope "permissions" => ["read(\"any\")"] ]); - $this->assertEquals(201, $originalDocument['headers']['status-code']); + $this->assertEquals(201, $originalRow['headers']['status-code']); - // Rename the attribute + // Rename the column $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/level2' . '/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -3955,59 +3955,59 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $update['headers']['status-code']); - // Check the document's key has been renamed - $newDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows/' . $originalDocument['body']['$id'], array_merge([ + // Check the row's key has been renamed + $newRow = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows/' . $originalRow['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertArrayHasKey('new_level_2', $newDocument['body']); - $this->assertNotEmpty($newDocument['body']['new_level_2']); - $this->assertArrayNotHasKey('level2', $newDocument['body']); + $this->assertArrayHasKey('new_level_2', $newRow['body']); + $this->assertNotEmpty($newRow['body']['new_level_2']); + $this->assertArrayNotHasKey('level2', $newRow['body']); - // Check level2 document has been renamed - $level2Document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id . '/rows/' . $newDocument['body']['new_level_2']['$id'], array_merge([ + // Check level2 row has been renamed + $level2Row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id . '/rows/' . $newRow['body']['new_level_2']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertArrayHasKey('level1', $level2Document['body']); - $this->assertNotEmpty($level2Document['body']['level1']); + $this->assertArrayHasKey('level1', $level2Row['body']); + $this->assertNotEmpty($level2Row['body']['level1']); - // Check if attribute was renamed on the parent's side - $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + // Check if column was renamed on the parent's side + $table1Columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $this->assertEquals(200, $table1Attributes['headers']['status-code']); - $this->assertEquals(1, count($table1Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $table1Attributes['body']['columns'][0]['key']); + $this->assertEquals(200, $table1Columns['headers']['status-code']); + $this->assertEquals(1, count($table1Columns['body']['columns'])); + $this->assertEquals('new_level_2', $table1Columns['body']['columns'][0]['key']); - // Check if attribute was renamed on the child's side - $table2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id, [ + // Check if column was renamed on the child's side + $table2Columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $this->assertEquals(200, $table2Attributes['headers']['status-code']); - $this->assertEquals(1, count($table2Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $table2Attributes['body']['columns'][0]['twoWayKey']); + $this->assertEquals(200, $table2Columns['headers']['status-code']); + $this->assertEquals(1, count($table2Columns['body']['columns'])); + $this->assertEquals('new_level_2', $table2Columns['body']['columns'][0]['twoWayKey']); - $this->cleanupRelationshipCollection(); + $this->cleanupRelationshipTable(); } - public function testAttributeRenameRelationshipManyToMany() + public function testColumnRenameRelationshipManyToMany() { $databaseId = 'database1'; - $table1Id = 'collection1'; - $table2Id = 'collection2'; + $table1Id = 'table1'; + $table2Id = 'table2'; - $this->createRelationshipCollections(); + $this->createRelationshipTables(); $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/relationship', array_merge([ 'content-type' => 'application/json', @@ -4024,20 +4024,20 @@ class DatabasesCustomServerTest extends Scope \sleep(3); - $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + $table1Columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $table1RelationAttribute = $table1Attributes['body']['columns'][0]; + $table1RelationColumn = $table1Columns['body']['columns'][0]; - $this->assertEquals($relation['body']['side'], $table1RelationAttribute['side']); - $this->assertEquals($relation['body']['twoWayKey'], $table1RelationAttribute['twoWayKey']); - $this->assertEquals($relation['body']['relatedTable'], $table1RelationAttribute['relatedTable']); + $this->assertEquals($relation['body']['side'], $table1RelationColumn['side']); + $this->assertEquals($relation['body']['twoWayKey'], $table1RelationColumn['twoWayKey']); + $this->assertEquals($relation['body']['relatedTable'], $table1RelationColumn['relatedTable']); - // Create a document for checking later - $originalDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows', array_merge([ + // Create a row for checking later + $originalRow = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -4052,9 +4052,9 @@ class DatabasesCustomServerTest extends Scope "permissions" => ["read(\"any\")"] ]); - $this->assertEquals(201, $originalDocument['headers']['status-code']); + $this->assertEquals(201, $originalRow['headers']['status-code']); - // Rename the attribute + // Rename the column $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/tables/' . $table1Id . '/columns/level2' . '/relationship', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4065,50 +4065,50 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $update['headers']['status-code']); - // Check the document's key has been renamed - $newDocument = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows/' . $originalDocument['body']['$id'], array_merge([ + // Check the row's key has been renamed + $newRow = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id . '/rows/' . $originalRow['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertArrayHasKey('new_level_2', $newDocument['body']); - $this->assertNotEmpty($newDocument['body']['new_level_2']); - $this->assertArrayNotHasKey('level2', $newDocument['body']); + $this->assertArrayHasKey('new_level_2', $newRow['body']); + $this->assertNotEmpty($newRow['body']['new_level_2']); + $this->assertArrayNotHasKey('level2', $newRow['body']); - // Check level2 document has been renamed - $level2Document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id . '/rows/' . $newDocument['body']['new_level_2']['$id'], array_merge([ + // Check level2 row has been renamed + $level2Row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id . '/rows/' . $newRow['body']['new_level_2']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $this->assertArrayHasKey('level1', $level2Document['body']); - $this->assertNotEmpty($level2Document['body']['level1']); + $this->assertArrayHasKey('level1', $level2Row['body']); + $this->assertNotEmpty($level2Row['body']['level1']); - // Check if attribute was renamed on the parent's side - $table1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ + // Check if column was renamed on the parent's side + $table1Columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table1Id, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $this->assertEquals(200, $table1Attributes['headers']['status-code']); - $this->assertEquals(1, count($table1Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $table1Attributes['body']['columns'][0]['key']); + $this->assertEquals(200, $table1Columns['headers']['status-code']); + $this->assertEquals(1, count($table1Columns['body']['columns'])); + $this->assertEquals('new_level_2', $table1Columns['body']['columns'][0]['key']); - // Check if attribute was renamed on the child's side - $table2Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id, [ + // Check if column was renamed on the child's side + $table2Columns = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $table2Id, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]); - $this->assertEquals(200, $table2Attributes['headers']['status-code']); - $this->assertEquals(1, count($table2Attributes['body']['columns'])); - $this->assertEquals('new_level_2', $table2Attributes['body']['columns'][0]['twoWayKey']); + $this->assertEquals(200, $table2Columns['headers']['status-code']); + $this->assertEquals(1, count($table2Columns['body']['columns'])); + $this->assertEquals('new_level_2', $table2Columns['body']['columns'][0]['twoWayKey']); - $this->cleanupRelationshipCollection(); + $this->cleanupRelationshipTable(); } public function testBulkCreate(): void @@ -4127,7 +4127,7 @@ class DatabasesCustomServerTest extends Scope $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -4143,15 +4143,15 @@ class DatabasesCustomServerTest extends Scope ], ]); - $this->assertEquals(201, $collection['headers']['status-code']); + $this->assertEquals(201, $table['headers']['status-code']); $data = [ - '$id' => $collection['body']['$id'], - 'databaseId' => $collection['body']['databaseId'] + '$id' => $table['body']['$id'], + 'databaseId' => $table['body']['databaseId'] ]; - // Await attribute - $numberAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/integer', array_merge([ + // Await column + $numberColumn = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -4160,7 +4160,7 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - $this->assertEquals(202, $numberAttribute['headers']['status-code']); + $this->assertEquals(202, $numberColumn['headers']['status-code']); sleep(1); @@ -4199,7 +4199,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(3, $response['body']['rows']); - // TEST SUCCESS - $id is auto-assigned if not included in bulk documents + // TEST SUCCESS - $id is auto-assigned if not included in bulk rows $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4213,7 +4213,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); - // TEST FAIL - Can't use data and document together + // TEST FAIL - Can't use data and row together $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4231,7 +4231,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - // TEST FAIL - Can't use $rowId and create bulk documents + // TEST FAIL - Can't use $rowId and create bulk rows $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4247,7 +4247,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - // TEST FAIL - Can't include invalid ID in bulk documents + // TEST FAIL - Can't include invalid ID in bulk rows $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4262,7 +4262,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - // TEST FAIL - Can't miss number in bulk documents + // TEST FAIL - Can't miss number in bulk rows $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4280,7 +4280,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - // TEST FAIL - Can't push more than APP_LIMIT_DATABASE_BATCH documents + // TEST FAIL - Can't push more than APP_LIMIT_DATABASE_BATCH rows $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4293,7 +4293,7 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - // TEST FAIL - Can't include invalid permissions in nested documents + // TEST FAIL - Can't include invalid permissions in nested rows $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/tables/{$data['$id']}/rows", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4307,8 +4307,8 @@ class DatabasesCustomServerTest extends Scope ], ]); - // TEST FAIL - Can't bulk create in a collection with relationships - $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + // TEST FAIL - Can't bulk create in a table with relationships + $table2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -4324,7 +4324,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ], $this->getHeaders()), [ - 'relatedTableId' => $collection2['body']['$id'], + 'relatedTableId' => $table2['body']['$id'], 'type' => 'manyToOne', 'twoWay' => true, 'onDelete' => 'cascade', @@ -4365,7 +4365,7 @@ class DatabasesCustomServerTest extends Scope $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -4381,15 +4381,15 @@ class DatabasesCustomServerTest extends Scope ], ]); - $this->assertEquals(201, $collection['headers']['status-code']); + $this->assertEquals(201, $table['headers']['status-code']); $data = [ - '$id' => $collection['body']['$id'], - 'databaseId' => $collection['body']['databaseId'] + '$id' => $table['body']['$id'], + 'databaseId' => $table['body']['databaseId'] ]; - // Await attribute - $numberAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/integer', array_merge([ + // Await column + $numberColumn = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -4398,17 +4398,17 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - $this->assertEquals(202, $numberAttribute['headers']['status-code']); + $this->assertEquals(202, $numberColumn['headers']['status-code']); - // Wait for database worker to create attributes + // Wait for database worker to create columns sleep(2); - // Create documents - $createBulkDocuments = function ($amount = 10) use ($data) { - $documents = []; + // Create rows + $createBulkRows = function ($amount = 10) use ($data) { + $rows = []; for ($x = 1; $x <= $amount; $x++) { - $documents[] = [ + $rows[] = [ '$id' => ID::unique(), 'number' => $x, ]; @@ -4418,15 +4418,15 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rows' => $documents, + 'rows' => $rows, ]); $this->assertEquals(201, $doc['headers']['status-code']); }; - $createBulkDocuments(); + $createBulkRows(); - // TEST: Update all documents + // TEST: Update all rows $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4444,30 +4444,30 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(10, $response['body']['rows']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ Query::equal('number', [100])->toString(), ]); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(10, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(10, $rows['body']['total']); - $returnedDocuments = $response['body']['rows']; - $refetchedDocuments = $documents['body']['rows']; + $returnedRows = $response['body']['rows']; + $refetchedRows = $rows['body']['rows']; - $this->assertEquals($returnedDocuments, $refetchedDocuments); + $this->assertEquals($returnedRows, $refetchedRows); - foreach ($documents['body']['rows'] as $document) { + foreach ($rows['body']['rows'] as $row) { $this->assertEquals([ Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ], $document['$permissions']); - $this->assertEquals($collection['body']['$id'], $document['$tableId']); - $this->assertEquals($data['databaseId'], $document['$databaseId']); - $this->assertEquals(100, $document['number']); + ], $row['$permissions']); + $this->assertEquals($table['body']['$id'], $row['$tableId']); + $this->assertEquals($data['databaseId'], $row['$databaseId']); + $this->assertEquals(100, $row['number']); } // TEST: Check permissions persist @@ -4483,25 +4483,25 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(10, $response['body']['rows']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ Query::equal('number', [200])->toString(), ]); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(10, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(10, $rows['body']['total']); - foreach ($documents['body']['rows'] as $document) { + foreach ($rows['body']['rows'] as $row) { $this->assertEquals([ Permission::read(Role::user($this->getUser()['$id'])), Permission::update(Role::user($this->getUser()['$id'])), Permission::delete(Role::user($this->getUser()['$id'])), - ], $document['$permissions']); + ], $row['$permissions']); } - // TEST: Update documents with limit + // TEST: Update rows with limit $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4517,17 +4517,17 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(5, $response['body']['rows']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [Query::equal('number', [200])->toString()] ]); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(5, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(5, $rows['body']['total']); - // TEST: Update documents with offset + // TEST: Update rows with offset $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4543,17 +4543,17 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(5, $response['body']['rows']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [Query::equal('number', [300])->toString()] ]); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(10, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(10, $rows['body']['total']); - // TEST: Update documents with equals filter + // TEST: Update rows with equals filter $response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4569,18 +4569,18 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(10, $response['body']['rows']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [Query::equal('number', [400])->toString()] ]); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(10, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(10, $rows['body']['total']); - // TEST: Fail - Can't bulk update in a collection with relationships - $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + // TEST: Fail - Can't bulk update in a table with relationships + $table2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -4596,7 +4596,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ], $this->getHeaders()), [ - 'relatedTableId' => $collection2['body']['$id'], + 'relatedTableId' => $table2['body']['$id'], 'type' => 'manyToOne', 'twoWay' => true, 'onDelete' => 'cascade', @@ -4639,7 +4639,7 @@ class DatabasesCustomServerTest extends Scope $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -4655,15 +4655,15 @@ class DatabasesCustomServerTest extends Scope ], ]); - $this->assertEquals(201, $collection['headers']['status-code']); + $this->assertEquals(201, $table['headers']['status-code']); $data = [ - '$id' => $collection['body']['$id'], - 'databaseId' => $collection['body']['databaseId'] + '$id' => $table['body']['$id'], + 'databaseId' => $table['body']['databaseId'] ]; - // Await attribute - $numberAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/integer', array_merge([ + // Await column + $numberColumn = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -4672,17 +4672,17 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - $this->assertEquals(202, $numberAttribute['headers']['status-code']); + $this->assertEquals(202, $numberColumn['headers']['status-code']); - // Wait for database worker to create attributes + // Wait for database worker to create columns sleep(2); - // Create documents - $createBulkDocuments = function ($amount = 10) use ($data) { - $documents = []; + // Create rows + $createBulkRows = function ($amount = 10) use ($data) { + $rows = []; for ($x = 1; $x <= $amount; $x++) { - $documents[] = [ + $rows[] = [ '$id' => "$x", 'number' => $x, ]; @@ -4692,53 +4692,53 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rows' => $documents, + 'rows' => $rows, ]); $this->assertEquals(201, $response['headers']['status-code']); - return $documents; + return $rows; }; - $documents = $createBulkDocuments(); + $rows = $createBulkRows(); - // Update 1 document - $documents[\array_key_last($documents)]['number'] = 1000; + // Update 1 row + $rows[\array_key_last($rows)]['number'] = 1000; - // Add 1 document - $documents[] = ['number' => 11]; + // Add 1 row + $rows[] = ['number' => 11]; - // TEST: Upsert all documents + // TEST: Upsert all rows $response = $this->client->call(Client::METHOD_PUT, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rows' => $documents, + 'rows' => $rows, ]); - // Unchanged docs are skipped. 2 documents should be returned, 1 updated and 1 inserted. + // Unchanged docs are skipped. 2 rows should be returned, 1 updated and 1 inserted. $this->assertEquals(200, $response['headers']['status-code']); $this->assertCount(2, $response['body']['rows']); $this->assertEquals(1000, $response['body']['rows'][0]['number']); $this->assertEquals(11, $response['body']['rows'][1]['number']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ])); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(11, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(11, $rows['body']['total']); - foreach ($documents['body']['rows'] as $index => $document) { - $this->assertEquals($collection['body']['$id'], $document['$tableId']); - $this->assertEquals($data['databaseId'], $document['$databaseId']); + foreach ($rows['body']['rows'] as $index => $row) { + $this->assertEquals($table['body']['$id'], $row['$tableId']); + $this->assertEquals($data['databaseId'], $row['$databaseId']); switch ($index) { case 9: - $this->assertEquals(1000, $document['number']); + $this->assertEquals(1000, $row['number']); break; default: - $this->assertEquals($index + 1, $document['number']); + $this->assertEquals($index + 1, $row['number']); } } @@ -4772,8 +4772,8 @@ class DatabasesCustomServerTest extends Scope Permission::delete(Role::user($this->getUser()['$id'])), ], $response['body']['rows'][1]['$permissions']); - // TEST: Fail - Can't bulk upsert in a collection with relationships - $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + // TEST: Fail - Can't bulk upsert in a table with relationships + $table2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -4789,7 +4789,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ], $this->getHeaders()), [ - 'relatedTableId' => $collection2['body']['$id'], + 'relatedTableId' => $table2['body']['$id'], 'type' => 'manyToOne', 'twoWay' => true, 'onDelete' => 'cascade', @@ -4832,7 +4832,7 @@ class DatabasesCustomServerTest extends Scope $databaseId = $database['body']['$id']; - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + $table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -4847,15 +4847,15 @@ class DatabasesCustomServerTest extends Scope ], ]); - $this->assertEquals(201, $collection['headers']['status-code']); + $this->assertEquals(201, $table['headers']['status-code']); $data = [ - '$id' => $collection['body']['$id'], - 'databaseId' => $collection['body']['databaseId'] + '$id' => $table['body']['$id'], + 'databaseId' => $table['body']['databaseId'] ]; - // Await attribute - $numberAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/integer', array_merge([ + // Await column + $numberColumn = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables/' . $data['$id'] . '/columns/integer', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -4864,17 +4864,17 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - $this->assertEquals(202, $numberAttribute['headers']['status-code']); + $this->assertEquals(202, $numberColumn['headers']['status-code']); - // wait for database worker to create attributes + // wait for database worker to create columns sleep(2); - // Create documents - $createBulkDocuments = function ($amount = 11) use ($data) { - $documents = []; + // Create rows + $createBulkRows = function ($amount = 11) use ($data) { + $rows = []; for ($x = 0; $x < $amount; $x++) { - $documents[] = [ + $rows[] = [ '$id' => ID::unique(), 'number' => $x, ]; @@ -4884,23 +4884,23 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'rows' => $documents, + 'rows' => $rows, ]); $this->assertEquals(201, $doc['headers']['status-code']); }; - $createBulkDocuments(); + $createBulkRows(); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(11, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(11, $rows['body']['total']); - // TEST: Delete all documents + // TEST: Delete all rows $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -4909,24 +4909,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(11, $response['body']['total']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(0, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(0, $rows['body']['total']); - // TEST: Delete documents with query - $createBulkDocuments(); + // TEST: Delete rows with query + $createBulkRows(); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(11, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(11, $rows['body']['total']); $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', @@ -4940,16 +4940,16 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(5, $response['body']['total']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(6, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(6, $rows['body']['total']); - foreach ($documents['body']['rows'] as $document) { - $this->assertGreaterThanOrEqual(5, $document['number']); + foreach ($rows['body']['rows'] as $row) { + $this->assertGreaterThanOrEqual(5, $row['number']); } // Cleanup @@ -4961,16 +4961,16 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(6, $response['body']['total']); - // SUCCESS: Delete documents with query - $createBulkDocuments(); + // SUCCESS: Delete rows with query + $createBulkRows(); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(11, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(11, $rows['body']['total']); $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', @@ -4984,13 +4984,13 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(5, $response['body']['total']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(6, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(6, $rows['body']['total']); // Cleanup $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ @@ -5001,16 +5001,16 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(6, $response['body']['total']); - // SUCCESS: Delete Documents with limit query - $createBulkDocuments(); + // SUCCESS: Delete Rows with limit query + $createBulkRows(); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(11, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(11, $rows['body']['total']); $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', @@ -5024,13 +5024,13 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(2, $response['body']['total']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(9, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(9, $rows['body']['total']); // Cleanup $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ @@ -5041,16 +5041,16 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(9, $response['body']['total']); - // SUCCESS: Delete Documents with offset query - $createBulkDocuments(); + // SUCCESS: Delete Rows with offset query + $createBulkRows(); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(11, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(11, $rows['body']['total']); $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', @@ -5064,15 +5064,15 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(6, $response['body']['total']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(5, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(5, $rows['body']['total']); - $lastDoc = end($documents['body']['rows']); + $lastDoc = end($rows['body']['rows']); $this->assertNotEmpty($lastDoc); $this->assertEquals(4, $lastDoc['number']); @@ -5086,16 +5086,16 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(5, $response['body']['total']); - // SUCCESS: Delete 100 documents - $createBulkDocuments(100); + // SUCCESS: Delete 100 rows + $createBulkRows(100); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(100, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(100, $rows['body']['total']); $response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', @@ -5105,16 +5105,16 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(100, $response['body']['total']); - $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ + $rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $documents['headers']['status-code']); - $this->assertEquals(0, $documents['body']['total']); + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(0, $rows['body']['total']); - // TEST: Fail - Can't bulk delete in a collection with relationships - $collection2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ + // TEST: Fail - Can't bulk delete in a table with relationships + $table2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/tables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -5130,7 +5130,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ], $this->getHeaders()), [ - 'relatedTableId' => $collection2['body']['$id'], + 'relatedTableId' => $table2['body']['$id'], 'type' => 'manyToOne', 'twoWay' => true, 'onDelete' => 'cascade', From 2e05844ca2242feca29d0afece230b483b020a64 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 13 Jun 2025 14:04:23 +0530 Subject: [PATCH 167/343] add: graphql tests for bulk apis. --- .../Collections/Documents/Bulk/Upsert.php | 1 - .../Collections/Documents/Create.php | 13 +- .../Databases/Tables/Rows/Bulk/Upsert.php | 1 - tests/e2e/Services/GraphQL/Base.php | 135 ++++++++- .../Collections/DatabaseClientTest.php | 176 +++++++++++ .../Collections/DatabaseServerTest.php | 1 + .../GraphQL/Tables/DatabaseClientTest.php | 283 ++++++++++++++++++ .../GraphQL/Tables/DatabaseServerTest.php | 1 + 8 files changed, 601 insertions(+), 10 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php index 1e7d838fba..770f7a4d95 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php @@ -43,7 +43,6 @@ class Upsert extends Action ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents') ->desc('Create or update documents') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].create') ->label('scope', 'documents.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'document.create') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index 33406044f1..e68a27ba34 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -418,6 +418,13 @@ class Create extends Action $response->setStatusCode(SwooleResponse::STATUS_CODE_CREATED); + // BIG TODO: @itznotabug - need to check what to do for bulk api because there's not just one `[document/rowId]`. + $queueForEvents + ->setParam('documentId', $documents[0]->getId()) + ->setParam('rowId', $documents[0]->getId()) + // TODO: @itznotabug - check if the events mirroring works here! + ->setEvent('databases.[databaseId].collections.[collectionId].documents.[documentId].create'); + if ($isBulk) { $response->dynamic(new Document([ 'total' => count($documents), @@ -427,12 +434,6 @@ class Create extends Action return; } - $queueForEvents - ->setParam('documentId', $documents[0]->getId()) - ->setParam('rowId', $documents[0]->getId()) - // TODO: @itznotabug - check if the events mirroring works here! - ->setEvent('databases.[databaseId].collections.[collectionId].documents.[documentId].create'); - $response->dynamic( $documents[0], $this->getResponseModel() diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php index 9331e75aa8..2b4117c23e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php @@ -38,7 +38,6 @@ class Upsert extends DocumentsUpsert ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') ->desc('Create or update rows') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].create') ->label('scope', 'documents.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'row.create') diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index f050fa9638..f001265caf 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -99,15 +99,29 @@ trait Base public static string $GET_DOCUMENTS = 'list_documents'; public static string $GET_DOCUMENT = 'get_document'; public static string $UPDATE_DOCUMENT = 'update_document'; + public static string $UPSERT_DOCUMENT = 'upsert_document'; public static string $DELETE_DOCUMENT = 'delete_document'; + // Documents Bulk APIs + public static string $CREATE_DOCUMENTS = 'create_documents_rest'; + public static string $UPDATE_DOCUMENTS = 'update_documents'; + public static string $UPSERT_DOCUMENTS = 'upsert_documents'; + public static string $DELETE_DOCUMENTS = 'delete_documents'; + // Rows public static string $CREATE_ROW = 'create_row_rest'; public static string $GET_ROWS = 'list_rows'; public static string $GET_ROW = 'get_row'; public static string $UPDATE_ROW = 'update_row'; + public static string $UPSERT_ROW = 'upsert_row'; public static string $DELETE_ROW = 'delete_row'; + // Rows Bulk APIs + public static string $CREATE_ROWS = 'create_rows_rest'; + public static string $UPDATE_ROWS = 'update_rows'; + public static string $UPSERT_ROWS = 'upsert_rows'; + public static string $DELETE_ROWS = 'delete_rows'; + // Custom Entities public static string $CREATE_CUSTOM_ENTITY = 'create_custom_entity'; public static string $GET_CUSTOM_ENTITIES = 'get_custom_entities'; @@ -1100,6 +1114,28 @@ trait Base _permissions } }'; + case self::$CREATE_DOCUMENTS: + return 'mutation createDocuments($databaseId: String!, $collectionId: String!, $documents: [Json!]!) { + collectionsCreateDocuments(databaseId: $databaseId, collectionId: $collectionId, documents: $documents) { + documents { + _id + _collectionId + _permissions + data + } + } + }'; + case self::$CREATE_ROWS: + return 'mutation createRows($databaseId: String!, $tableId: String!, $rows: [Json!]!) { + tablesCreateRows(databaseId: $databaseId, tableId: $tableId, rows: $rows) { + rows { + _id + _tableId + _permissions + data + } + } + }'; case self::$GET_ROW: return 'query getRow($databaseId: String!, $tableId: String!, $rowId: String!) { tablesGetRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId) { @@ -1110,11 +1146,12 @@ trait Base } }'; case self::$GET_ROWS: - return 'query listRows($databaseId: String!, $tableId: String!) { - tablesListRows(databaseId: $databaseId, tableId: $tableId) { + return 'query listRows($databaseId: String!, $tableId: String!, $queries: [String!] = []) { + tablesListRows(databaseId: $databaseId, tableId: $tableId, queries: $queries) { total rows { _id + _databaseId _tableId _permissions data @@ -1196,6 +1233,53 @@ trait Base data } }'; + case self::$UPSERT_DOCUMENT: + return 'mutation upsertDocument($databaseId: String!, $collectionId: String!, $documentId: String!, $data: Json!, $permissions: [String!] = []) { + collectionsUpsertDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { + _id + _databaseId + _collectionId + data + } + }'; + case self::$UPDATE_DOCUMENTS: + return 'mutation updateDocuments($databaseId: String!, $collectionId: String!, $data: Json!, $queries: [String!]) { + collectionsUpdateDocuments(databaseId: $databaseId, collectionId: $collectionId, data: $data, queries: $queries) { + total + documents { + _id + _databaseId + _collectionId + _permissions + data + } + } + }'; + case self::$UPSERT_DOCUMENTS: + return 'mutation upsertDocuments($databaseId: String!, $collectionId: String!, $documents: [Json!]!) { + collectionsUpsertDocuments(databaseId: $databaseId, collectionId: $collectionId, documents: $documents) { + total + documents { + _id + _databaseId + _collectionId + _permissions + data + } + } + }'; + case self::$DELETE_DOCUMENTS: + return 'mutation deleteDocuments($databaseId: String!, $collectionId: String!, $queries: [String!] = []) { + collectionsDeleteDocuments(databaseId: $databaseId, collectionId: $collectionId, queries: $queries) { + total + documents { + _id + _databaseId + _collectionId + data + } + } + }'; case self::$DELETE_DOCUMENT: return 'mutation deleteDocument($databaseId: String!, $collectionId: String!, $documentId: String!){ collectionsDeleteDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { @@ -1210,12 +1294,59 @@ trait Base data } }'; + case self::$UPSERT_ROW: + return 'mutation upsertRow($databaseId: String!, $tableId: String!, $rowId: String!, $data: Json!, $permissions: [String!] = []) { + tablesUpsertRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId, data: $data, permissions: $permissions) { + _id + _databaseId + _tableId + data + } + }'; case self::$DELETE_ROW: return 'mutation deleteRow($databaseId: String!, $tableId: String!, $rowId: String!) { tablesDeleteRow(databaseId: $databaseId, tableId: $tableId, rowId: $rowId) { status } }'; + case self::$UPDATE_ROWS: + return 'mutation updateRows($databaseId: String!, $tableId: String!, $data: Json!, $queries: [String!]) { + tablesUpdateRows(databaseId: $databaseId, tableId: $tableId, data: $data, queries: $queries) { + total + rows { + _id + _databaseId + _tableId + _permissions + data + } + } + }'; + case self::$UPSERT_ROWS: + return 'mutation upsertRows($databaseId: String!, $tableId: String!, $rows: [Json!]!) { + tablesUpsertRows(databaseId: $databaseId, tableId: $tableId, rows: $rows) { + total + rows { + _id + _databaseId + _tableId + _permissions + data + } + } + }'; + case self::$DELETE_ROWS: + return 'mutation deleteRows($databaseId: String!, $tableId: String!, $queries: [String!] = []) { + tablesDeleteRows(databaseId: $databaseId, tableId: $tableId, queries: $queries) { + total + rows { + _id + _databaseId + _tableId + data + } + } + }'; case self::$GET_USER: return 'query getUser($userId : String!) { usersGet(userId : $userId) { diff --git a/tests/e2e/Services/GraphQL/Collections/DatabaseClientTest.php b/tests/e2e/Services/GraphQL/Collections/DatabaseClientTest.php index 9c23a8d784..349d580d64 100644 --- a/tests/e2e/Services/GraphQL/Collections/DatabaseClientTest.php +++ b/tests/e2e/Services/GraphQL/Collections/DatabaseClientTest.php @@ -303,4 +303,180 @@ class DatabaseClientTest extends Scope $this->assertIsNotArray($document['body']); $this->assertEquals(204, $document['headers']['status-code']); } + + /** + * @throws \Exception + */ + public function testBulkCreateDocuments(): array + { + $project = $this->getProject(); + $projectId = $project['$id']; + $headers = [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $project['apiKey'], + ]; + + // Step 1: Create database + $query = $this->getQuery(self::$CREATE_DATABASE); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => 'bulk', + 'name' => 'Bulk', + ], + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $databaseId = $res['body']['data']['databasesCreate']['_id']; + + // Step 2: Create collection + $query = $this->getQuery(self::$CREATE_COLLECTION); + $payload['query'] = $query; + $payload['variables'] = [ + 'databaseId' => $databaseId, + 'collectionId' => 'operations', + 'name' => 'Operations', + 'documentSecurity' => false, + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $collectionId = $res['body']['data']['databasesCreateCollection']['_id']; + + // Step 3: Create attribute + $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); + $payload['query'] = $query; + $payload['variables'] = [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + sleep(1); + + // Step 4: Create documents + $query = $this->getQuery(self::$CREATE_DOCUMENTS); + $documents = []; + for ($i = 1; $i <= 10; $i++) { + $documents[] = ['$id' => 'doc' . $i, 'name' => 'Doc #' . $i]; + } + + $payload['query'] = $query; + $payload['variables'] = [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'documents' => $documents, + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $this->assertCount(10, $res['body']['data']['collectionsCreateDocuments']['documents']); + + return [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'projectId' => $projectId, + ]; + } + + /** + * @depends testBulkCreateDocuments + */ + public function testBulkUpdateDocuments(array $data): array + { + $userId = $this->getUser()['$id']; + $permissions = [ + Permission::read(Role::user($userId)), + Permission::update(Role::user($userId)), + Permission::delete(Role::user($userId)), + ]; + + $headers = [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectId'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]; + + $query = $this->getQuery(self::$UPDATE_DOCUMENTS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'collectionId' => $data['collectionId'], + 'data' => [ + 'name' => 'Docs Updated', + '$permissions' => $permissions, + ], + ], + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $this->assertCount(10, $res['body']['data']['collectionsUpdateDocuments']['documents']); + + return $data; + } + + /** + * @depends testBulkUpdateDocuments + */ + public function testBulkUpsertDocuments(array $data): array + { + $headers = [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectId'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]; + + // Upsert: Update one, insert one + $query = $this->getQuery(self::$UPSERT_DOCUMENTS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'collectionId' => $data['collectionId'], + 'documents' => [ + ['$id' => 'doc10', 'name' => 'Doc #1000'], + ['name' => 'Doc #11'], + ], + ], + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $this->assertCount(2, $res['body']['data']['collectionsUpsertDocuments']['documents']); + + return $data; + } + + /** + * @depends testBulkUpsertDocuments + */ + public function testBulkDeleteDocuments(array $data): array + { + $headers = [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectId'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]; + + $query = $this->getQuery(self::$DELETE_DOCUMENTS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'collectionId' => $data['collectionId'], + ], + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $this->assertCount(11, $res['body']['data']['collectionsDeleteDocuments']['documents']); + + return $data; + } } diff --git a/tests/e2e/Services/GraphQL/Collections/DatabaseServerTest.php b/tests/e2e/Services/GraphQL/Collections/DatabaseServerTest.php index 4aa540a47e..f60acb9b0b 100644 --- a/tests/e2e/Services/GraphQL/Collections/DatabaseServerTest.php +++ b/tests/e2e/Services/GraphQL/Collections/DatabaseServerTest.php @@ -134,6 +134,7 @@ class DatabaseServerTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), $gqlPayload); + // TODO: @itznotabug - check for `encrypt` attribute in string column's response body as well! $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); $this->assertIsArray($attribute['body']['data']['collectionsCreateStringAttribute']); diff --git a/tests/e2e/Services/GraphQL/Tables/DatabaseClientTest.php b/tests/e2e/Services/GraphQL/Tables/DatabaseClientTest.php index 3296f2d622..c5cba6c47f 100644 --- a/tests/e2e/Services/GraphQL/Tables/DatabaseClientTest.php +++ b/tests/e2e/Services/GraphQL/Tables/DatabaseClientTest.php @@ -10,6 +10,7 @@ use Tests\E2E\Services\GraphQL\Base; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; class DatabaseClientTest extends Scope { @@ -303,4 +304,286 @@ class DatabaseClientTest extends Scope $this->assertIsNotArray($row['body']); $this->assertEquals(204, $row['headers']['status-code']); } + + /** + * @throws \Exception + */ + public function testBulkCreate(): array + { + $project = $this->getProject(); + $projectId = $project['$id']; + $headers = [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $project['apiKey'], + ]; + + // Step 1: Create database + $query = $this->getQuery(self::$CREATE_DATABASE); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => 'bulk', + 'name' => 'Bulk', + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $databaseId = $res['body']['data']['databasesCreate']['_id']; + + // Step 2: Create table + $query = $this->getQuery(self::$CREATE_TABLE); + $payload['query'] = $query; + $payload['variables'] = [ + 'databaseId' => $databaseId, + 'tableId' => 'operations', + 'name' => 'Operations', + 'rowSecurity' => false, + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $tableId = $res['body']['data']['databasesCreateTable']['_id']; + + // Step 3: Create column + $query = $this->getQuery(self::$CREATE_STRING_COLUMN); + $payload['query'] = $query; + $payload['variables'] = [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + sleep(1); + + // Step 4: Create rows + $query = $this->getQuery(self::$CREATE_ROWS); + $rows = []; + for ($i = 1; $i <= 10; $i++) { + $rows[] = ['$id' => 'row' . $i, 'name' => 'Row #' . $i]; + } + + $payload['query'] = $query; + $payload['variables'] = [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'rows' => $rows, + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $this->assertCount(10, $res['body']['data']['tablesCreateRows']['rows']); + + return compact('databaseId', 'tableId', 'projectId'); + } + + /** + * @depends testBulkCreate + */ + public function testBulkUpdate(array $data): array + { + $userId = $this->getUser()['$id']; + $permissions = [ + Permission::read(Role::user($userId)), + Permission::update(Role::user($userId)), + Permission::delete(Role::user($userId)), + ]; + + $headers = [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectId'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]; + + // Step 1: Bulk update rows + $query = $this->getQuery(self::$UPDATE_ROWS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + 'data' => [ + 'name' => 'Rows Updated', + '$permissions' => $permissions, + ], + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $this->assertCount(10, $res['body']['data']['tablesUpdateRows']['rows']); + + // Step 2: Fetch and validate updated rows + $query = $this->getQuery(self::$GET_ROWS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + 'queries' => [Query::equal('name', ['Rows Updated'])->toString()], + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertEquals(200, $res['headers']['status-code']); + + $fetched = $res['body']['data']['tablesListRows']; + $this->assertEquals(10, $fetched['total']); + + foreach ($fetched['rows'] as $row) { + $this->assertEquals($permissions, $row['_permissions']); + $this->assertEquals($data['tableId'], $row['_tableId']); + $this->assertEquals($data['databaseId'], $row['_databaseId']); + $this->assertEquals('Rows Updated', json_decode($row['data'], true)['name']); + } + + return $data; + } + + /** + * @depends testBulkCreate + */ + public function testBulkUpsert(array $data): array + { + $userId = $this->getUser()['$id']; + $headers = [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectId'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]; + + $permissions = [ + Permission::read(Role::user($userId)), + Permission::update(Role::user($userId)), + Permission::delete(Role::user($userId)), + ]; + + // Step 1: Mutate row 10 and add row 11 + $query = $this->getQuery(self::$UPSERT_ROWS); + $upsertPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + 'rows' => [ + [ + '$id' => 'row10', + 'name' => 'Row #1000', + ], + [ + 'name' => 'Row #11', + ], + ], + ], + ]; + + $response = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $upsertPayload); + $this->assertArrayNotHasKey('errors', $response['body']); + + $rows = $response['body']['data']['tablesUpsertRows']['rows']; + $this->assertCount(2, $rows); + + $rowMap = []; + foreach ($rows as $row) { + $decoded = json_decode($row['data'], true); + $rowMap[$decoded['name']] = $decoded; + } + + $this->assertArrayHasKey('Row #1000', $rowMap); + $this->assertArrayHasKey('Row #11', $rowMap); + + // Step 2: Fetch all rows and confirm count is now 11 + $query = $this->getQuery(self::$GET_ROWS); + $fetchPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $fetchPayload); + $this->assertEquals(200, $res['headers']['status-code']); + + $fetched = $res['body']['data']['tablesListRows']; + $this->assertEquals(11, $fetched['total']); + + // Step 3: Upsert row with new permissions using `tablesUpsertRow` + $query = $this->getQuery(self::$UPSERT_ROW); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + 'rowId' => 'row10', + 'data' => ['name' => 'Row #10 Patched'], + 'permissions' => $permissions, + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + + $updated = $res['body']['data']['tablesUpsertRow']; + $this->assertEquals('Row #10 Patched', json_decode($updated['data'], true)['name']); + $this->assertEquals($data['databaseId'], $updated['_databaseId']); + $this->assertEquals($data['tableId'], $updated['_tableId']); + + return $data; + } + + /** + * @depends testBulkUpsert + */ + public function testBulkDelete(array $data): array + { + $headers = [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectId'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]; + + // Step 1: Perform bulk delete + $query = $this->getQuery(self::$DELETE_ROWS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + + $deleted = $res['body']['data']['tablesDeleteRows']['rows']; + $this->assertIsArray($deleted); + $this->assertCount(11, $deleted); + + // Step 2: Confirm deletion via refetch + $query = $this->getQuery(self::$GET_ROWS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertEquals(200, $res['headers']['status-code']); + $this->assertEquals(0, $res['body']['data']['tablesListRows']['total']); + + return $data; + } } diff --git a/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php b/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php index 4f711148e3..af72bb8a9f 100644 --- a/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php +++ b/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php @@ -134,6 +134,7 @@ class DatabaseServerTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), $gqlPayload); + // TODO: @itznotabug - check for `encrypt` attribute in string column's response body as well! $this->assertArrayNotHasKey('errors', $column['body']); $this->assertIsArray($column['body']['data']); $this->assertIsArray($column['body']['data']['tablesCreateStringColumn']); From 6e1fa0526d627e0e5f97dcf2a5c9b18c6f2dfb0f Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 13 Jun 2025 14:07:33 +0530 Subject: [PATCH 168/343] add: graphql tests for bulk apis to server tests. --- .../Collections/DatabaseServerTest.php | 172 ++++++++++++++++++ 1 file changed, 172 insertions(+) diff --git a/tests/e2e/Services/GraphQL/Collections/DatabaseServerTest.php b/tests/e2e/Services/GraphQL/Collections/DatabaseServerTest.php index f60acb9b0b..3e5b457308 100644 --- a/tests/e2e/Services/GraphQL/Collections/DatabaseServerTest.php +++ b/tests/e2e/Services/GraphQL/Collections/DatabaseServerTest.php @@ -1465,4 +1465,176 @@ class DatabaseServerTest extends Scope $this->assertIsNotArray($database['body']); $this->assertEquals(204, $database['headers']['status-code']); } + + /** + * @throws Exception + */ + public function testBulkCreateDocuments(): array + { + $project = $this->getProject(); + $projectId = $project['$id']; + $headers = array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()); + + // Step 1: Create database + $query = $this->getQuery(self::$CREATE_DATABASE); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => 'bulk', + 'name' => 'Bulk', + ], + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $databaseId = $res['body']['data']['databasesCreate']['_id']; + + // Step 2: Create collection + $query = $this->getQuery(self::$CREATE_COLLECTION); + $payload['query'] = $query; + $payload['variables'] = [ + 'databaseId' => $databaseId, + 'collectionId' => 'operations', + 'name' => 'Operations', + 'documentSecurity' => false, + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $collectionId = $res['body']['data']['databasesCreateCollection']['_id']; + + // Step 3: Create attribute + $query = $this->getQuery(self::$CREATE_STRING_ATTRIBUTE); + $payload['query'] = $query; + $payload['variables'] = [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + sleep(1); + + // Step 4: Create documents + $query = $this->getQuery(self::$CREATE_DOCUMENTS); + $documents = []; + for ($i = 1; $i <= 10; $i++) { + $documents[] = ['$id' => 'doc' . $i, 'name' => 'Doc #' . $i]; + } + + $payload['query'] = $query; + $payload['variables'] = [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'documents' => $documents, + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $this->assertCount(10, $res['body']['data']['collectionsCreateDocuments']['documents']); + + return [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'projectId' => $projectId, + ]; + } + + /** + * @depends testBulkCreateDocuments + */ + public function testBulkUpdateDocuments(array $data): array + { + $userId = $this->getUser()['$id']; + $permissions = [ + Permission::read(Role::user($userId)), + Permission::update(Role::user($userId)), + Permission::delete(Role::user($userId)), + ]; + + $headers = array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectId'], + ], $this->getHeaders()); + + $query = $this->getQuery(self::$UPDATE_DOCUMENTS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'collectionId' => $data['collectionId'], + 'data' => [ + 'name' => 'Docs Updated', + '$permissions' => $permissions, + ], + ], + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $this->assertCount(10, $res['body']['data']['collectionsUpdateDocuments']['documents']); + + return $data; + } + + /** + * @depends testBulkUpdateDocuments + */ + public function testBulkUpsertDocuments(array $data): array + { + $headers = array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectId'], + ], $this->getHeaders()); + + // Upsert: Update one, insert one + $query = $this->getQuery(self::$UPSERT_DOCUMENTS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'collectionId' => $data['collectionId'], + 'documents' => [ + ['$id' => 'doc10', 'name' => 'Doc #1000'], + ['name' => 'Doc #11'], + ], + ], + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $this->assertCount(2, $res['body']['data']['collectionsUpsertDocuments']['documents']); + + return $data; + } + + /** + * @depends testBulkUpsertDocuments + */ + public function testBulkDeleteDocuments(array $data): array + { + $headers = array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectId'], + ], $this->getHeaders()); + + $query = $this->getQuery(self::$DELETE_DOCUMENTS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'collectionId' => $data['collectionId'], + ], + ]; + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $this->assertCount(11, $res['body']['data']['collectionsDeleteDocuments']['documents']); + + return $data; + } } From 9cfff792fdcc6617edf4445a2152528ff87529d4 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 13 Jun 2025 14:13:26 +0530 Subject: [PATCH 169/343] add: graphql tests for bulk apis to server tests. --- .../GraphQL/Tables/DatabaseServerTest.php | 279 ++++++++++++++++++ 1 file changed, 279 insertions(+) diff --git a/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php b/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php index af72bb8a9f..61cb57911a 100644 --- a/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php +++ b/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php @@ -12,6 +12,7 @@ use Utopia\Database\Database; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; class DatabaseServerTest extends Scope { @@ -1465,4 +1466,282 @@ class DatabaseServerTest extends Scope $this->assertIsNotArray($database['body']); $this->assertEquals(204, $database['headers']['status-code']); } + + /** + * @throws Exception + */ + public function testBulkCreate(): array + { + $project = $this->getProject(); + $projectId = $project['$id']; + $headers = array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()); + + // Step 1: Create database + $query = $this->getQuery(self::$CREATE_DATABASE); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => 'bulk', + 'name' => 'Bulk', + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $databaseId = $res['body']['data']['databasesCreate']['_id']; + + // Step 2: Create table + $query = $this->getQuery(self::$CREATE_TABLE); + $payload['query'] = $query; + $payload['variables'] = [ + 'databaseId' => $databaseId, + 'tableId' => 'operations', + 'name' => 'Operations', + 'rowSecurity' => false, + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $tableId = $res['body']['data']['databasesCreateTable']['_id']; + + // Step 3: Create column + $query = $this->getQuery(self::$CREATE_STRING_COLUMN); + $payload['query'] = $query; + $payload['variables'] = [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + sleep(1); + + // Step 4: Create rows + $query = $this->getQuery(self::$CREATE_ROWS); + $rows = []; + for ($i = 1; $i <= 10; $i++) { + $rows[] = ['$id' => 'row' . $i, 'name' => 'Row #' . $i]; + } + + $payload['query'] = $query; + $payload['variables'] = [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'rows' => $rows, + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $this->assertCount(10, $res['body']['data']['tablesCreateRows']['rows']); + + return compact('databaseId', 'tableId', 'projectId'); + } + + /** + * @depends testBulkCreate + */ + public function testBulkUpdate(array $data): array + { + $userId = $this->getUser()['$id']; + $permissions = [ + Permission::read(Role::user($userId)), + Permission::update(Role::user($userId)), + Permission::delete(Role::user($userId)), + ]; + + $headers = array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectId'], + ], $this->getHeaders()); + + // Step 1: Bulk update rows + $query = $this->getQuery(self::$UPDATE_ROWS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + 'data' => [ + 'name' => 'Rows Updated', + '$permissions' => $permissions, + ], + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + $this->assertCount(10, $res['body']['data']['tablesUpdateRows']['rows']); + + // Step 2: Fetch and validate updated rows + $query = $this->getQuery(self::$GET_ROWS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + 'queries' => [Query::equal('name', ['Rows Updated'])->toString()], + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertEquals(200, $res['headers']['status-code']); + + $fetched = $res['body']['data']['tablesListRows']; + $this->assertEquals(10, $fetched['total']); + + foreach ($fetched['rows'] as $row) { + $this->assertEquals($permissions, $row['_permissions']); + $this->assertEquals($data['tableId'], $row['_tableId']); + $this->assertEquals($data['databaseId'], $row['_databaseId']); + $this->assertEquals('Rows Updated', json_decode($row['data'], true)['name']); + } + + return $data; + } + + /** + * @depends testBulkCreate + */ + public function testBulkUpsert(array $data): array + { + $userId = $this->getUser()['$id']; + $headers = array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectId'], + ], $this->getHeaders()); + + $permissions = [ + Permission::read(Role::user($userId)), + Permission::update(Role::user($userId)), + Permission::delete(Role::user($userId)), + ]; + + // Step 1: Mutate row 10 and add row 11 + $query = $this->getQuery(self::$UPSERT_ROWS); + $upsertPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + 'rows' => [ + [ + '$id' => 'row10', + 'name' => 'Row #1000', + ], + [ + 'name' => 'Row #11', + ], + ], + ], + ]; + + $response = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $upsertPayload); + $this->assertArrayNotHasKey('errors', $response['body']); + + $rows = $response['body']['data']['tablesUpsertRows']['rows']; + $this->assertCount(2, $rows); + + $rowMap = []; + foreach ($rows as $row) { + $decoded = json_decode($row['data'], true); + $rowMap[$decoded['name']] = $decoded; + } + + $this->assertArrayHasKey('Row #1000', $rowMap); + $this->assertArrayHasKey('Row #11', $rowMap); + + // Step 2: Fetch all rows and confirm count is now 11 + $query = $this->getQuery(self::$GET_ROWS); + $fetchPayload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $fetchPayload); + $this->assertEquals(200, $res['headers']['status-code']); + + $fetched = $res['body']['data']['tablesListRows']; + $this->assertEquals(11, $fetched['total']); + + // Step 3: Upsert row with new permissions using `tablesUpsertRow` + $query = $this->getQuery(self::$UPSERT_ROW); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + 'rowId' => 'row10', + 'data' => ['name' => 'Row #10 Patched'], + 'permissions' => $permissions, + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + + $updated = $res['body']['data']['tablesUpsertRow']; + $this->assertEquals('Row #10 Patched', json_decode($updated['data'], true)['name']); + $this->assertEquals($data['databaseId'], $updated['_databaseId']); + $this->assertEquals($data['tableId'], $updated['_tableId']); + + return $data; + } + + /** + * @depends testBulkUpsert + */ + public function testBulkDelete(array $data): array + { + $headers = array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectId'], + ], $this->getHeaders()); + + // Step 1: Perform bulk delete + $query = $this->getQuery(self::$DELETE_ROWS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertArrayNotHasKey('errors', $res['body']); + + $deleted = $res['body']['data']['tablesDeleteRows']['rows']; + $this->assertIsArray($deleted); + $this->assertCount(11, $deleted); + + // Step 2: Confirm deletion via refetch + $query = $this->getQuery(self::$GET_ROWS); + $payload = [ + 'query' => $query, + 'variables' => [ + 'databaseId' => $data['databaseId'], + 'tableId' => $data['tableId'], + ], + ]; + + $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); + $this->assertEquals(200, $res['headers']['status-code']); + $this->assertEquals(0, $res['body']['data']['tablesListRows']['total']); + + return $data; + } } From 8cbd06173db748191d4ee6f2794b5e7fbf1ad2eb Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 13 Jun 2025 15:11:18 +0530 Subject: [PATCH 170/343] update: realtime channels checks for tables api. --- .../Services/Realtime/RealtimeCustomClientTest.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index 7f5e2a9da8..6d6c0d18a4 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -81,11 +81,17 @@ class RealtimeCustomClientTest extends Scope 'files', 'files.1', 'collections', + 'tables', 'collections.1.documents', 'collections.2.documents', + 'tables.1.rows', + 'tables.2.rows', 'documents', + 'rows', 'collections.1.documents.1', 'collections.2.documents.2', + 'tables.1.rows.1', + 'tables.2.rows.2', ], $headers); $response = json_decode($client->receive(), true); @@ -95,17 +101,22 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals('connected', $response['type']); $this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']['user']); - $this->assertCount(10, $response['data']['channels']); + $this->assertCount(16, $response['data']['channels']); $this->assertContains('account', $response['data']['channels']); $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains('files', $response['data']['channels']); $this->assertContains('files.1', $response['data']['channels']); $this->assertContains('collections', $response['data']['channels']); + $this->assertContains('tables', $response['data']['channels']); $this->assertContains('collections.1.documents', $response['data']['channels']); $this->assertContains('collections.2.documents', $response['data']['channels']); + $this->assertContains('tables.1.rows', $response['data']['channels']); + $this->assertContains('tables.2.rows', $response['data']['channels']); $this->assertContains('documents', $response['data']['channels']); $this->assertContains('collections.1.documents.1', $response['data']['channels']); $this->assertContains('collections.2.documents.2', $response['data']['channels']); + $this->assertContains('tables.1.rows.1', $response['data']['channels']); + $this->assertContains('tables.2.rows.2', $response['data']['channels']); $this->assertEquals($userId, $response['data']['user']['$id']); $client->close(); From 8d74083da3a6b214c557d22fed943d7859652299 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 13 Jun 2025 15:18:21 +0530 Subject: [PATCH 171/343] remove: filter queries. --- .../Databases/Http/Databases/Collections/Attributes/XList.php | 4 +--- .../Databases/Http/Databases/Collections/Indexes/XList.php | 3 +-- .../Modules/Databases/Http/Databases/Collections/XList.php | 4 +--- .../Platform/Modules/Databases/Http/Databases/XList.php | 4 +--- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index b9f1450fa3..2509115e13 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -118,11 +118,9 @@ class XList extends Action $cursor->setValue($cursorDocument); } - $filterQueries = Query::groupByType($queries)['filters']; - try { $attributes = $dbForProject->find('attributes', $queries); - $total = $dbForProject->count('attributes', $filterQueries, APP_LIMIT_COUNT); + $total = $dbForProject->count('attributes', $queries, APP_LIMIT_COUNT); } catch (OrderException $e) { $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; $attribute = $this->isCollectionsAPI() ? 'attribute' : 'column'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index 13717034ce..dae25a3335 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -122,9 +122,8 @@ class XList extends Action $cursor->setValue($cursorDocument[0]); } - $filterQueries = Query::groupByType($queries)['filters']; try { - $total = $dbForProject->count('indexes', $filterQueries, APP_LIMIT_COUNT); + $total = $dbForProject->count('indexes', $queries, APP_LIMIT_COUNT); $indexes = $dbForProject->find('indexes', $queries); } catch (OrderException $e) { $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index 06a6d2cd39..d3ddb9301f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -108,11 +108,9 @@ class XList extends Action $cursor->setValue($cursorDocument); } - $filterQueries = Query::groupByType($queries)['filters']; - try { $collections = $dbForProject->find('database_' . $database->getSequence(), $queries); - $total = $dbForProject->count('database_' . $database->getSequence(), $filterQueries, APP_LIMIT_COUNT); + $total = $dbForProject->count('database_' . $database->getSequence(), $queries, APP_LIMIT_COUNT); } catch (OrderException) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL); } catch (QueryException) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php index dcf7e2d724..7179be90ec 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php @@ -92,11 +92,9 @@ class XList extends Action $cursor->setValue($cursorDocument); } - $filterQueries = Query::groupByType($queries)['filters']; - try { $databases = $dbForProject->find('databases', $queries); - $total = $dbForProject->count('databases', $filterQueries, APP_LIMIT_COUNT); + $total = $dbForProject->count('databases', $queries, APP_LIMIT_COUNT); } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); } catch (QueryException) { From cee6420fa2e5545e4e9302d1daf9809477c1a211 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Fri, 13 Jun 2025 15:50:53 +0530 Subject: [PATCH 172/343] Use env vars instead of request --- .env | 1 + app/config/templates/site.php | 5 ----- app/controllers/api/vcs.php | 16 +++++++++++----- app/controllers/general.php | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/.env b/.env index b7dd9e24f3..42c23ac87f 100644 --- a/.env +++ b/.env @@ -22,6 +22,7 @@ _APP_OPTIONS_FORCE_HTTPS=disabled _APP_OPTIONS_ROUTER_FORCE_HTTPS=disabled _APP_OPENSSL_KEY_V1=your-secret-key _APP_DOMAIN=traefik +_APP_CONSOLE_DOMAIN=localhost _APP_DOMAIN_FUNCTIONS=functions.localhost _APP_DOMAIN_SITES=sites.localhost _APP_DOMAIN_TARGET_CNAME=test.localhost diff --git a/app/config/templates/site.php b/app/config/templates/site.php index 725e6fa918..47a436b44e 100644 --- a/app/config/templates/site.php +++ b/app/config/templates/site.php @@ -9,11 +9,6 @@ use Utopia\System\System; $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); -// TODO: Development override -if (System::getEnv('_APP_ENV') === 'development') { - $hostname = 'localhost'; -} - $url = $protocol . '://' . $hostname; class UseCases diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 79050c2913..a7f8ee7718 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -116,8 +116,10 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } $commentStatus = $isAuthorized ? 'waiting' : 'failed'; + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); - $authorizeUrl = $request->getProtocol() . '://' . $request->getHostname() . "/console/git/authorize-contributor?projectId={$projectId}&installationId={$installationId}&repositoryId={$repositoryId}&providerPullRequestId={$providerPullRequestId}"; + $authorizeUrl = $protocol . '://' . $hostname . "/console/git/authorize-contributor?projectId={$projectId}&installationId={$installationId}&repositoryId={$repositoryId}&providerPullRequestId={$providerPullRequestId}"; $action = $isAuthorized ? ['type' => 'logs'] : ['type' => 'authorize', 'url' => $authorizeUrl]; @@ -378,7 +380,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } $owner = $github->getOwnerName($providerInstallationId); - $providerTargetUrl = $request->getProtocol() . '://' . $request->getHostname() . "/console/project-$region-$projectId/$resourceCollection/$resourceType-$resourceId"; + $providerTargetUrl = $protocol . '://' . $hostname . "/console/project-$region-$projectId/$resourceCollection/$resourceType-$resourceId"; $github->updateCommitStatus($repositoryName, $providerCommitHash, $owner, 'pending', $message, $providerTargetUrl, $name); } @@ -437,6 +439,8 @@ App::get('/v1/vcs/github/authorize') ]); $appName = System::getEnv('_APP_VCS_GITHUB_APP_NAME'); + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); if (empty($appName)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'GitHub App name is not configured. Please configure VCS (Version Control System) variables in .env file.'); @@ -444,7 +448,7 @@ App::get('/v1/vcs/github/authorize') $url = "https://github.com/apps/$appName/installations/new?" . \http_build_query([ 'state' => $state, - 'redirect_uri' => $request->getProtocol() . '://' . $request->getHostname() . "/v1/vcs/github/callback" + 'redirect_uri' => $protocol . '://' . $hostname . "/v1/vcs/github/callback" ]); $response @@ -494,10 +498,12 @@ App::get('/v1/vcs/github/callback') } $region = $project->getAttribute('region', 'default'); + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $defaultState = [ - 'success' => $request->getProtocol() . '://' . $request->getHostname() . "/console/project-$region-$projectId/settings/git-installations", - 'failure' => $request->getProtocol() . '://' . $request->getHostname() . "/console/project-$region-$projectId/settings/git-installations", + 'success' => $protocol . '://' . $hostname . "/console/project-$region-$projectId/settings/git-installations", + 'failure' => $protocol . '://' . $hostname . "/console/project-$region-$projectId/settings/git-installations", ]; $state = \array_merge($defaultState, $state ?? []); diff --git a/app/controllers/general.php b/app/controllers/general.php index 724e69f61f..858ac2c4c3 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -810,7 +810,7 @@ App::init() * Appwrite Router */ $host = $request->getHostname() ?? ''; - $mainDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain || !empty($previewHostname)) { if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { From 37388fcf1b4a6ea1cee8a2952e534090b0a275b5 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Fri, 13 Jun 2025 18:08:19 +0530 Subject: [PATCH 173/343] Change php version in composer.lock --- composer.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.lock b/composer.lock index fdde3f2750..3120d937ae 100644 --- a/composer.lock +++ b/composer.lock @@ -3357,7 +3357,7 @@ "shasum": "" }, "require": { - "php": ">=7.4", + "php": ">=8.3", "utopia-php/framework": "0.*.*" }, "require-dev": { From fc656167d5c659c2e32afe29a52877888c6d4f35 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Fri, 13 Jun 2025 18:11:51 +0530 Subject: [PATCH 174/343] Composer update --- composer.lock | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/composer.lock b/composer.lock index 3120d937ae..4e434d714a 100644 --- a/composer.lock +++ b/composer.lock @@ -3357,7 +3357,7 @@ "shasum": "" }, "require": { - "php": ">=8.3", + "php": ">=7.4", "utopia-php/framework": "0.*.*" }, "require-dev": { @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.41.4", + "version": "0.41.6", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "07804269131f411576aac60c795a5ebc3afaa48a" + "reference": "bfcebb968c527e17fdf18d40b8986c83d9c18c93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/07804269131f411576aac60c795a5ebc3afaa48a", - "reference": "07804269131f411576aac60c795a5ebc3afaa48a", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/bfcebb968c527e17fdf18d40b8986c83d9c18c93", + "reference": "bfcebb968c527e17fdf18d40b8986c83d9c18c93", "shasum": "" }, "require": { @@ -4852,9 +4852,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.41.4" + "source": "https://github.com/appwrite/sdk-generator/tree/0.41.6" }, - "time": "2025-06-10T08:28:11+00:00" + "time": "2025-06-12T03:27:26+00:00" }, { "name": "doctrine/annotations", @@ -5147,16 +5147,16 @@ }, { "name": "matthiasmullie/minify", - "version": "1.3.73", + "version": "1.3.74", "source": { "type": "git", "url": "https://github.com/matthiasmullie/minify.git", - "reference": "cb7a9297b4ab070909cefade30ee95054d4ae87a" + "reference": "a2593286a4135d03c6a6a9e9aeded5d41e931ce4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/cb7a9297b4ab070909cefade30ee95054d4ae87a", - "reference": "cb7a9297b4ab070909cefade30ee95054d4ae87a", + "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/a2593286a4135d03c6a6a9e9aeded5d41e931ce4", + "reference": "a2593286a4135d03c6a6a9e9aeded5d41e931ce4", "shasum": "" }, "require": { @@ -5167,8 +5167,7 @@ "require-dev": { "friendsofphp/php-cs-fixer": ">=2.0", "matthiasmullie/scrapbook": ">=1.3", - "phpunit/phpunit": ">=4.8", - "squizlabs/php_codesniffer": ">=3.0" + "phpunit/phpunit": ">=4.8" }, "suggest": { "psr/cache-implementation": "Cache implementation to use with Minify::cache" @@ -5206,7 +5205,7 @@ ], "support": { "issues": "https://github.com/matthiasmullie/minify/issues", - "source": "https://github.com/matthiasmullie/minify/tree/1.3.73" + "source": "https://github.com/matthiasmullie/minify/tree/1.3.74" }, "funding": [ { @@ -5214,7 +5213,7 @@ "type": "github" } ], - "time": "2024-03-15T10:27:10+00:00" + "time": "2025-06-12T08:06:04+00:00" }, { "name": "matthiasmullie/path-converter", From 050a563db1220ef5e414b275ec9bc22c8a8a9b3f Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Sat, 14 Jun 2025 13:24:10 +0530 Subject: [PATCH 175/343] chore: update cli version and add bulk operation warnings --- app/config/platforms.php | 2 +- app/config/specs/open-api3-1.7.x-client.json | 28 ++++++++- app/config/specs/open-api3-1.7.x-console.json | 63 +++++++++++++++---- app/config/specs/open-api3-1.7.x-server.json | 29 ++++++--- app/config/specs/open-api3-latest-client.json | 4 +- .../specs/open-api3-latest-console.json | 10 +-- app/config/specs/open-api3-latest-server.json | 10 +-- app/config/specs/swagger2-1.7.x-client.json | 28 ++++++++- app/config/specs/swagger2-1.7.x-console.json | 63 +++++++++++++++---- app/config/specs/swagger2-1.7.x-server.json | 29 ++++++--- app/config/specs/swagger2-latest-client.json | 4 +- app/config/specs/swagger2-latest-console.json | 10 +-- app/config/specs/swagger2-latest-server.json | 10 +-- composer.lock | 27 ++++---- .../examples/proxy/create-redirect-rule.md | 4 +- .../examples/vcs/get-repository-contents.md | 1 + docs/references/databases/create-documents.md | 2 + docs/references/databases/delete-documents.md | 2 + docs/references/databases/update-documents.md | 2 + docs/references/databases/upsert-document.md | 2 + docs/references/databases/upsert-documents.md | 4 +- 21 files changed, 247 insertions(+), 87 deletions(-) diff --git a/app/config/platforms.php b/app/config/platforms.php index f08401e8fa..e2e6fdd4eb 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -217,7 +217,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '8.0.0', + 'version' => '8.0.1', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, diff --git a/app/config/specs/open-api3-1.7.x-client.json b/app/config/specs/open-api3-1.7.x-client.json index bbb78c6c66..9f1215c222 100644 --- a/app/config/specs/open-api3-1.7.x-client.json +++ b/app/config/specs/open-api3-1.7.x-client.json @@ -4490,6 +4490,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/components\/schemas\/documentList" + } + ], + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -4666,7 +4689,7 @@ "tags": [ "databases" ], - "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Document", @@ -6595,7 +6618,8 @@ "png", "webp", "heic", - "avif" + "avif", + "gif" ], "x-enum-name": "ImageFormat", "x-enum-keys": [], diff --git a/app/config/specs/open-api3-1.7.x-console.json b/app/config/specs/open-api3-1.7.x-console.json index 90ef137fc2..48440caac4 100644 --- a/app/config/specs/open-api3-1.7.x-console.json +++ b/app/config/specs/open-api3-1.7.x-console.json @@ -8071,7 +8071,7 @@ "model": "#\/components\/schemas\/documentList" } ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -8151,7 +8151,7 @@ "tags": [ "databases" ], - "description": "Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Documents List", @@ -8242,7 +8242,7 @@ "tags": [ "databases" ], - "description": "Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nUpdate all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", "responses": { "200": { "description": "Documents List", @@ -8335,7 +8335,7 @@ "tags": [ "databases" ], - "description": "Bulk delete documents using queries, if no queries are passed then all documents are deleted.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nBulk delete documents using queries, if no queries are passed then all documents are deleted.", "responses": { "200": { "description": "Documents List", @@ -8520,7 +8520,7 @@ "tags": [ "databases" ], - "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Document", @@ -9767,6 +9767,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -9792,7 +9793,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -10395,6 +10397,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -10420,7 +10423,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -25446,12 +25450,33 @@ "Temporary Redirect 307", "Permanent Redirect 308" ] + }, + "resourceId": { + "type": "string", + "description": "ID of parent resource.", + "x-example": "" + }, + "resourceType": { + "type": "string", + "description": "Type of parent resource.", + "x-example": "site", + "enum": [ + "site", + "function" + ], + "x-enum-name": "ProxyResourceType", + "x-enum-keys": [ + "Site", + "Function" + ] } }, "required": [ "domain", "url", - "statusCode" + "statusCode", + "resourceId", + "resourceType" ] } } @@ -25936,6 +25961,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -25961,7 +25987,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -26580,6 +26607,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -26605,7 +26633,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -29364,7 +29393,8 @@ "png", "webp", "heic", - "avif" + "avif", + "gif" ], "x-enum-name": "ImageFormat", "x-enum-keys": [], @@ -34846,6 +34876,17 @@ "default": "" }, "in": "query" + }, + { + "name": "providerReference", + "description": "Git reference (branch, tag, commit) to get contents from", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" } ] } diff --git a/app/config/specs/open-api3-1.7.x-server.json b/app/config/specs/open-api3-1.7.x-server.json index 1ae9328864..4a6a4f3b4f 100644 --- a/app/config/specs/open-api3-1.7.x-server.json +++ b/app/config/specs/open-api3-1.7.x-server.json @@ -7552,7 +7552,7 @@ "model": "#\/components\/schemas\/documentList" } ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -7634,7 +7634,7 @@ "tags": [ "databases" ], - "description": "Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Documents List", @@ -7726,7 +7726,7 @@ "tags": [ "databases" ], - "description": "Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nUpdate all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", "responses": { "200": { "description": "Documents List", @@ -7820,7 +7820,7 @@ "tags": [ "databases" ], - "description": "Bulk delete documents using queries, if no queries are passed then all documents are deleted.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nBulk delete documents using queries, if no queries are passed then all documents are deleted.", "responses": { "200": { "description": "Documents List", @@ -8008,7 +8008,7 @@ "tags": [ "databases" ], - "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Document", @@ -8844,6 +8844,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -8869,7 +8870,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -9244,6 +9246,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -9269,7 +9272,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -17490,6 +17494,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -17515,7 +17520,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -17906,6 +17912,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -17931,7 +17938,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -20646,7 +20654,8 @@ "png", "webp", "heic", - "avif" + "avif", + "gif" ], "x-enum-name": "ImageFormat", "x-enum-keys": [], diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 807903b764..9f1215c222 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -4512,7 +4512,7 @@ "model": "#\/components\/schemas\/documentList" } ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -4689,7 +4689,7 @@ "tags": [ "databases" ], - "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Document", diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index cc4753dd4a..48440caac4 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -8071,7 +8071,7 @@ "model": "#\/components\/schemas\/documentList" } ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -8151,7 +8151,7 @@ "tags": [ "databases" ], - "description": "Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Documents List", @@ -8242,7 +8242,7 @@ "tags": [ "databases" ], - "description": "Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nUpdate all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", "responses": { "200": { "description": "Documents List", @@ -8335,7 +8335,7 @@ "tags": [ "databases" ], - "description": "Bulk delete documents using queries, if no queries are passed then all documents are deleted.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nBulk delete documents using queries, if no queries are passed then all documents are deleted.", "responses": { "200": { "description": "Documents List", @@ -8520,7 +8520,7 @@ "tags": [ "databases" ], - "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Document", diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index cc0abd241d..4a6a4f3b4f 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -7552,7 +7552,7 @@ "model": "#\/components\/schemas\/documentList" } ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -7634,7 +7634,7 @@ "tags": [ "databases" ], - "description": "Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Documents List", @@ -7726,7 +7726,7 @@ "tags": [ "databases" ], - "description": "Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nUpdate all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", "responses": { "200": { "description": "Documents List", @@ -7820,7 +7820,7 @@ "tags": [ "databases" ], - "description": "Bulk delete documents using queries, if no queries are passed then all documents are deleted.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nBulk delete documents using queries, if no queries are passed then all documents are deleted.", "responses": { "200": { "description": "Documents List", @@ -8008,7 +8008,7 @@ "tags": [ "databases" ], - "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Document", diff --git a/app/config/specs/swagger2-1.7.x-client.json b/app/config/specs/swagger2-1.7.x-client.json index 92132151b4..fce7991c6e 100644 --- a/app/config/specs/swagger2-1.7.x-client.json +++ b/app/config/specs/swagger2-1.7.x-client.json @@ -4636,6 +4636,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/definitions\/documentList" + } + ], + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -4809,7 +4832,7 @@ "tags": [ "databases" ], - "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Document", @@ -6729,7 +6752,8 @@ "png", "webp", "heic", - "avif" + "avif", + "gif" ], "x-enum-name": "ImageFormat", "x-enum-keys": [], diff --git a/app/config/specs/swagger2-1.7.x-console.json b/app/config/specs/swagger2-1.7.x-console.json index e53a0dfb0b..9b2696efe5 100644 --- a/app/config/specs/swagger2-1.7.x-console.json +++ b/app/config/specs/swagger2-1.7.x-console.json @@ -8200,7 +8200,7 @@ "model": "#\/definitions\/documentList" } ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -8284,7 +8284,7 @@ "tags": [ "databases" ], - "description": "Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Documents List", @@ -8372,7 +8372,7 @@ "tags": [ "databases" ], - "description": "Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nUpdate all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", "responses": { "200": { "description": "Documents List", @@ -8463,7 +8463,7 @@ "tags": [ "databases" ], - "description": "Bulk delete documents using queries, if no queries are passed then all documents are deleted.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nBulk delete documents using queries, if no queries are passed then all documents are deleted.", "responses": { "200": { "description": "Documents List", @@ -8638,7 +8638,7 @@ "tags": [ "databases" ], - "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Document", @@ -9835,6 +9835,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -9860,7 +9861,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -10466,6 +10468,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -10491,7 +10494,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -25696,12 +25700,35 @@ "Temporary Redirect 307", "Permanent Redirect 308" ] + }, + "resourceId": { + "type": "string", + "description": "ID of parent resource.", + "default": null, + "x-example": "" + }, + "resourceType": { + "type": "string", + "description": "Type of parent resource.", + "default": null, + "x-example": "site", + "enum": [ + "site", + "function" + ], + "x-enum-name": "ProxyResourceType", + "x-enum-keys": [ + "Site", + "Function" + ] } }, "required": [ "domain", "url", - "statusCode" + "statusCode", + "resourceId", + "resourceType" ] } } @@ -26203,6 +26230,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -26228,7 +26256,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -26850,6 +26879,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -26875,7 +26905,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -29604,7 +29635,8 @@ "png", "webp", "heic", - "avif" + "avif", + "gif" ], "x-enum-name": "ImageFormat", "x-enum-keys": [], @@ -35063,6 +35095,15 @@ "x-example": "", "default": "", "in": "query" + }, + { + "name": "providerReference", + "description": "Git reference (branch, tag, commit) to get contents from", + "required": false, + "type": "string", + "x-example": "", + "default": "", + "in": "query" } ] } diff --git a/app/config/specs/swagger2-1.7.x-server.json b/app/config/specs/swagger2-1.7.x-server.json index 083290bcc0..aba8aa5032 100644 --- a/app/config/specs/swagger2-1.7.x-server.json +++ b/app/config/specs/swagger2-1.7.x-server.json @@ -7671,7 +7671,7 @@ "model": "#\/definitions\/documentList" } ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -7757,7 +7757,7 @@ "tags": [ "databases" ], - "description": "Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Documents List", @@ -7846,7 +7846,7 @@ "tags": [ "databases" ], - "description": "Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nUpdate all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", "responses": { "200": { "description": "Documents List", @@ -7938,7 +7938,7 @@ "tags": [ "databases" ], - "description": "Bulk delete documents using queries, if no queries are passed then all documents are deleted.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nBulk delete documents using queries, if no queries are passed then all documents are deleted.", "responses": { "200": { "description": "Documents List", @@ -8116,7 +8116,7 @@ "tags": [ "databases" ], - "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Document", @@ -8927,6 +8927,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -8952,7 +8953,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -9340,6 +9342,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -9365,7 +9368,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -17792,6 +17796,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -17817,7 +17822,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -18221,6 +18227,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -18246,7 +18253,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -20935,7 +20943,8 @@ "png", "webp", "heic", - "avif" + "avif", + "gif" ], "x-enum-name": "ImageFormat", "x-enum-keys": [], diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index b3f41e101c..fce7991c6e 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -4658,7 +4658,7 @@ "model": "#\/definitions\/documentList" } ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -4832,7 +4832,7 @@ "tags": [ "databases" ], - "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Document", diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 4e60716c4b..9b2696efe5 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -8200,7 +8200,7 @@ "model": "#\/definitions\/documentList" } ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -8284,7 +8284,7 @@ "tags": [ "databases" ], - "description": "Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Documents List", @@ -8372,7 +8372,7 @@ "tags": [ "databases" ], - "description": "Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nUpdate all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", "responses": { "200": { "description": "Documents List", @@ -8463,7 +8463,7 @@ "tags": [ "databases" ], - "description": "Bulk delete documents using queries, if no queries are passed then all documents are deleted.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nBulk delete documents using queries, if no queries are passed then all documents are deleted.", "responses": { "200": { "description": "Documents List", @@ -8638,7 +8638,7 @@ "tags": [ "databases" ], - "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Document", diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 4c7c193858..aba8aa5032 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -7671,7 +7671,7 @@ "model": "#\/definitions\/documentList" } ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -7757,7 +7757,7 @@ "tags": [ "databases" ], - "description": "Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Documents List", @@ -7846,7 +7846,7 @@ "tags": [ "databases" ], - "description": "Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nUpdate all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", "responses": { "200": { "description": "Documents List", @@ -7938,7 +7938,7 @@ "tags": [ "databases" ], - "description": "Bulk delete documents using queries, if no queries are passed then all documents are deleted.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nBulk delete documents using queries, if no queries are passed then all documents are deleted.", "responses": { "200": { "description": "Documents List", @@ -8116,7 +8116,7 @@ "tags": [ "databases" ], - "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", "responses": { "200": { "description": "Document", diff --git a/composer.lock b/composer.lock index fdde3f2750..644b147d26 100644 --- a/composer.lock +++ b/composer.lock @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.41.4", + "version": "0.41.7", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "07804269131f411576aac60c795a5ebc3afaa48a" + "reference": "d8c7bb26ea32ab378faf4e0dfa62fd15fe37c57b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/07804269131f411576aac60c795a5ebc3afaa48a", - "reference": "07804269131f411576aac60c795a5ebc3afaa48a", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/d8c7bb26ea32ab378faf4e0dfa62fd15fe37c57b", + "reference": "d8c7bb26ea32ab378faf4e0dfa62fd15fe37c57b", "shasum": "" }, "require": { @@ -4852,9 +4852,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.41.4" + "source": "https://github.com/appwrite/sdk-generator/tree/0.41.7" }, - "time": "2025-06-10T08:28:11+00:00" + "time": "2025-06-13T17:05:57+00:00" }, { "name": "doctrine/annotations", @@ -5147,16 +5147,16 @@ }, { "name": "matthiasmullie/minify", - "version": "1.3.73", + "version": "1.3.74", "source": { "type": "git", "url": "https://github.com/matthiasmullie/minify.git", - "reference": "cb7a9297b4ab070909cefade30ee95054d4ae87a" + "reference": "a2593286a4135d03c6a6a9e9aeded5d41e931ce4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/cb7a9297b4ab070909cefade30ee95054d4ae87a", - "reference": "cb7a9297b4ab070909cefade30ee95054d4ae87a", + "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/a2593286a4135d03c6a6a9e9aeded5d41e931ce4", + "reference": "a2593286a4135d03c6a6a9e9aeded5d41e931ce4", "shasum": "" }, "require": { @@ -5167,8 +5167,7 @@ "require-dev": { "friendsofphp/php-cs-fixer": ">=2.0", "matthiasmullie/scrapbook": ">=1.3", - "phpunit/phpunit": ">=4.8", - "squizlabs/php_codesniffer": ">=3.0" + "phpunit/phpunit": ">=4.8" }, "suggest": { "psr/cache-implementation": "Cache implementation to use with Minify::cache" @@ -5206,7 +5205,7 @@ ], "support": { "issues": "https://github.com/matthiasmullie/minify/issues", - "source": "https://github.com/matthiasmullie/minify/tree/1.3.73" + "source": "https://github.com/matthiasmullie/minify/tree/1.3.74" }, "funding": [ { @@ -5214,7 +5213,7 @@ "type": "github" } ], - "time": "2024-03-15T10:27:10+00:00" + "time": "2025-06-12T08:06:04+00:00" }, { "name": "matthiasmullie/path-converter", diff --git a/docs/examples/1.7.x/console-cli/examples/proxy/create-redirect-rule.md b/docs/examples/1.7.x/console-cli/examples/proxy/create-redirect-rule.md index f975ce686e..ec9098a748 100644 --- a/docs/examples/1.7.x/console-cli/examples/proxy/create-redirect-rule.md +++ b/docs/examples/1.7.x/console-cli/examples/proxy/create-redirect-rule.md @@ -1,4 +1,6 @@ appwrite proxy createRedirectRule \ --domain '' \ --url https://example.com \ - --statusCode 301 + --statusCode 301 \ + --resourceId \ + --resourceType site diff --git a/docs/examples/1.7.x/console-cli/examples/vcs/get-repository-contents.md b/docs/examples/1.7.x/console-cli/examples/vcs/get-repository-contents.md index 7d378d7efa..3ba8d75c91 100644 --- a/docs/examples/1.7.x/console-cli/examples/vcs/get-repository-contents.md +++ b/docs/examples/1.7.x/console-cli/examples/vcs/get-repository-contents.md @@ -2,3 +2,4 @@ appwrite vcs getRepositoryContents \ --installationId \ --providerRepositoryId \ + diff --git a/docs/references/databases/create-documents.md b/docs/references/databases/create-documents.md index a02d7c8bf1..7f60c138ea 100644 --- a/docs/references/databases/create-documents.md +++ b/docs/references/databases/create-documents.md @@ -1 +1,3 @@ +**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions. + Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) API or directly from your database console. \ No newline at end of file diff --git a/docs/references/databases/delete-documents.md b/docs/references/databases/delete-documents.md index a7b05503de..b4e255c69f 100644 --- a/docs/references/databases/delete-documents.md +++ b/docs/references/databases/delete-documents.md @@ -1 +1,3 @@ +**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions. + Bulk delete documents using queries, if no queries are passed then all documents are deleted. \ No newline at end of file diff --git a/docs/references/databases/update-documents.md b/docs/references/databases/update-documents.md index 5f560c6435..9ab8373d36 100644 --- a/docs/references/databases/update-documents.md +++ b/docs/references/databases/update-documents.md @@ -1 +1,3 @@ +**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions. + Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated. \ No newline at end of file diff --git a/docs/references/databases/upsert-document.md b/docs/references/databases/upsert-document.md index a67694cfa6..1980141d22 100644 --- a/docs/references/databases/upsert-document.md +++ b/docs/references/databases/upsert-document.md @@ -1 +1,3 @@ +**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions. + Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) API or directly from your database console. \ No newline at end of file diff --git a/docs/references/databases/upsert-documents.md b/docs/references/databases/upsert-documents.md index f46254bd7b..2e2dc461ba 100644 --- a/docs/references/databases/upsert-documents.md +++ b/docs/references/databases/upsert-documents.md @@ -1 +1,3 @@ -Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) API or directly from your database console. +**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions. + +Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) API or directly from your database console. \ No newline at end of file From e54a157ca8627d16835f8cab5bfc2dd4a33a9f09 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Sat, 14 Jun 2025 13:29:50 +0530 Subject: [PATCH 176/343] chore: remove createDocuments method from client side specs --- app/config/specs/open-api3-1.7.x-client.json | 23 ------------------- app/config/specs/open-api3-latest-client.json | 23 ------------------- app/config/specs/swagger2-1.7.x-client.json | 23 ------------------- app/config/specs/swagger2-latest-client.json | 23 ------------------- .../references/vcs/get-repository-contents.md | 2 +- 5 files changed, 1 insertion(+), 93 deletions(-) diff --git a/app/config/specs/open-api3-1.7.x-client.json b/app/config/specs/open-api3-1.7.x-client.json index 9f1215c222..11fd80fda8 100644 --- a/app/config/specs/open-api3-1.7.x-client.json +++ b/app/config/specs/open-api3-1.7.x-client.json @@ -4490,29 +4490,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/components\/schemas\/documentList" - } - ], - "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 9f1215c222..11fd80fda8 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -4490,29 +4490,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/components\/schemas\/documentList" - } - ], - "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { diff --git a/app/config/specs/swagger2-1.7.x-client.json b/app/config/specs/swagger2-1.7.x-client.json index fce7991c6e..0e83cb4691 100644 --- a/app/config/specs/swagger2-1.7.x-client.json +++ b/app/config/specs/swagger2-1.7.x-client.json @@ -4636,29 +4636,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/definitions\/documentList" - } - ], - "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index fce7991c6e..0e83cb4691 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -4636,29 +4636,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/definitions\/documentList" - } - ], - "description": "**WARNING: Experimental Feature** - This endpoint is experimental and not yet officially supported. It may be subject to breaking changes or removal in future versions.\n\nCreate new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { diff --git a/docs/references/vcs/get-repository-contents.md b/docs/references/vcs/get-repository-contents.md index ab5ef7f8da..176b4203d3 100644 --- a/docs/references/vcs/get-repository-contents.md +++ b/docs/references/vcs/get-repository-contents.md @@ -1 +1 @@ -Get a list of files and directories from a GitHub repository connected to your project. This endpoint returns the contents of a specified repository path, including file names, sizes, and whether each item is a file or directory. The GitHub installation must be properly configured and the repository must be accessible through your installation for this endpoint to work. +Get a list of files and directories from a GitHub repository connected to your project. This endpoint returns the contents of a specified repository path, including file names, sizes, and whether each item is a file or directory. The GitHub installation must be properly configured and the repository must be accessible through your installation for this endpoint to work. \ No newline at end of file From ac2acbb770905761b986afbe9f580babbb05e0d4 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Sat, 14 Jun 2025 14:21:26 +0530 Subject: [PATCH 177/343] fix: duplication of platforms in swagger specs --- app/config/specs/swagger2-latest-client.json | 54 ++---------------- app/config/specs/swagger2-latest-console.json | 56 ++----------------- app/config/specs/swagger2-latest-server.json | 56 ++----------------- .../SDK/Specification/Format/Swagger2.php | 1 + 4 files changed, 13 insertions(+), 154 deletions(-) diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index b3f41e101c..386178abaa 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -3451,7 +3451,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -3576,7 +3575,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -3707,7 +3705,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -3770,7 +3767,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -4257,7 +4253,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -4340,7 +4335,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -4431,7 +4425,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -4522,7 +4515,6 @@ "scope": "documents.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -4604,7 +4596,6 @@ "scope": "documents.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -4766,7 +4757,6 @@ "scope": "documents.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -4856,7 +4846,6 @@ "scope": "documents.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -4961,7 +4950,6 @@ "scope": "documents.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -5058,7 +5046,6 @@ "scope": "documents.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -5136,7 +5123,6 @@ "scope": "execution.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -5210,7 +5196,6 @@ "scope": "execution.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -5327,7 +5312,6 @@ "scope": "execution.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -5399,8 +5383,7 @@ "scope": "graphql", "platforms": [ "server", - "client", - "server" + "client" ], "packaging": false, "auth": { @@ -5473,8 +5456,7 @@ "scope": "graphql", "platforms": [ "server", - "client", - "server" + "client" ], "packaging": false, "auth": { @@ -5545,7 +5527,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -5597,7 +5578,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -5649,7 +5629,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -5701,7 +5680,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -5753,7 +5731,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -5805,7 +5782,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -5857,7 +5833,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -5909,7 +5884,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -5964,8 +5938,7 @@ "platforms": [ "server", "client", - "console", - "server" + "console" ], "packaging": false, "auth": { @@ -6049,8 +6022,7 @@ "platforms": [ "server", "client", - "console", - "server" + "console" ], "packaging": false, "auth": { @@ -6119,7 +6091,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -6202,7 +6173,6 @@ "scope": "files.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -6292,7 +6262,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -6362,7 +6331,6 @@ "scope": "files.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -6451,7 +6419,6 @@ "scope": "files.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -6521,7 +6488,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -6600,7 +6566,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -6807,7 +6772,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -6886,7 +6850,6 @@ "scope": "teams.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -6961,7 +6924,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -7051,7 +7013,6 @@ "scope": "teams.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -7113,7 +7074,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -7188,7 +7148,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -7250,7 +7209,6 @@ "scope": "teams.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -7333,7 +7291,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -7446,7 +7403,6 @@ "scope": "teams.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -7516,7 +7472,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -7602,7 +7557,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 4e60716c4b..9baeddecc0 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -3466,7 +3466,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -3591,7 +3590,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -3722,7 +3720,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -3785,7 +3782,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -4272,7 +4268,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -4355,7 +4350,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -4446,7 +4440,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -8064,7 +8057,6 @@ "scope": "documents.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -8146,7 +8138,6 @@ "scope": "documents.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -8572,7 +8563,6 @@ "scope": "documents.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -8662,7 +8652,6 @@ "scope": "documents.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -8767,7 +8756,6 @@ "scope": "documents.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -8864,7 +8852,6 @@ "scope": "documents.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -11364,7 +11351,6 @@ "rate-key": "url:{url},ip:{ip}", "scope": "functions.read", "platforms": [ - "server", "server" ], "packaging": false, @@ -11518,7 +11504,6 @@ "scope": "execution.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -11592,7 +11577,6 @@ "scope": "execution.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -11709,7 +11693,6 @@ "scope": "execution.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -12296,8 +12279,7 @@ "scope": "graphql", "platforms": [ "server", - "client", - "server" + "client" ], "packaging": false, "auth": { @@ -12370,8 +12352,7 @@ "scope": "graphql", "platforms": [ "server", - "client", - "server" + "client" ], "packaging": false, "auth": { @@ -13705,7 +13686,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -13757,7 +13737,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -13809,7 +13788,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -13861,7 +13839,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -13913,7 +13890,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -13965,7 +13941,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -14017,7 +13992,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -14069,7 +14043,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -18458,8 +18431,7 @@ "platforms": [ "server", "client", - "console", - "server" + "console" ], "packaging": false, "auth": { @@ -18609,8 +18581,7 @@ "platforms": [ "server", "client", - "console", - "server" + "console" ], "packaging": false, "auth": { @@ -27733,7 +27704,6 @@ "rate-key": "url:{url},ip:{ip}", "scope": "sites.read", "platforms": [ - "server", "server" ], "packaging": false, @@ -29002,7 +28972,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -29085,7 +29054,6 @@ "scope": "files.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -29175,7 +29143,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -29245,7 +29212,6 @@ "scope": "files.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -29334,7 +29300,6 @@ "scope": "files.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -29404,7 +29369,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -29483,7 +29447,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -29690,7 +29653,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -29917,7 +29879,6 @@ "scope": "teams.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -29992,7 +29953,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -30082,7 +30042,6 @@ "scope": "teams.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -30144,7 +30103,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -30219,7 +30177,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -30351,7 +30308,6 @@ "scope": "teams.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -30434,7 +30390,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -30547,7 +30502,6 @@ "scope": "teams.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -30617,7 +30571,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -30703,7 +30656,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 4c7c193858..70f399dcc6 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -3142,7 +3142,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -3269,7 +3268,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -3402,7 +3400,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -3467,7 +3464,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -3956,7 +3952,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -4041,7 +4036,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -4134,7 +4128,6 @@ "scope": "avatars.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -7533,7 +7526,6 @@ "scope": "documents.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -7617,7 +7609,6 @@ "scope": "documents.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -8048,7 +8039,6 @@ "scope": "documents.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -8140,7 +8130,6 @@ "scope": "documents.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -8247,7 +8236,6 @@ "scope": "documents.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -8346,7 +8334,6 @@ "scope": "documents.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -10247,7 +10234,6 @@ "rate-key": "url:{url},ip:{ip}", "scope": "functions.read", "platforms": [ - "server", "server" ], "packaging": false, @@ -10403,7 +10389,6 @@ "scope": "execution.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -10479,7 +10464,6 @@ "scope": "execution.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -10598,7 +10582,6 @@ "scope": "execution.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -11115,8 +11098,7 @@ "scope": "graphql", "platforms": [ "server", - "client", - "server" + "client" ], "packaging": false, "auth": { @@ -11191,8 +11173,7 @@ "scope": "graphql", "platforms": [ "server", - "client", - "server" + "client" ], "packaging": false, "auth": { @@ -12550,7 +12531,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -12604,7 +12584,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -12658,7 +12637,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -12712,7 +12690,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -12766,7 +12743,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -12820,7 +12796,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -12874,7 +12849,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -12928,7 +12902,6 @@ "scope": "locale.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -17362,8 +17335,7 @@ "platforms": [ "server", "client", - "console", - "server" + "console" ], "packaging": false, "auth": { @@ -17516,8 +17488,7 @@ "platforms": [ "server", "client", - "console", - "server" + "console" ], "packaging": false, "auth": { @@ -19090,7 +19061,6 @@ "rate-key": "url:{url},ip:{ip}", "scope": "sites.read", "platforms": [ - "server", "server" ], "packaging": false, @@ -20296,7 +20266,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -20381,7 +20350,6 @@ "scope": "files.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -20473,7 +20441,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -20545,7 +20512,6 @@ "scope": "files.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -20636,7 +20602,6 @@ "scope": "files.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -20708,7 +20673,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -20789,7 +20753,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -20998,7 +20961,6 @@ "scope": "files.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -21079,7 +21041,6 @@ "scope": "teams.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -21156,7 +21117,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -21248,7 +21208,6 @@ "scope": "teams.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -21312,7 +21271,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -21389,7 +21347,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -21453,7 +21410,6 @@ "scope": "teams.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -21538,7 +21494,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -21653,7 +21608,6 @@ "scope": "teams.read", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -21725,7 +21679,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, @@ -21813,7 +21766,6 @@ "scope": "teams.write", "platforms": [ "client", - "server", "server" ], "packaging": false, diff --git a/src/Appwrite/SDK/Specification/Format/Swagger2.php b/src/Appwrite/SDK/Specification/Format/Swagger2.php index bac483ffee..06ef6bbd7d 100644 --- a/src/Appwrite/SDK/Specification/Format/Swagger2.php +++ b/src/Appwrite/SDK/Specification/Format/Swagger2.php @@ -141,6 +141,7 @@ class Swagger2 extends Format $sdkPlatforms[] = APP_PLATFORM_CLIENT; } + $sdkPlatforms = array_unique($sdkPlatforms); $namespace = $sdk->getNamespace() ?? 'default'; $desc ??= ''; From 0c163baf80553653ced46a0a3a392a80ab5c0b97 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Sun, 15 Jun 2025 11:06:00 +0530 Subject: [PATCH 178/343] fix: reset array keys after removing duplicates in swagger specs --- src/Appwrite/SDK/Specification/Format/Swagger2.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/SDK/Specification/Format/Swagger2.php b/src/Appwrite/SDK/Specification/Format/Swagger2.php index 06ef6bbd7d..3a6c1b44ba 100644 --- a/src/Appwrite/SDK/Specification/Format/Swagger2.php +++ b/src/Appwrite/SDK/Specification/Format/Swagger2.php @@ -141,7 +141,7 @@ class Swagger2 extends Format $sdkPlatforms[] = APP_PLATFORM_CLIENT; } - $sdkPlatforms = array_unique($sdkPlatforms); + $sdkPlatforms = array_values(array_unique($sdkPlatforms)); $namespace = $sdk->getNamespace() ?? 'default'; $desc ??= ''; From 96c035401ba7420929fcf8e90c9600e099dbef87 Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 15 Jun 2025 11:30:57 +0300 Subject: [PATCH 179/343] Override project resource to update hooks, since x-appwrite-project is not available when executing custom domain function --- app/controllers/general.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/controllers/general.php b/app/controllers/general.php index 5beac9e1e8..aeb4c5bd9c 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -10,6 +10,7 @@ use Appwrite\Event\Certificate; use Appwrite\Event\Event; use Appwrite\Event\Func; use Appwrite\Event\StatsUsage; +use Appwrite\Extend\Exception; use Appwrite\Extend\Exception as AppwriteException; use Appwrite\Network\Validator\Origin; use Appwrite\Platform\Appwrite; @@ -118,6 +119,11 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $project->setAttribute('accessedAt', DateTime::now()); Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } + /** + * Override project resource to update hooks, since x-appwrite-project is not available when executing custom domain function + */ + App::setResource('project', fn () => $project); + } if (array_key_exists('proxy', $project->getAttribute('services', []))) { @@ -1136,6 +1142,12 @@ App::error() ->inject('queueForStatsUsage') ->inject('devKey') ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage) { + + var_dump([ + 'location' => 'error hook', + 'project' => $project->getId(), + ]); + $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); From 4d41c903673c3d55bd45f3c247f80047d13e530b Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 15 Jun 2025 12:00:39 +0300 Subject: [PATCH 180/343] remove duplicate use --- app/controllers/general.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index aeb4c5bd9c..8ad7e188fd 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -10,7 +10,6 @@ use Appwrite\Event\Certificate; use Appwrite\Event\Event; use Appwrite\Event\Func; use Appwrite\Event\StatsUsage; -use Appwrite\Extend\Exception; use Appwrite\Extend\Exception as AppwriteException; use Appwrite\Network\Validator\Origin; use Appwrite\Platform\Appwrite; From 7d54a6191d675ba522b70f5de3df790e36286710 Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 15 Jun 2025 12:13:15 +0300 Subject: [PATCH 181/343] remove duplicate use --- app/controllers/general.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 8ad7e188fd..17e855e9ac 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1142,11 +1142,6 @@ App::error() ->inject('devKey') ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage) { - var_dump([ - 'location' => 'error hook', - 'project' => $project->getId(), - ]); - $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); From c0c30fe767f8c197b8793bf562f57146e5ba15a8 Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 15 Jun 2025 12:40:22 +0300 Subject: [PATCH 182/343] remove duplicate use --- app/controllers/general.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 17e855e9ac..3ab1a23401 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1141,7 +1141,6 @@ App::error() ->inject('queueForStatsUsage') ->inject('devKey') ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage) { - $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); From 5e345c0388ca45826c7a6dfe26f0eeb9797ca963 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Mon, 16 Jun 2025 17:29:01 +0530 Subject: [PATCH 183/343] Revert some changes --- app/controllers/api/console.php | 4 ++-- app/controllers/general.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index d78924028c..558dc0e4ef 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -43,8 +43,8 @@ App::get('/v1/console/variables') )) ->inject('response') ->action(function (Response $response) { - $validator = new Domain(System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', ''))); - $isDomainValid = !empty(System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', ''))) && $validator->isKnown() && !$validator->isTest(); + $validator = new Domain(System::getEnv('_APP_DOMAIN')); + $isDomainValid = !empty(System::getEnv('_APP_DOMAIN', '')) && $validator->isKnown() && !$validator->isTest(); $validator = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME')); $isCNAMEValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')) && $validator->isKnown() && !$validator->isTest(); diff --git a/app/controllers/general.php b/app/controllers/general.php index c4e5f3d55e..69912a9cb9 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -76,7 +76,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $errorView = __DIR__ . '/../views/general/error.phtml'; - $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . '://' . System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . '://' . System::getEnv('_APP_DOMAIN', ''); if ($rule->isEmpty()) { $appDomainFunctionsFallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''); @@ -262,7 +262,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } if (!$authorized) { - $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . "://" . System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . "://" . System::getEnv('_APP_DOMAIN'); $response ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') ->addHeader('Pragma', 'no-cache') @@ -449,7 +449,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $hostname = System::getEnv('_APP_DOMAIN'); $endpoint = $protocol . '://' . $hostname . "/v1"; // Appwrite vars @@ -858,7 +858,7 @@ App::init() } else { Authorization::disable(); - $envDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $envDomain = System::getEnv('_APP_DOMAIN', ''); $mainDomain = null; if (!empty($envDomain) && $envDomain !== 'localhost') { $mainDomain = $envDomain; From 8c8abfdecebbf3cfc9e6978ab3ca76569bd9f8e5 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Mon, 16 Jun 2025 18:47:50 +0530 Subject: [PATCH 184/343] Add var_dumps to debug --- app/controllers/general.php | 2 +- src/Appwrite/Vcs/Comment.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 69912a9cb9..1761e16881 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -262,7 +262,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } if (!$authorized) { - $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . "://" . System::getEnv('_APP_DOMAIN'); + $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . "://" . System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $response ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') ->addHeader('Pragma', 'no-cache') diff --git a/src/Appwrite/Vcs/Comment.php b/src/Appwrite/Vcs/Comment.php index 5b303efe44..96cbd9662d 100644 --- a/src/Appwrite/Vcs/Comment.php +++ b/src/Appwrite/Vcs/Comment.php @@ -88,6 +88,7 @@ class Comment foreach ($projects as $projectId => $project) { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + var_dump("hostname: $hostname"); $text .= "## {$project['name']}\n\n"; $text .= "Project ID: `{$projectId}`\n\n"; @@ -166,6 +167,8 @@ class Comment }; if ($function['action']['type'] === 'logs') { + var_dump("in view logs"); + var_dump("hostname: $hostname"); $action = '[View Logs](' . $protocol . '://' . $hostname . '/console/project-' . $function['region'] . '-' . $projectId . '/functions/function-' . $functionId . '/deployment-' . $function['deploymentId'] . ')'; } else { $action = '[Authorize](' . $function['action']['url'] . ')'; From ad60ff99728d720957a82e6e846b0c72854e7715 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Mon, 16 Jun 2025 19:16:20 +0530 Subject: [PATCH 185/343] Update url in general.php --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 1761e16881..12b3c5d773 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -76,7 +76,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $errorView = __DIR__ . '/../views/general/error.phtml'; - $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . '://' . System::getEnv('_APP_DOMAIN', ''); + $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . '://' . System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); if ($rule->isEmpty()) { $appDomainFunctionsFallback = System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''); From cacf323993945281897a45e7ff97fe8b88cfea46 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 17 Jun 2025 09:15:26 +0530 Subject: [PATCH 186/343] update: fallback font to `sans-serif`. --- app/config/locale/templates/email-inner-base.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/locale/templates/email-inner-base.tpl b/app/config/locale/templates/email-inner-base.tpl index 64fbdd33b1..677f70ce7d 100644 --- a/app/config/locale/templates/email-inner-base.tpl +++ b/app/config/locale/templates/email-inner-base.tpl @@ -1,6 +1,6 @@

    {{hello}}

    {{body}}

    -

    {{buttonText}}

    +

    {{buttonText}}

    {{footer}}

    {{thanks}} From e236aac0ea4388e61e30e9c65af4a87c6f7b5d07 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 17 Jun 2025 09:57:35 +0530 Subject: [PATCH 187/343] =?UTF-8?q?fix:=20events=20logic=20=F0=9F=98=AE?= =?UTF-8?q?=E2=80=8D=F0=9F=92=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Http/Databases/Collections/Documents/Create.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index e68a27ba34..6005495a68 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -56,7 +56,6 @@ class Create extends Action ->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents') ->desc('Create document') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].create') ->label('scope', 'documents.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'document.create') @@ -418,12 +417,6 @@ class Create extends Action $response->setStatusCode(SwooleResponse::STATUS_CODE_CREATED); - // BIG TODO: @itznotabug - need to check what to do for bulk api because there's not just one `[document/rowId]`. - $queueForEvents - ->setParam('documentId', $documents[0]->getId()) - ->setParam('rowId', $documents[0]->getId()) - // TODO: @itznotabug - check if the events mirroring works here! - ->setEvent('databases.[databaseId].collections.[collectionId].documents.[documentId].create'); if ($isBulk) { $response->dynamic(new Document([ @@ -434,6 +427,11 @@ class Create extends Action return; } + $queueForEvents + ->setParam('documentId', $documents[0]->getId()) + ->setParam('rowId', $documents[0]->getId()) + ->setEvent('databases.[databaseId].collections.[collectionId].documents.[documentId].create'); + $response->dynamic( $documents[0], $this->getResponseModel() From 1337b759deffd552c05c28e80c82f23ff3b6720b Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 17 Jun 2025 10:15:45 +0530 Subject: [PATCH 188/343] fix: remove event for bulk api support. --- .../Modules/Databases/Http/Databases/Tables/Rows/Create.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php index 881d2b28ed..03e5548ddb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php @@ -47,7 +47,6 @@ class Create extends DocumentCreate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') ->desc('Create row') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].create') ->label('scope', 'documents.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'row.create') From 41bc8272ff30d3717154d8d1f6641306415c4086 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Tue, 17 Jun 2025 12:15:52 +0530 Subject: [PATCH 189/343] Add env var to docker-compose --- docker-compose.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 0b653af8c2..72006a10a6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -116,6 +116,7 @@ services: - _APP_OPTIONS_ROUTER_FORCE_HTTPS - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN + - _APP_CONSOLE_DOMAIN - _APP_DOMAIN_TARGET_CNAME - _APP_DOMAIN_TARGET_AAAA - _APP_DOMAIN_TARGET_A @@ -481,6 +482,7 @@ services: - _APP_OPTIONS_FORCE_HTTPS - _APP_OPTIONS_ROUTER_FORCE_HTTPS - _APP_DOMAIN + - _APP_CONSOLE_DOMAIN - _APP_STORAGE_DEVICE - _APP_STORAGE_S3_ACCESS_KEY - _APP_STORAGE_S3_SECRET @@ -564,6 +566,7 @@ services: - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN + - _APP_CONSOLE_DOMAIN - _APP_OPTIONS_FORCE_HTTPS - _APP_REDIS_HOST - _APP_REDIS_PORT From b7ffd2ca94ea6655c90026a0255cc87290610306 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Tue, 17 Jun 2025 13:57:21 +0530 Subject: [PATCH 190/343] Revert some changes --- docker-compose.yml | 1 - .../Platform/Modules/Functions/Http/Executions/Create.php | 2 +- src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php | 2 +- .../Platform/Modules/Proxy/Http/Rules/Function/Create.php | 2 +- .../Platform/Modules/Proxy/Http/Rules/Redirect/Create.php | 2 +- src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php | 2 +- src/Appwrite/Platform/Workers/Functions.php | 2 +- src/Appwrite/Vcs/Comment.php | 3 --- src/Executor/Executor.php | 2 +- tests/e2e/Services/Projects/ProjectsCustomServerTest.php | 2 +- 10 files changed, 8 insertions(+), 12 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 72006a10a6..56f8f38f44 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -566,7 +566,6 @@ services: - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN - - _APP_CONSOLE_DOMAIN - _APP_OPTIONS_FORCE_HTTPS - _APP_REDIS_HOST - _APP_REDIS_PORT diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index 2f7c84b7d1..71ff730b98 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -351,7 +351,7 @@ class Create extends Base } $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $hostname = System::getEnv('_APP_DOMAIN'); $endpoint = $protocol . '://' . $hostname . "/v1"; // Appwrite vars diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php index a4d4980384..e4d0d2899f 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php @@ -76,7 +76,7 @@ class Create extends Action APP_HOSTNAME_INTERNAL ]; - $mainDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $mainDomain = System::getEnv('_APP_DOMAIN', ''); $deniedDomains[] = $mainDomain; $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php index 66465a0a97..6c5a87a68d 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php @@ -81,7 +81,7 @@ class Create extends Action APP_HOSTNAME_INTERNAL ]; - $mainDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $mainDomain = System::getEnv('_APP_DOMAIN', ''); $deniedDomains[] = $mainDomain; $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php index 66a186993c..3396a9c6fd 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php @@ -84,7 +84,7 @@ class Create extends Action APP_HOSTNAME_INTERNAL ]; - $mainDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $mainDomain = System::getEnv('_APP_DOMAIN', ''); $deniedDomains[] = $mainDomain; $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php index b466b1774b..894c954a32 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php @@ -81,7 +81,7 @@ class Create extends Action APP_HOSTNAME_INTERNAL ]; - $mainDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $mainDomain = System::getEnv('_APP_DOMAIN', ''); $deniedDomains[] = $mainDomain; $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index 6dde173843..843cb4a5b9 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -484,7 +484,7 @@ class Functions extends Action } $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $hostname = System::getEnv('_APP_DOMAIN'); $endpoint = $protocol . '://' . $hostname . "/v1"; // Appwrite vars diff --git a/src/Appwrite/Vcs/Comment.php b/src/Appwrite/Vcs/Comment.php index 96cbd9662d..5b303efe44 100644 --- a/src/Appwrite/Vcs/Comment.php +++ b/src/Appwrite/Vcs/Comment.php @@ -88,7 +88,6 @@ class Comment foreach ($projects as $projectId => $project) { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); - var_dump("hostname: $hostname"); $text .= "## {$project['name']}\n\n"; $text .= "Project ID: `{$projectId}`\n\n"; @@ -167,8 +166,6 @@ class Comment }; if ($function['action']['type'] === 'logs') { - var_dump("in view logs"); - var_dump("hostname: $hostname"); $action = '[View Logs](' . $protocol . '://' . $hostname . '/console/project-' . $function['region'] . '-' . $projectId . '/functions/function-' . $functionId . '/deployment-' . $function['deploymentId'] . ')'; } else { $action = '[Authorize](' . $function['action']['url'] . ')'; diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index 8ead1c82a2..15411f18ab 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -191,7 +191,7 @@ class Executor int $requestTimeout = null ) { if (empty($headers['host'])) { - $headers['host'] = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $headers['host'] = System::getEnv('_APP_DOMAIN', ''); } $runtimeId = "$projectId-$deploymentId"; diff --git a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php index 9146d0636f..a01073f3a3 100644 --- a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php +++ b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php @@ -83,7 +83,7 @@ class ProjectsCustomServerTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); - $mainDomain = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $mainDomain = System::getEnv('_APP_DOMAIN', ''); $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); From 1fbbbee31012d5d0a430f24b6f522372af957c10 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 17 Jun 2025 15:01:13 +0530 Subject: [PATCH 191/343] update: add cached logic to `processDocument`. --- .../Collections/Documents/Action.php | 93 +++++++++++++++++++ .../Collections/Documents/Create.php | 39 +------- .../Collections/Documents/Delete.php | 38 +------- .../Databases/Collections/Documents/Get.php | 52 ++--------- .../Collections/Documents/Update.php | 37 +------- .../Collections/Documents/Upsert.php | 37 +------- .../Databases/Collections/Documents/XList.php | 66 ++----------- 7 files changed, 126 insertions(+), 236 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index c0e71d3730..32e26bb344 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -4,6 +4,9 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documen use Appwrite\Extend\Exception; use Appwrite\Platform\Modules\Databases\Context; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action as UtopiaAction; abstract class Action extends UtopiaAction @@ -193,4 +196,94 @@ abstract class Action extends UtopiaAction { return $this->isCollectionsAPI() ? 'collection' : 'table'; } + + /** + * Resolves relationships in a document and attaches metadata. + */ + final protected function resolveDocumentRelations(Document $document, Document $collection, array &$context): bool + { + /* @type Document $database */ + $database = $context['database']; + + /* @type Database $dbForProject */ + $dbForProject = $context['dbForProject']; + + /* remove `$collection` if needed */ + $removeCollection = $context['removeCollection'] ?? false; + + /* count operations and use `continue` inside loop */ + $trackOperations = array_key_exists('trackOperations', $context); + + if (!$trackOperations) { + $context['operations'] ??= 0; + } elseif ($document->isEmpty()) { + return false; + } + + $operations = &$context['operations']; + $collectionsCache = &$context['collectionsCache']; + + $operations++; + $collectionId = $collection->getId(); + + $document->setAttribute('$databaseId', $database->getId()); + $document->setAttribute('$collectionId', $collectionId); + + if ($removeCollection) { + $document->removeAttribute('$collection'); + } + + $relationships = $collectionsCache[$collectionId] ??= \array_filter( + $collection->getAttribute('attributes', []), + fn ($attr) => $attr->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $key = $relationship->getAttribute('key'); + $related = $document->getAttribute($key); + + if (empty($related)) { + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + continue; + } + + $relations = \is_array($related) ? $related : [$related]; + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + + if (!isset($collectionsCache[$relatedCollectionId])) { + $relatedCollectionDoc = Authorization::skip( + fn () => $dbForProject->getDocument( + 'database_' . $database->getSequence(), + $relatedCollectionId + ) + ); + + $collectionsCache[$relatedCollectionId] = \array_filter( + $relatedCollectionDoc->getAttribute('attributes', []), + fn ($attr) => $attr->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + } + + foreach ($relations as $index => $relation) { + if ($relation instanceof Document) { + $relatedCollection = new Document([ + '$id' => $relatedCollectionId, + 'attributes' => $collectionsCache[$relatedCollectionId], + ]); + + $this->resolveDocumentRelations(document: $relation, collection: $relatedCollection, context: $context); + } + } + + if (\is_array($related)) { + $document->setAttribute($relationship->getAttribute('key'), \array_values($relations)); + } elseif (empty($relations)) { + $document->setAttribute($relationship->getAttribute('key'), null); + } + } + + return true; + } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index 6005495a68..47c6acf0b7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -373,42 +373,13 @@ class Create extends Action ->setParam('tableId', $collection->getId()) ->setContext($this->getCollectionsEventsContext(), $collection); - // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $table, Document $document) use (&$processDocument, $dbForProject, $database) { - $document->removeAttribute('$collection'); - $document->setAttribute('$databaseId', $database->getId()); - $document->setAttribute('$collectionId', $table->getId()); - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processDocument($relatedCollection, $relation); - } - } - } - }; + $collectionsCache = []; + $removeCollection = true; + $context = compact('database', 'dbForProject', 'collectionsCache', 'removeCollection'); foreach ($documents as $document) { - $processDocument($collection, $document); + // Add $collectionId and $databaseId for all documents + $this->resolveDocumentRelations(document: $document, collection: $collection, context: $context); } $queueForStatsUsage diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index dc307071e4..9f1f27b1f8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Restricted as RestrictedException; use Utopia\Database\Validator\Authorization; @@ -115,40 +114,11 @@ class Delete extends Action throw new Exception($this->getRestrictedException()); } + $collectionsCache = []; + $context = compact('database', 'dbForProject', 'collectionsCache'); + // Add $collection and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { - $document->setAttribute('$databaseId', $database->getId()); - $document->setAttribute('$collectionId', $collection->getId()); - - $relationships = \array_filter( - $collection->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processDocument($relatedCollection, $relation); - } - } - } - }; - - $processDocument($collection, $document); + $this->resolveDocumentRelations(document: $document, collection: $collection, context: $context); $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index 3f7f74ee75..bf1acb8086 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; @@ -101,52 +100,15 @@ class Get extends Action } $operations = 0; + $collectionsCache = []; + $trackOperations = true; + $context = compact('database', 'dbForProject', 'operations', 'trackOperations', 'collectionsCache'); - // Add $collectionId and $databaseId for all rows - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { - if ($document->isEmpty()) { - return; - } + // Add $collectionId and $databaseId for all documents + $this->resolveDocumentRelations(document: $document, collection: $collection, context: $context); - $operations++; - - $document->setAttribute('$databaseId', $database->getId()); - $document->setAttribute('$collectionId', $collection->getId()); - - $relationships = \array_filter( - $collection->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - if (\in_array(\gettype($related), ['array', 'object'])) { - $operations++; - } - - continue; - } - - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processDocument($relatedCollection, $relation); - } - } - } - }; - - $processDocument($collection, $document); + // get updated from the context + $operations = $context['operations']; $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index 3bc97e817b..b946731c7a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -247,40 +247,11 @@ class Update extends Action throw new Exception($this->getInvalidStructureException(), $e->getMessage()); } + $collectionsCache = []; + $context = compact('database', 'dbForProject', 'collectionsCache'); + // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $table, Document $row) use (&$processDocument, $dbForProject, $database) { - $row->setAttribute('$databaseId', $database->getId()); - $row->setAttribute('$collectionId', $table->getId()); - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $row->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processDocument($relatedCollection, $relation); - } - } - } - }; - - $processDocument($collection, $document); + $this->resolveDocumentRelations(document: $document, collection: $collection, context: $context); $response->dynamic($document, $this->getResponseModel()); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php index ebe30f6970..d27ff632b8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php @@ -235,41 +235,12 @@ class Upsert extends Action throw new Exception($this->getInvalidStructureException(), $e->getMessage()); } + $collectionsCache = []; $document = $upserted[0]; + $context = compact('database', 'dbForProject', 'collectionsCache'); + // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $table, Document $document) use (&$processDocument, $dbForProject, $database) { - $document->setAttribute('$databaseId', $database->getId()); - $document->setAttribute('$collectionId', $table->getId()); - - $relationships = \array_filter( - $table->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - continue; - } - if (!\is_array($related)) { - $related = [$related]; - } - - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) - ); - - foreach ($related as $relation) { - if ($relation instanceof Document) { - $processDocument($relatedCollection, $relation); - } - } - } - }; - - $processDocument($collection, $document); + $this->resolveDocumentRelations(document: $document, collection: $collection, context: $context); $relationships = \array_map( fn ($document) => $document->getAttribute('key'), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 0012b8339a..b87efe42de 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -130,67 +130,19 @@ class XList extends Action } $operations = 0; + $collectionsCache = []; + $trackOperations = true; + $removeCollection = true; + $context = compact('database', 'dbForProject', 'operations', 'collectionsCache', 'removeCollection', 'trackOperations'); // Add $collectionId and $databaseId for all documents - $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations): bool { - if ($document->isEmpty()) { - return false; - } - - $operations++; - - $document->removeAttribute('$collection'); - $document->setAttribute('$databaseId', $database->getId()); - $document->setAttribute('$collectionId', $collection->getId()); - - $relationships = \array_filter( - $collection->getAttribute('attributes', []), - fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP - ); - - foreach ($relationships as $relationship) { - $related = $document->getAttribute($relationship->getAttribute('key')); - - if (empty($related)) { - if (\in_array(\gettype($related), ['array', 'object'])) { - $operations++; - } - - continue; - } - - if (!\is_array($related)) { - $relations = [$related]; - } else { - $relations = $related; - } - - $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - // todo: Use local cache for this getDocument - $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId)); - - foreach ($relations as $index => $doc) { - if ($doc instanceof Document) { - if (!$processDocument($relatedCollection, $doc)) { - unset($relations[$index]); - } - } - } - - if (\is_array($related)) { - $document->setAttribute($relationship->getAttribute('key'), \array_values($relations)); - } elseif (empty($relations)) { - $document->setAttribute($relationship->getAttribute('key'), null); - } - } - - return true; - }); - - foreach ($documents as $row) { - $processDocument($collection, $row); + foreach ($documents as $document) { + $this->resolveDocumentRelations(document: $document, collection: $collection, context: $context); } + // get updated from the context + $operations = $context['operations']; + $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); From 16a87535097292cad4e395def4a3ba467b89be38 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 17 Jun 2025 15:03:11 +0530 Subject: [PATCH 192/343] update: comment. --- .../Databases/Http/Databases/Collections/Documents/Action.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index 32e26bb344..d5e7d84695 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -211,7 +211,7 @@ abstract class Action extends UtopiaAction /* remove `$collection` if needed */ $removeCollection = $context['removeCollection'] ?? false; - /* count operations and use `continue` inside loop */ + /* count operations inside loop */ $trackOperations = array_key_exists('trackOperations', $context); if (!$trackOperations) { From 22cda269b18c4cd40abbaf53f19254135e0ed8b6 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Tue, 17 Jun 2025 18:37:02 +0530 Subject: [PATCH 193/343] Update console --- composer.lock | 39 +++++++++++++++++++-------------------- docker-compose.yml | 2 +- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/composer.lock b/composer.lock index fdde3f2750..c60ba97f8b 100644 --- a/composer.lock +++ b/composer.lock @@ -1874,16 +1874,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.43", + "version": "3.0.44", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "709ec107af3cb2f385b9617be72af8cf62441d02" + "reference": "1d0b5e7e1434678411787c5a0535e68907cf82d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/709ec107af3cb2f385b9617be72af8cf62441d02", - "reference": "709ec107af3cb2f385b9617be72af8cf62441d02", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/1d0b5e7e1434678411787c5a0535e68907cf82d9", + "reference": "1d0b5e7e1434678411787c5a0535e68907cf82d9", "shasum": "" }, "require": { @@ -1964,7 +1964,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.43" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.44" }, "funding": [ { @@ -1980,7 +1980,7 @@ "type": "tidelift" } ], - "time": "2024-12-14T21:12:59+00:00" + "time": "2025-06-15T09:59:26+00:00" }, { "name": "psr/container", @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.41.4", + "version": "0.41.7", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "07804269131f411576aac60c795a5ebc3afaa48a" + "reference": "d8c7bb26ea32ab378faf4e0dfa62fd15fe37c57b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/07804269131f411576aac60c795a5ebc3afaa48a", - "reference": "07804269131f411576aac60c795a5ebc3afaa48a", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/d8c7bb26ea32ab378faf4e0dfa62fd15fe37c57b", + "reference": "d8c7bb26ea32ab378faf4e0dfa62fd15fe37c57b", "shasum": "" }, "require": { @@ -4852,9 +4852,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.41.4" + "source": "https://github.com/appwrite/sdk-generator/tree/0.41.7" }, - "time": "2025-06-10T08:28:11+00:00" + "time": "2025-06-13T17:05:57+00:00" }, { "name": "doctrine/annotations", @@ -5147,16 +5147,16 @@ }, { "name": "matthiasmullie/minify", - "version": "1.3.73", + "version": "1.3.74", "source": { "type": "git", "url": "https://github.com/matthiasmullie/minify.git", - "reference": "cb7a9297b4ab070909cefade30ee95054d4ae87a" + "reference": "a2593286a4135d03c6a6a9e9aeded5d41e931ce4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/cb7a9297b4ab070909cefade30ee95054d4ae87a", - "reference": "cb7a9297b4ab070909cefade30ee95054d4ae87a", + "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/a2593286a4135d03c6a6a9e9aeded5d41e931ce4", + "reference": "a2593286a4135d03c6a6a9e9aeded5d41e931ce4", "shasum": "" }, "require": { @@ -5167,8 +5167,7 @@ "require-dev": { "friendsofphp/php-cs-fixer": ">=2.0", "matthiasmullie/scrapbook": ">=1.3", - "phpunit/phpunit": ">=4.8", - "squizlabs/php_codesniffer": ">=3.0" + "phpunit/phpunit": ">=4.8" }, "suggest": { "psr/cache-implementation": "Cache implementation to use with Minify::cache" @@ -5206,7 +5205,7 @@ ], "support": { "issues": "https://github.com/matthiasmullie/minify/issues", - "source": "https://github.com/matthiasmullie/minify/tree/1.3.73" + "source": "https://github.com/matthiasmullie/minify/tree/1.3.74" }, "funding": [ { @@ -5214,7 +5213,7 @@ "type": "github" } ], - "time": "2024-03-15T10:27:10+00:00" + "time": "2025-06-12T08:06:04+00:00" }, { "name": "matthiasmullie/path-converter", diff --git a/docker-compose.yml b/docker-compose.yml index 56f8f38f44..749613c8c6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -214,7 +214,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:6.0.41 + image: appwrite/console:6.1.2 restart: unless-stopped networks: - appwrite From 5a3e44a36d570c0d3b0e8b54314e0549c637eadf Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Wed, 18 Jun 2025 11:06:35 +0530 Subject: [PATCH 194/343] Replace == with === --- app/config/templates/site.php | 2 +- app/controllers/api/vcs.php | 6 +++--- app/controllers/general.php | 2 +- src/Appwrite/Vcs/Comment.php | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/config/templates/site.php b/app/config/templates/site.php index 47a436b44e..c6f0119ed9 100644 --- a/app/config/templates/site.php +++ b/app/config/templates/site.php @@ -6,7 +6,7 @@ use Utopia\System\System; * List of Appwrite Sites templates */ -$protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; +$protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $url = $protocol . '://' . $hostname; diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 2568925c43..12d3980f7c 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -116,7 +116,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } $commentStatus = $isAuthorized ? 'waiting' : 'failed'; - $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $authorizeUrl = $protocol . '://' . $hostname . "/console/git/authorize-contributor?projectId={$projectId}&installationId={$installationId}&repositoryId={$repositoryId}&providerPullRequestId={$providerPullRequestId}"; @@ -439,7 +439,7 @@ App::get('/v1/vcs/github/authorize') ]); $appName = System::getEnv('_APP_VCS_GITHUB_APP_NAME'); - $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); if (empty($appName)) { @@ -498,7 +498,7 @@ App::get('/v1/vcs/github/callback') } $region = $project->getAttribute('region', 'default'); - $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $defaultState = [ diff --git a/app/controllers/general.php b/app/controllers/general.php index 12b3c5d773..97d90ebea9 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -448,7 +448,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); } - $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $hostname = System::getEnv('_APP_DOMAIN'); $endpoint = $protocol . '://' . $hostname . "/v1"; diff --git a/src/Appwrite/Vcs/Comment.php b/src/Appwrite/Vcs/Comment.php index 5b303efe44..a66706a4a2 100644 --- a/src/Appwrite/Vcs/Comment.php +++ b/src/Appwrite/Vcs/Comment.php @@ -86,7 +86,7 @@ class Comment $i = 0; foreach ($projects as $projectId => $project) { - $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $text .= "## {$project['name']}\n\n"; @@ -200,7 +200,7 @@ class Comment public function generatImage(string $pathLight, string $pathDark, string $alt, int $width): string { - $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); $imageLight = $protocol . '://' . $hostname . $pathLight; From d6bf748a079682546a19efa54945cd110f0aee8d Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 18 Jun 2025 12:00:19 +0530 Subject: [PATCH 195/343] address comments. --- .../Collections/Documents/Action.php | 51 +++++++++---------- .../Collections/Documents/Create.php | 12 +++-- .../Collections/Documents/Delete.php | 11 ++-- .../Databases/Collections/Documents/Get.php | 16 +++--- .../Collections/Documents/Update.php | 11 ++-- .../Collections/Documents/Upsert.php | 11 ++-- .../Databases/Collections/Documents/XList.php | 17 +++---- 7 files changed, 69 insertions(+), 60 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index d5e7d84695..52dfc62f50 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -200,39 +200,31 @@ abstract class Action extends UtopiaAction /** * Resolves relationships in a document and attaches metadata. */ - final protected function resolveDocumentRelations(Document $document, Document $collection, array &$context): bool - { - /* @type Document $database */ - $database = $context['database']; + final protected function processDocument( + /* database */ + Document $database, + Document $collection, + Document $document, + Database $dbForProject, - /* @type Database $dbForProject */ - $dbForProject = $context['dbForProject']; + /* options */ + array &$collectionsCache, + ?int &$operations = null, + ): bool { - /* remove `$collection` if needed */ - $removeCollection = $context['removeCollection'] ?? false; - - /* count operations inside loop */ - $trackOperations = array_key_exists('trackOperations', $context); - - if (!$trackOperations) { - $context['operations'] ??= 0; - } elseif ($document->isEmpty()) { + if ($operations !== null && $document->isEmpty()) { return false; } - $operations = &$context['operations']; - $collectionsCache = &$context['collectionsCache']; + if ($operations !== null) { + $operations++; + } - $operations++; $collectionId = $collection->getId(); - + $document->removeAttribute('$collection'); $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collectionId); - if ($removeCollection) { - $document->removeAttribute('$collection'); - } - $relationships = $collectionsCache[$collectionId] ??= \array_filter( $collection->getAttribute('attributes', []), fn ($attr) => $attr->getAttribute('type') === Database::VAR_RELATIONSHIP @@ -243,7 +235,7 @@ abstract class Action extends UtopiaAction $related = $document->getAttribute($key); if (empty($related)) { - if (\in_array(\gettype($related), ['array', 'object'])) { + if (\in_array(\gettype($related), ['array', 'object']) && $operations !== null) { $operations++; } continue; @@ -266,14 +258,21 @@ abstract class Action extends UtopiaAction ); } - foreach ($relations as $index => $relation) { + foreach ($relations as $relation) { if ($relation instanceof Document) { $relatedCollection = new Document([ '$id' => $relatedCollectionId, 'attributes' => $collectionsCache[$relatedCollectionId], ]); - $this->resolveDocumentRelations(document: $relation, collection: $relatedCollection, context: $context); + $this->processDocument( + database: $database, + collection: $relatedCollection, + document: $relation, + dbForProject: $dbForProject, + collectionsCache: $collectionsCache, + operations: $operations + ); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index 47c6acf0b7..ebab4a7ece 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -374,12 +374,14 @@ class Create extends Action ->setContext($this->getCollectionsEventsContext(), $collection); $collectionsCache = []; - $removeCollection = true; - $context = compact('database', 'dbForProject', 'collectionsCache', 'removeCollection'); - foreach ($documents as $document) { - // Add $collectionId and $databaseId for all documents - $this->resolveDocumentRelations(document: $document, collection: $collection, context: $context); + $this->processDocument( + database: $database, + collection: $collection, + document: $document, + dbForProject: $dbForProject, + collectionsCache: $collectionsCache, + ); } $queueForStatsUsage diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index 9f1f27b1f8..d8ec82910c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -115,10 +115,13 @@ class Delete extends Action } $collectionsCache = []; - $context = compact('database', 'dbForProject', 'collectionsCache'); - - // Add $collection and $databaseId for all documents - $this->resolveDocumentRelations(document: $document, collection: $collection, context: $context); + $this->processDocument( + database: $database, + collection: $collection, + document: $document, + dbForProject: $dbForProject, + collectionsCache: $collectionsCache, + ); $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index bf1acb8086..fe40a2412f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -101,14 +101,14 @@ class Get extends Action $operations = 0; $collectionsCache = []; - $trackOperations = true; - $context = compact('database', 'dbForProject', 'operations', 'trackOperations', 'collectionsCache'); - - // Add $collectionId and $databaseId for all documents - $this->resolveDocumentRelations(document: $document, collection: $collection, context: $context); - - // get updated from the context - $operations = $context['operations']; + $this->processDocument( + database: $database, + collection: $collection, + document: $document, + dbForProject: $dbForProject, + collectionsCache: $collectionsCache, + operations: $operations + ); $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index b946731c7a..c39eeea707 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -248,10 +248,13 @@ class Update extends Action } $collectionsCache = []; - $context = compact('database', 'dbForProject', 'collectionsCache'); - - // Add $collectionId and $databaseId for all documents - $this->resolveDocumentRelations(document: $document, collection: $collection, context: $context); + $this->processDocument( + database: $database, + collection: $collection, + document: $document, + dbForProject: $dbForProject, + collectionsCache: $collectionsCache, + ); $response->dynamic($document, $this->getResponseModel()); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php index d27ff632b8..fa632c7b2b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php @@ -237,10 +237,13 @@ class Upsert extends Action $collectionsCache = []; $document = $upserted[0]; - $context = compact('database', 'dbForProject', 'collectionsCache'); - - // Add $collectionId and $databaseId for all documents - $this->resolveDocumentRelations(document: $document, collection: $collection, context: $context); + $this->processDocument( + database: $database, + collection: $collection, + document: $document, + dbForProject: $dbForProject, + collectionsCache: $collectionsCache, + ); $relationships = \array_map( fn ($document) => $document->getAttribute('key'), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index b87efe42de..9aad8f4b77 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -131,18 +131,17 @@ class XList extends Action $operations = 0; $collectionsCache = []; - $trackOperations = true; - $removeCollection = true; - $context = compact('database', 'dbForProject', 'operations', 'collectionsCache', 'removeCollection', 'trackOperations'); - - // Add $collectionId and $databaseId for all documents foreach ($documents as $document) { - $this->resolveDocumentRelations(document: $document, collection: $collection, context: $context); + $this->processDocument( + database: $database, + collection: $collection, + document: $document, + dbForProject: $dbForProject, + collectionsCache: $collectionsCache, + operations: $operations, + ); } - // get updated from the context - $operations = $context['operations']; - $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); From d69189bd55317fe5b31bce211669e24be6991c74 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 18 Jun 2025 12:02:08 +0530 Subject: [PATCH 196/343] ci: empty commit From f4434264cdf99640ab13beef2deaa7c1eee2dc31 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Wed, 18 Jun 2025 12:50:53 +0530 Subject: [PATCH 197/343] Fix missing screenshot logs --- src/Appwrite/Platform/Modules/Functions/Workers/Builds.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index bbe1e1f004..8ff1690da9 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1032,6 +1032,7 @@ class Builds extends Action $date = \date('H:i:s'); $logs .= "[$date] [appwrite] Screenshot capturing finished. \n"; + $deployment->setAttribute('buildLogs', $logs); $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); $queueForRealtime @@ -1046,6 +1047,7 @@ class Builds extends Action $date = \date('H:i:s'); $logs .= "[$date] [appwrite] Screenshot capturing failed. Deployment will continue. \n"; + $deployment->setAttribute('buildLogs', $logs); $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); } } From 5934ad459fdbad9fdab50a3b7227e33ac6ea0cd5 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 18 Jun 2025 13:44:33 +0530 Subject: [PATCH 198/343] chore: update react native sdk and changelog --- app/config/platforms.php | 2 +- composer.json | 2 +- composer.lock | 30 +++++++++++++++-------------- docs/sdks/react-native/CHANGELOG.md | 13 +++++++++++++ 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/app/config/platforms.php b/app/config/platforms.php index f08401e8fa..c8d70c6cfb 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -134,7 +134,7 @@ return [ [ 'key' => 'react-native', 'name' => 'React Native', - 'version' => '0.9.1', + 'version' => '0.10.0', 'url' => 'https://github.com/appwrite/sdk-for-react-native', 'package' => 'https://npmjs.com/package/react-native-appwrite', 'enabled' => true, diff --git a/composer.json b/composer.json index 18507e04f1..1c1a9efbda 100644 --- a/composer.json +++ b/composer.json @@ -86,7 +86,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "0.41.*", + "appwrite/sdk-generator": "dev-PLA-2728", "phpunit/phpunit": "9.*", "swoole/ide-helper": "5.1.2", "phpstan/phpstan": "1.8.*", diff --git a/composer.lock b/composer.lock index ff6884de7d..584ee1292b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1557e469b3074a6478a0b2fd522e1a2a", + "content-hash": "df602257a97ccc069f377903b57a2380", "packages": [ { "name": "adhocore/jwt", @@ -3490,16 +3490,16 @@ }, { "name": "utopia-php/database", - "version": "0.71.6", + "version": "0.71.7", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "2bd87acc40af087fc0fdcccc47c43141dff0be5c" + "reference": "aa0116b2380125907fc18c82662be8e74c54091f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/2bd87acc40af087fc0fdcccc47c43141dff0be5c", - "reference": "2bd87acc40af087fc0fdcccc47c43141dff0be5c", + "url": "https://api.github.com/repos/utopia-php/database/zipball/aa0116b2380125907fc18c82662be8e74c54091f", + "reference": "aa0116b2380125907fc18c82662be8e74c54091f", "shasum": "" }, "require": { @@ -3540,9 +3540,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.71.6" + "source": "https://github.com/utopia-php/database/tree/0.71.7" }, - "time": "2025-06-16T16:48:37+00:00" + "time": "2025-06-17T23:59:10+00:00" }, { "name": "utopia-php/detector", @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.41.7", + "version": "dev-PLA-2728", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "d8c7bb26ea32ab378faf4e0dfa62fd15fe37c57b" + "reference": "9973cd6969f2a225ae88df28e99d19eac475f7c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/d8c7bb26ea32ab378faf4e0dfa62fd15fe37c57b", - "reference": "d8c7bb26ea32ab378faf4e0dfa62fd15fe37c57b", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/9973cd6969f2a225ae88df28e99d19eac475f7c8", + "reference": "9973cd6969f2a225ae88df28e99d19eac475f7c8", "shasum": "" }, "require": { @@ -4852,9 +4852,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.41.7" + "source": "https://github.com/appwrite/sdk-generator/tree/PLA-2728" }, - "time": "2025-06-13T17:05:57+00:00" + "time": "2025-06-18T08:06:19+00:00" }, { "name": "doctrine/annotations", @@ -8233,7 +8233,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "appwrite/sdk-generator": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/docs/sdks/react-native/CHANGELOG.md b/docs/sdks/react-native/CHANGELOG.md index 1bc7d89373..56e176f08f 100644 --- a/docs/sdks/react-native/CHANGELOG.md +++ b/docs/sdks/react-native/CHANGELOG.md @@ -1,5 +1,18 @@ # Change log +## 0.10.0 + +* Add generate file URL methods like`getFilePreviewURL`, `getFileViewURL` etc. +* Update (breaking) existing methods like `getFilePreview` to download the image instead of returning URLs + +## 0.9.2 + +* Fix `devKeys` by removing credentials from requests when the key is set + +## 0.9.1 + +* Add `setDevkey` and `upsertDocument` methods + ## 0.9.0 * Add `token` param to `getFilePreview` and `getFileView` for File tokens usage From 2cbc399fd5385b9d70f42c6ae49ec428f6cfd7df Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 18 Jun 2025 14:46:55 +0300 Subject: [PATCH 199/343] update deleteProject scope --- src/Appwrite/Platform/Workers/Deletes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 8ed96c76a2..2f41001b58 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -495,7 +495,7 @@ class Deletes extends Action * @throws Authorization * @throws DatabaseException */ - private function deleteProject(Database $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForSites, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Document $document): void + protected function deleteProject(Database $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForSites, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Document $document): void { $projectInternalId = $document->getSequence(); $projectId = $document->getId(); From 89b559dd8f885fa7b24e4554fd37f66b844641df Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 18 Jun 2025 18:57:28 +0530 Subject: [PATCH 200/343] chore: update composer --- composer.json | 2 +- composer.lock | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index 1c1a9efbda..18507e04f1 100644 --- a/composer.json +++ b/composer.json @@ -86,7 +86,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "dev-PLA-2728", + "appwrite/sdk-generator": "0.41.*", "phpunit/phpunit": "9.*", "swoole/ide-helper": "5.1.2", "phpstan/phpstan": "1.8.*", diff --git a/composer.lock b/composer.lock index 584ee1292b..984f3e9fd3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "df602257a97ccc069f377903b57a2380", + "content-hash": "1557e469b3074a6478a0b2fd522e1a2a", "packages": [ { "name": "adhocore/jwt", @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "dev-PLA-2728", + "version": "0.41.8", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "9973cd6969f2a225ae88df28e99d19eac475f7c8" + "reference": "93ffb24b25b376ca4423e3a5caf6f916673af4b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/9973cd6969f2a225ae88df28e99d19eac475f7c8", - "reference": "9973cd6969f2a225ae88df28e99d19eac475f7c8", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/93ffb24b25b376ca4423e3a5caf6f916673af4b2", + "reference": "93ffb24b25b376ca4423e3a5caf6f916673af4b2", "shasum": "" }, "require": { @@ -4852,9 +4852,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/PLA-2728" + "source": "https://github.com/appwrite/sdk-generator/tree/0.41.8" }, - "time": "2025-06-18T08:06:19+00:00" + "time": "2025-06-18T13:20:45+00:00" }, { "name": "doctrine/annotations", @@ -8233,9 +8233,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "appwrite/sdk-generator": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From c93d92abef22927abdd3a7be942f1c2ecddbabc9 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 19 Jun 2025 10:52:15 +0530 Subject: [PATCH 201/343] rename: tests from `collections` to `legacy`. --- .github/workflows/tests.yml | 4 ++-- .../Databases/{Collections => Legacy}/DatabasesBase.php | 2 +- .../{Collections => Legacy}/DatabasesConsoleClientTest.php | 2 +- .../{Collections => Legacy}/DatabasesCustomClientTest.php | 2 +- .../{Collections => Legacy}/DatabasesCustomServerTest.php | 2 +- .../{Collections => Legacy}/DatabasesPermissionsGuestTest.php | 2 +- .../DatabasesPermissionsMemberTest.php | 2 +- .../{Collections => Legacy}/DatabasesPermissionsScope.php | 2 +- .../{Collections => Legacy}/DatabasesPermissionsTeamTest.php | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) rename tests/e2e/Services/Databases/{Collections => Legacy}/DatabasesBase.php (99%) rename tests/e2e/Services/Databases/{Collections => Legacy}/DatabasesConsoleClientTest.php (99%) rename tests/e2e/Services/Databases/{Collections => Legacy}/DatabasesCustomClientTest.php (99%) rename tests/e2e/Services/Databases/{Collections => Legacy}/DatabasesCustomServerTest.php (99%) rename tests/e2e/Services/Databases/{Collections => Legacy}/DatabasesPermissionsGuestTest.php (99%) rename tests/e2e/Services/Databases/{Collections => Legacy}/DatabasesPermissionsMemberTest.php (99%) rename tests/e2e/Services/Databases/{Collections => Legacy}/DatabasesPermissionsScope.php (98%) rename tests/e2e/Services/Databases/{Collections => Legacy}/DatabasesPermissionsTeamTest.php (99%) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index cf1e55f7ec..766b295fff 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -145,7 +145,7 @@ jobs: Account, Avatars, Console, - Databases/Collections, + Databases/Legacy, Databases/Tables, Functions, FunctionsSchedule, @@ -214,7 +214,7 @@ jobs: Account, Avatars, Console, - Databases/Collections, + Databases/Legacy, Databases/Tables, Functions, FunctionsSchedule, diff --git a/tests/e2e/Services/Databases/Collections/DatabasesBase.php b/tests/e2e/Services/Databases/Legacy/DatabasesBase.php similarity index 99% rename from tests/e2e/Services/Databases/Collections/DatabasesBase.php rename to tests/e2e/Services/Databases/Legacy/DatabasesBase.php index 6b0aca1512..69b24d5052 100644 --- a/tests/e2e/Services/Databases/Collections/DatabasesBase.php +++ b/tests/e2e/Services/Databases/Legacy/DatabasesBase.php @@ -1,6 +1,6 @@ Date: Thu, 19 Jun 2025 10:54:56 +0530 Subject: [PATCH 202/343] change: namespace. --- .../Databases/Http/Databases/Collections/Attributes/Action.php | 2 +- .../Databases/Http/Databases/Collections/Documents/Action.php | 2 +- .../Databases/Http/Databases/Collections/Indexes/Action.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 2ee265a18d..b115edbee8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -83,7 +83,7 @@ abstract class Action extends UtopiaAction */ final protected function getSdkNamespace(): string { - return $this->isCollectionsAPI() ? 'collections' : 'tables'; + return $this->isCollectionsAPI() ? 'databases' : 'tables'; } /** diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index 52dfc62f50..bd92e233f1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -78,7 +78,7 @@ abstract class Action extends UtopiaAction */ final protected function getSdkNamespace(): string { - return $this->isCollectionsAPI() ? 'collections' : 'tables'; + return $this->isCollectionsAPI() ? 'databases' : 'tables'; } /** diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php index 4a40ea6b5f..7013259fa7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php @@ -71,7 +71,7 @@ abstract class Action extends UtopiaAction */ final protected function getSdkNamespace(): string { - return $this->isCollectionsAPI() ? 'collections' : 'tables'; + return $this->isCollectionsAPI() ? 'databases' : 'tables'; } /** From e5caa856290a5403f0deef25b22edc4193dbe6dc Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 19 Jun 2025 11:02:31 +0530 Subject: [PATCH 203/343] update: init with module structure. --- app/controllers/general.php | 14 -------- .../Modules/Databases/Http/Init/Timeout.php | 35 +++++++++++++++++++ .../Modules/Databases/Services/Http.php | 2 ++ 3 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Http/Init/Timeout.php diff --git a/app/controllers/general.php b/app/controllers/general.php index 1872ba82e3..ba5b409a2b 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1582,20 +1582,6 @@ foreach (Config::getParam('services', []) as $service) { } } -// legacy controller init hooks as the endpoint controller logic is now moved to a module structure. -// 1. databases -App::init() - ->groups(['api', 'database']) - ->inject('request') - ->inject('dbForProject') - ->action(function (Request $request, Database $dbForProject) { - $timeout = \intval($request->getHeader('x-appwrite-timeout')); - - if (!empty($timeout) && App::isDevelopment()) { - $dbForProject->setTimeout($timeout); - } - }); - // Check for any errors found while we were initialising the SDK Methods. if (!empty(Method::getErrors())) { throw new \Exception('Errors found during SDK initialization:' . PHP_EOL . implode(PHP_EOL, Method::getErrors())); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Init/Timeout.php b/src/Appwrite/Platform/Modules/Databases/Http/Init/Timeout.php new file mode 100644 index 0000000000..19e202981b --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Init/Timeout.php @@ -0,0 +1,35 @@ +setType(Action::TYPE_INIT) + ->groups(['api', 'database']) + ->inject('request') + ->inject('dbForProject') + ->callback(function (Request $request, Database $dbForProject) { + $timeout = \intval($request->getHeader('x-appwrite-timeout')); + + if (!empty($timeout) && App::isDevelopment()) { + $dbForProject->setTimeout($timeout); + } + }); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Http.php b/src/Appwrite/Platform/Modules/Databases/Services/Http.php index 6c1361b0b1..a877c89345 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Http.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Http.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Services; +use Appwrite\Platform\Modules\Databases\Http\Init\Timeout; use Appwrite\Platform\Modules\Databases\Services\Registry\Collections as CollectionsRegistry; use Appwrite\Platform\Modules\Databases\Services\Registry\Databases as DatabasesRegistry; use Appwrite\Platform\Modules\Databases\Services\Registry\Tables as TablesRegistry; @@ -14,6 +15,7 @@ class Http extends Service $this->type = Service::TYPE_HTTP; foreach ([ + Timeout::class, DatabasesRegistry::class, CollectionsRegistry::class, TablesRegistry::class, From 1d23e2ec127bf53951f5718b2c4401a89887049a Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 19 Jun 2025 14:31:54 +0530 Subject: [PATCH 204/343] remove: `use HTTP`. update: inline context logic. --- .../Platform/Modules/Databases/Constants.php | 24 +++++++++++++++++ .../Platform/Modules/Databases/Context.php | 26 ------------------- .../Http/Databases/Collections/Action.php | 19 +++++--------- .../Collections/Attributes/Action.php | 18 +++++-------- .../Collections/Attributes/Boolean/Create.php | 3 --- .../Collections/Attributes/Boolean/Update.php | 3 --- .../Attributes/Datetime/Create.php | 3 --- .../Attributes/Datetime/Update.php | 3 --- .../Collections/Attributes/Delete.php | 3 --- .../Collections/Attributes/Email/Create.php | 3 --- .../Collections/Attributes/Email/Update.php | 3 --- .../Collections/Attributes/Enum/Create.php | 3 --- .../Collections/Attributes/Enum/Update.php | 3 --- .../Collections/Attributes/Float/Create.php | 3 --- .../Collections/Attributes/Float/Update.php | 3 --- .../Databases/Collections/Attributes/Get.php | 3 --- .../Collections/Attributes/IP/Create.php | 3 --- .../Collections/Attributes/IP/Update.php | 3 --- .../Collections/Attributes/Integer/Create.php | 3 --- .../Collections/Attributes/Integer/Update.php | 3 --- .../Attributes/Relationship/Create.php | 3 --- .../Attributes/Relationship/Update.php | 3 --- .../Collections/Attributes/String/Create.php | 3 --- .../Collections/Attributes/String/Update.php | 3 --- .../Collections/Attributes/URL/Create.php | 3 --- .../Collections/Attributes/URL/Update.php | 3 --- .../Collections/Attributes/XList.php | 3 --- .../Http/Databases/Collections/Create.php | 3 --- .../Http/Databases/Collections/Delete.php | 3 --- .../Collections/Documents/Action.php | 18 +++++-------- .../Documents/Attribute/Decrement.php | 3 --- .../Documents/Attribute/Increment.php | 3 --- .../Collections/Documents/Bulk/Delete.php | 3 --- .../Collections/Documents/Bulk/Update.php | 3 --- .../Collections/Documents/Bulk/Upsert.php | 3 --- .../Collections/Documents/Create.php | 3 --- .../Collections/Documents/Delete.php | 3 --- .../Databases/Collections/Documents/Get.php | 3 --- .../Collections/Documents/Logs/XList.php | 3 --- .../Collections/Documents/Update.php | 3 --- .../Collections/Documents/Upsert.php | 3 --- .../Databases/Collections/Documents/XList.php | 3 --- .../Http/Databases/Collections/Get.php | 3 --- .../Databases/Collections/Indexes/Action.php | 22 +++++----------- .../Databases/Collections/Indexes/Create.php | 3 --- .../Databases/Collections/Indexes/Delete.php | 3 --- .../Databases/Collections/Indexes/Get.php | 3 --- .../Databases/Collections/Indexes/XList.php | 3 --- .../Http/Databases/Collections/Logs/XList.php | 3 --- .../Http/Databases/Collections/Update.php | 3 --- .../Http/Databases/Collections/Usage/Get.php | 3 --- .../Http/Databases/Collections/XList.php | 8 +++--- .../Databases/Http/Databases/Create.php | 3 --- .../Databases/Http/Databases/Delete.php | 3 --- .../Modules/Databases/Http/Databases/Get.php | 3 --- .../Databases/Http/Databases/Logs/XList.php | 3 --- .../Tables/Columns/Boolean/Create.php | 6 ----- .../Tables/Columns/Boolean/Update.php | 6 ----- .../Tables/Columns/Datetime/Create.php | 6 ----- .../Tables/Columns/Datetime/Update.php | 6 ----- .../Http/Databases/Tables/Columns/Delete.php | 6 ----- .../Databases/Tables/Columns/Email/Create.php | 6 ----- .../Databases/Tables/Columns/Email/Update.php | 6 ----- .../Databases/Tables/Columns/Enum/Create.php | 6 ----- .../Databases/Tables/Columns/Enum/Update.php | 6 ----- .../Databases/Tables/Columns/Float/Create.php | 6 ----- .../Databases/Tables/Columns/Float/Update.php | 6 ----- .../Http/Databases/Tables/Columns/Get.php | 6 ----- .../Databases/Tables/Columns/IP/Create.php | 6 ----- .../Databases/Tables/Columns/IP/Update.php | 6 ----- .../Tables/Columns/Integer/Create.php | 6 ----- .../Tables/Columns/Integer/Update.php | 6 ----- .../Tables/Columns/Relationship/Create.php | 6 ----- .../Tables/Columns/Relationship/Update.php | 6 ----- .../Tables/Columns/String/Create.php | 6 ----- .../Tables/Columns/String/Update.php | 6 ----- .../Databases/Tables/Columns/URL/Create.php | 6 ----- .../Databases/Tables/Columns/URL/Update.php | 6 ----- .../Http/Databases/Tables/Columns/XList.php | 6 ----- .../Http/Databases/Tables/Create.php | 6 ----- .../Http/Databases/Tables/Delete.php | 6 ----- .../Databases/Http/Databases/Tables/Get.php | 6 ----- .../Http/Databases/Tables/Indexes/Create.php | 6 ----- .../Http/Databases/Tables/Indexes/Delete.php | 6 ----- .../Http/Databases/Tables/Indexes/Get.php | 6 ----- .../Http/Databases/Tables/Indexes/XList.php | 6 ----- .../Http/Databases/Tables/Logs/XList.php | 6 ----- .../Databases/Tables/Rows/Bulk/Delete.php | 6 ----- .../Databases/Tables/Rows/Bulk/Update.php | 6 ----- .../Databases/Tables/Rows/Bulk/Upsert.php | 6 ----- .../Tables/Rows/Column/Decrement.php | 6 ----- .../Tables/Rows/Column/Increment.php | 6 ----- .../Http/Databases/Tables/Rows/Create.php | 6 ----- .../Http/Databases/Tables/Rows/Delete.php | 6 ----- .../Http/Databases/Tables/Rows/Get.php | 6 ----- .../Http/Databases/Tables/Rows/Logs/XList.php | 6 ----- .../Http/Databases/Tables/Rows/Update.php | 6 ----- .../Http/Databases/Tables/Rows/Upsert.php | 6 ----- .../Http/Databases/Tables/Rows/XList.php | 6 ----- .../Http/Databases/Tables/Update.php | 6 ----- .../Http/Databases/Tables/Usage/Get.php | 6 ----- .../Databases/Http/Databases/Tables/XList.php | 6 ----- .../Databases/Http/Databases/Update.php | 3 --- .../Databases/Http/Databases/Usage/Get.php | 3 --- .../Databases/Http/Databases/Usage/XList.php | 3 --- .../Databases/Http/Databases/XList.php | 3 --- .../Platform/Modules/Databases/Module.php | 2 ++ .../Modules/Databases/Services/Http.php | 4 ++- .../Services/Registry/Collections.php | 2 ++ 109 files changed, 62 insertions(+), 516 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Databases/Constants.php delete mode 100644 src/Appwrite/Platform/Modules/Databases/Context.php diff --git a/src/Appwrite/Platform/Modules/Databases/Constants.php b/src/Appwrite/Platform/Modules/Databases/Constants.php new file mode 100644 index 0000000000..cfc297c3f4 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Constants.php @@ -0,0 +1,24 @@ +context = TABLES; } - $this->context = $context; + return parent::setHttpPath($path); } /** @@ -53,7 +48,7 @@ abstract class Action extends UtopiaAction */ final protected function isCollectionsAPI(): bool { - return $this->getContext() === Context::DATABASE_COLLECTIONS; + return $this->getContext() === COLLECTIONS; } /** diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index b115edbee8..0a977bce32 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -5,7 +5,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attribu use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; use Appwrite\Extend\Exception; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response as UtopiaResponse; use Throwable; @@ -29,25 +28,20 @@ abstract class Action extends UtopiaAction /** * @var string|null The current context (either 'column' or 'attribute') */ - private ?string $context = Context::DATABASE_ATTRIBUTES; + private ?string $context = ATTRIBUTES; /** * Get the correct response model. */ abstract protected function getResponseModel(): string|array; - /** - * Set the context to either `column` or `attribute`. - * - * @throws \InvalidArgumentException If the context is invalid. - */ - final protected function setContext(string $context): void + public function setHttpPath(string $path): UtopiaAction { - if (!\in_array($context, [Context::DATABASE_COLUMNS, Context::DATABASE_ATTRIBUTES], true)) { - throw new \InvalidArgumentException("Invalid context '$context'. Use `Context::DATABASE_COLUMNS` or `Context::DATABASE_ATTRIBUTES`"); + if (str_contains($path, '/:databaseId/tables')) { + $this->context = COLUMNS; } - $this->context = $context; + return parent::setHttpPath($path); } /** @@ -65,7 +59,7 @@ abstract class Action extends UtopiaAction { // columns in tables context // attributes in collections context - return $this->getContext() === Context::DATABASE_ATTRIBUTES; + return $this->getContext() === ATTRIBUTES; } /** diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php index b1fddc0371..c38ef8d703 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php @@ -13,14 +13,11 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createBooleanAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php index 7aa2360fb8..9bb606edf5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php @@ -12,15 +12,12 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Nullable; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateBooleanAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php index fd54fe0843..ff8054abe4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php @@ -14,14 +14,11 @@ use Utopia\Database\Document; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createDatetimeAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php index 17818fec2d..5f8909a294 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php @@ -13,15 +13,12 @@ use Utopia\Database\Database; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Nullable; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateDatetimeAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 4582500091..5dba0860e2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -15,13 +15,10 @@ use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\IndexDependency as IndexDependencyValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Delete extends Action { - use HTTP; - public static function getName(): string { return 'deleteAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php index 80f0270ea3..3c703f23a7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php @@ -14,14 +14,11 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createEmailAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php index 2f14d8a361..c8a34cf55c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php @@ -13,15 +13,12 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Nullable; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateEmailAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php index 006de12e91..99d540a4c2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php @@ -14,7 +14,6 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; @@ -22,8 +21,6 @@ use Utopia\Validator\Text; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createEnumAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php index c2f6d7696c..8624bde78d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php @@ -12,7 +12,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; @@ -21,8 +20,6 @@ use Utopia\Validator\Text; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateEnumAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php index 35e9bb68a1..520366f689 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php @@ -14,7 +14,6 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\FloatValidator; @@ -22,8 +21,6 @@ use Utopia\Validator\Range; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createFloatAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php index 2fdcf949f1..18a966d91d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php @@ -12,7 +12,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\FloatValidator; @@ -20,8 +19,6 @@ use Utopia\Validator\Nullable; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateFloatAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index d49639e049..d751e8def0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -11,13 +11,10 @@ use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Get extends Action { - use HTTP; - public static function getName(): string { return 'getAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php index c62e2add01..e46e508bc6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php @@ -13,15 +13,12 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\IP; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createIpAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php index a3e1ea5a61..e9d9404c17 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php @@ -12,7 +12,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\IP; @@ -20,8 +19,6 @@ use Utopia\Validator\Nullable; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateIpAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php index 69272b6aea..e348e9a2a6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php @@ -14,7 +14,6 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Integer; @@ -22,8 +21,6 @@ use Utopia\Validator\Range; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createIntegerAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php index 9c05382173..bbbf045115 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php @@ -12,7 +12,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Integer; @@ -20,8 +19,6 @@ use Utopia\Validator\Nullable; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateIntegerAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php index fa8d0ad750..795ea445c8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php @@ -15,15 +15,12 @@ use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\WhiteList; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createRelationshipAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php index da2d0b9b08..7202a3e4e6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php @@ -12,14 +12,11 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\WhiteList; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateRelationshipAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php index cc989f6687..8ce8626f3a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php @@ -14,7 +14,6 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator; use Utopia\Validator\Boolean; @@ -23,8 +22,6 @@ use Utopia\Validator\Text; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createStringAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php index b3f4cf3f03..b359b83eaa 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php @@ -12,7 +12,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator; use Utopia\Validator\Boolean; @@ -22,8 +21,6 @@ use Utopia\Validator\Text; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateStringAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php index 2d72533cf1..27bc2d38c1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php @@ -13,15 +13,12 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\URL; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createUrlAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php index e5c4288d92..ae48c43653 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php @@ -12,7 +12,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Nullable; @@ -20,8 +19,6 @@ use Utopia\Validator\URL; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateUrlAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 2509115e13..e09420d7ce 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -16,13 +16,10 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class XList extends Action { - use HTTP; - public static function getName(): string { return 'listAttributes'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php index 5edce7715f..176c3ca853 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -21,15 +21,12 @@ use Utopia\Database\Helpers\Permission; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Text; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createCollection'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php index b8080ab471..e4618a40b7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php @@ -13,13 +13,10 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Delete extends Action { - use HTTP; - public static function getName(): string { return 'deleteCollection'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index bd92e233f1..bfebca4cf7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -3,7 +3,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents; use Appwrite\Extend\Exception; -use Appwrite\Platform\Modules\Databases\Context; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; @@ -14,25 +13,20 @@ abstract class Action extends UtopiaAction /** * @var string|null The current context (either 'row' or 'document') */ - private ?string $context = Context::DATABASE_DOCUMENTS; + private ?string $context = DOCUMENTS; /** * Get the response model used in the SDK and HTTP responses. */ abstract protected function getResponseModel(): string; - /** - * Set the context to either `row` or `document`. - * - * @throws \InvalidArgumentException If the context is invalid. - */ - final protected function setContext(string $context): void + public function setHttpPath(string $path): UtopiaAction { - if (!\in_array($context, [Context::DATABASE_ROWS, Context::DATABASE_DOCUMENTS], true)) { - throw new \InvalidArgumentException("Invalid context '$context'. Use `Context::DATABASE_ROWS` or `Context::DATABASE_DOCUMENTS`"); + if (str_contains($path, '/:databaseId/tables')) { + $this->context = ROWS; } - $this->context = $context; + return parent::setHttpPath($path); } /** @@ -60,7 +54,7 @@ abstract class Action extends UtopiaAction { // rows in tables api context // documents in collections api context - return $this->getContext() === Context::DATABASE_DOCUMENTS; + return $this->getContext() === DOCUMENTS; } /** diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php index 9a8da5858c..40035ac302 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php @@ -19,14 +19,11 @@ use Utopia\Database\Exception\Type as TypeException; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Numeric; class Decrement extends Action { - use HTTP; - public static function getName(): string { return 'decrementDocumentAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php index b65ca3c285..90694d1c69 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php @@ -19,14 +19,11 @@ use Utopia\Database\Exception\Type as TypeException; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Numeric; class Increment extends Action { - use HTTP; - public static function getName(): string { return 'incrementDocumentAttribute'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php index bee3b35599..4ec852f7c5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php @@ -17,15 +17,12 @@ use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Exception\Restricted as RestrictedException; use Utopia\Database\Query; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Text; class Delete extends Action { - use HTTP; - public static function getName(): string { return 'deleteDocuments'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Update.php index 23c8d5d58e..d391c805fa 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Update.php @@ -19,7 +19,6 @@ use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Query; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\JSON; @@ -27,8 +26,6 @@ use Utopia\Validator\Text; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateDocuments'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php index 770f7a4d95..f4c8c2e6d2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php @@ -17,15 +17,12 @@ use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Exception\Relationship as RelationshipException; use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\JSON; class Upsert extends Action { - use HTTP; - public static function getName(): string { return 'upsertDocuments'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index ebab4a7ece..6c1fdae5e6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -25,15 +25,12 @@ use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\JSON; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createDocument'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index d8ec82910c..8c8cec2986 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -16,13 +16,10 @@ use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Restricted as RestrictedException; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Delete extends Action { - use HTTP; - public static function getName(): string { return 'deleteDocument'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index fe40a2412f..7376fe770a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -15,15 +15,12 @@ use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Text; class Get extends Action { - use HTTP; - public static function getName(): string { return 'getDocument'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php index 4f4dad9882..3fe25b9441 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php @@ -23,13 +23,10 @@ use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class XList extends Action { - use HTTP; - public static function getName(): string { return 'listDocumentLogs'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index c39eeea707..ce822ca713 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -23,14 +23,11 @@ use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\JSON; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateDocument'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php index fa632c7b2b..7a077fed0d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php @@ -24,14 +24,11 @@ use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\JSON; class Upsert extends Action { - use HTTP; - public static function getName(): string { return 'upsertDocument'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 9aad8f4b77..2e76942db1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -18,15 +18,12 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Text; class XList extends Action { - use HTTP; - public static function getName(): string { return 'listDocuments'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php index 0359025fc5..e35a924657 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php @@ -11,13 +11,10 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Get extends Action { - use HTTP; - public static function getName(): string { return 'getCollection'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php index 7013259fa7..33c2977be5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php @@ -3,7 +3,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes; use Appwrite\Extend\Exception; -use Appwrite\Platform\Modules\Databases\Context; use Utopia\Platform\Action as UtopiaAction; abstract class Action extends UtopiaAction @@ -11,25 +10,20 @@ abstract class Action extends UtopiaAction /** * The current API context (either 'columnIndex' or 'index'). */ - private ?string $context = Context::DATABASE_INDEX; + private ?string $context = INDEX; /** * Get the response model used in the SDK and HTTP responses. */ abstract protected function getResponseModel(): string; - /** - * Set the current API context. - * - * @param string $context Must be either `DATABASE_INDEX` or `DATABASE_COLUMN_INDEX`. - */ - final protected function setContext(string $context): void + public function setHttpPath(string $path): UtopiaAction { - if (!\in_array($context, [Context::DATABASE_INDEX, Context::DATABASE_COLUMN_INDEX], true)) { - throw new \InvalidArgumentException("Invalid context '$context'. Must be either `Context::DATABASE_COLUMN_INDEX` or `Context::DATABASE_INDEX`."); + if (str_contains($path, '/:databaseId/tables')) { + $this->context = COLUMN_INDEX; } - $this->context = $context; + return parent::setHttpPath($path); } /** @@ -37,9 +31,7 @@ abstract class Action extends UtopiaAction */ final protected function getParentContext(): string { - return $this->getContext() === Context::DATABASE_INDEX - ? Context::DATABASE_ATTRIBUTES - : Context::DATABASE_COLUMNS; + return $this->getContext() === INDEX ? ATTRIBUTES : COLUMNS; } /** @@ -55,7 +47,7 @@ abstract class Action extends UtopiaAction */ final protected function isCollectionsAPI(): bool { - return $this->getParentContext() === Context::DATABASE_ATTRIBUTES; + return $this->getParentContext() === ATTRIBUTES; } /** diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index 9dbd7924c6..9003fbb4a9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -19,7 +19,6 @@ use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Index as IndexValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Integer; @@ -28,8 +27,6 @@ use Utopia\Validator\WhiteList; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createIndex'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index bb0b7bc4ca..701ab103ad 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -14,13 +14,10 @@ use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Delete extends Action { - use HTTP; - public static function getName(): string { return 'deleteIndex'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php index e29bbf6647..c5b81fe231 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php @@ -12,13 +12,10 @@ use Utopia\Database\Database; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Get extends Action { - use HTTP; - public static function getName(): string { return 'getIndex'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index dae25a3335..36c52f711e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -17,13 +17,10 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class XList extends Action { - use HTTP; - public static function getName(): string { return 'listIndexes'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php index 2f9ac2c8c0..70bb14e9d8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php @@ -23,13 +23,10 @@ use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class XList extends Action { - use HTTP; - public static function getName(): string { return 'listCollectionLogs'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php index cc41d716d4..fd3b1e8bda 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php @@ -14,15 +14,12 @@ use Utopia\Database\Helpers\Permission; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Text; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateCollection'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php index 0c565806cc..e5335d6abf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Usage/Get.php @@ -15,14 +15,11 @@ use Utopia\Database\Document; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\WhiteList; class Get extends Action { - use HTTP; - public static function getName(): string { return 'getCollectionUsage'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index d3ddb9301f..ae63a40e64 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -17,14 +17,11 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Text; class XList extends Action { - use HTTP; - public static function getName(): string { return 'listCollections'; @@ -68,6 +65,11 @@ class XList extends Action public function action(string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject): void { + print_r(json_encode([ + 'context' => $this->getContext(), + 'model' => $this->getResponseModel() + ], JSON_PRETTY_PRINT)); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php index 3b9efa2fca..38374402fb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php @@ -19,15 +19,12 @@ use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; use Utopia\Platform\Action; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Text; class Create extends Action { - use HTTP; - public static function getName(): string { return 'createDatabase'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php index b9b475f699..56cf1a4296 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Delete.php @@ -13,13 +13,10 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Delete extends Action { - use HTTP; - public static function getName(): string { return 'deleteDatabase'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Get.php index c2c6a57da1..f478dc7917 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Get.php @@ -11,13 +11,10 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Get extends Action { - use HTTP; - public static function getName(): string { return 'getDatabase'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php index a531110398..52f2ad93b6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php @@ -23,13 +23,10 @@ use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; use Utopia\Platform\Action; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class XList extends Action { - use HTTP; - public static function getName(): string { return 'listDatabaseLogs'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php index b8675877f3..9e65e6e5b3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Boolean; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Boolean\Create as BooleanCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -10,14 +9,11 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; class Create extends BooleanCreate { - use HTTP; - public static function getName(): string { return 'createBooleanColumn'; @@ -30,8 +26,6 @@ class Create extends BooleanCreate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/boolean') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php index 09d01cae21..f7eff81ae3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Boolean; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Boolean\Update as BooleanUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,15 +10,12 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Nullable; class Update extends BooleanUpdate { - use HTTP; - public static function getName(): string { return 'updateBooleanColumn'; @@ -32,8 +28,6 @@ class Update extends BooleanUpdate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/boolean/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php index 34ead7c33d..5bb83733a4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Datetime; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Datetime\Create as DatetimeCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -12,14 +11,11 @@ use Utopia\Database\Database; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; class Create extends DatetimeCreate { - use HTTP; - public static function getName(): string { return 'createDatetimeColumn'; @@ -32,8 +28,6 @@ class Create extends DatetimeCreate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/datetime') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php index 5b026cd373..6710f76aaa 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Datetime; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Datetime\Update as DatetimeUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -13,15 +12,12 @@ use Utopia\Database\Database; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Nullable; class Update extends DatetimeUpdate { - use HTTP; - public static function getName(): string { return 'updateDatetimeColumn'; @@ -34,8 +30,6 @@ class Update extends DatetimeUpdate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/datetime/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php index 567cb02169..b85248e8c3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Delete as AttributesDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,13 +10,10 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Delete extends AttributesDelete { - use HTTP; - public static function getName(): string { return 'deleteColumn'; @@ -31,8 +27,6 @@ class Delete extends AttributesDelete public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php index f5bb2f5220..6aade1aa50 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php @@ -3,7 +3,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Email; use Appwrite\Network\Validator\Email; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Email\Create as EmailCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -11,14 +10,11 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; class Create extends EmailCreate { - use HTTP; - public static function getName(): string { return 'createEmailColumn'; @@ -31,8 +27,6 @@ class Create extends EmailCreate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/email') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php index faba9279b5..10213c87bb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php @@ -3,7 +3,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Email; use Appwrite\Network\Validator\Email; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Email\Update as EmailUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -12,15 +11,12 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Nullable; class Update extends EmailUpdate { - use HTTP; - public static function getName(): string { return 'updateEmailColumn'; @@ -33,8 +29,6 @@ class Update extends EmailUpdate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/email/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php index ec1d36a916..8e9a658aa8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Enum; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Enum\Create as EnumCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -11,7 +10,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; @@ -19,8 +17,6 @@ use Utopia\Validator\Text; class Create extends EnumCreate { - use HTTP; - public static function getName(): string { return 'createEnumColumn'; @@ -33,8 +29,6 @@ class Create extends EnumCreate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/enum') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php index ef2c829e0a..d1418e5144 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Enum; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Enum\Update as EnumUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -12,7 +11,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; @@ -21,8 +19,6 @@ use Utopia\Validator\Text; class Update extends EnumUpdate { - use HTTP; - public static function getName(): string { return 'updateEnumColumn'; @@ -35,8 +31,6 @@ class Update extends EnumUpdate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/enum/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php index 32579017c6..5c99b90f52 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Float; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Float\Create as FloatCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -10,15 +9,12 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\FloatValidator; class Create extends FloatCreate { - use HTTP; - public static function getName(): string { return 'createFloatColumn'; @@ -31,8 +27,6 @@ class Create extends FloatCreate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/float') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php index 4ed420cfa0..5360ca0304 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Float; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Float\Update as FloatUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,7 +10,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\FloatValidator; @@ -19,8 +17,6 @@ use Utopia\Validator\Nullable; class Update extends FloatUpdate { - use HTTP; - public static function getName(): string { return 'updateFloatColumn'; @@ -33,8 +29,6 @@ class Update extends FloatUpdate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/float/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php index ed28f96535..17777409d2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Get as AttributesGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -10,13 +9,10 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Get extends AttributesGet { - use HTTP; - public static function getName(): string { return 'getColumn'; @@ -40,8 +36,6 @@ class Get extends AttributesGet public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php index 8acc47f051..cb58a14cbe 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\IP; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\IP\Create as IPCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -10,15 +9,12 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\IP; class Create extends IPCreate { - use HTTP; - public static function getName(): string { return 'createIpColumn'; @@ -31,8 +27,6 @@ class Create extends IPCreate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/ip') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php index c43f132c13..ef4c62a51f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\IP; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\IP\Update as IPUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,7 +10,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\IP; @@ -19,8 +17,6 @@ use Utopia\Validator\Nullable; class Update extends IPUpdate { - use HTTP; - public static function getName(): string { return 'updateIpColumn'; @@ -33,8 +29,6 @@ class Update extends IPUpdate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/ip/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php index 7694e9d74f..6ca6cc4b93 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Integer; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Integer\Create as IntegerCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -10,15 +9,12 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Integer; class Create extends IntegerCreate { - use HTTP; - public static function getName(): string { return 'createIntegerColumn'; @@ -31,8 +27,6 @@ class Create extends IntegerCreate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/integer') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php index b3ce988830..764ae31f35 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Integer; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Integer\Update as IntegerUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,7 +10,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Integer; @@ -19,8 +17,6 @@ use Utopia\Validator\Nullable; class Update extends IntegerUpdate { - use HTTP; - public static function getName(): string { return 'updateIntegerColumn'; @@ -33,8 +29,6 @@ class Update extends IntegerUpdate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/integer/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php index 133f772605..20e89396a0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Relationship; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Relationship\Create as RelationshipCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -11,15 +10,12 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\WhiteList; class Create extends RelationshipCreate { - use HTTP; - public static function getName(): string { return 'createRelationshipColumn'; @@ -32,8 +28,6 @@ class Create extends RelationshipCreate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/relationship') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php index ef1d8c7a33..508c5da57a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\Relationship; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Relationship\Update as RelationshipUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -12,14 +11,11 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\WhiteList; class Update extends RelationshipUpdate { - use HTTP; - public static function getName(): string { return 'updateRelationshipColumn'; @@ -32,8 +28,6 @@ class Update extends RelationshipUpdate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key/relationship') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php index ed7989fbc3..a11ee3464e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\String; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\String\Create as StringCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -10,7 +9,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator; use Utopia\Validator\Boolean; @@ -19,8 +17,6 @@ use Utopia\Validator\Text; class Create extends StringCreate { - use HTTP; - public static function getName(): string { return 'createStringColumn'; @@ -33,8 +29,6 @@ class Create extends StringCreate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/string') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php index f7ec773e3c..92df091866 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\String; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\String\Update as StringUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,7 +10,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator; use Utopia\Validator\Boolean; @@ -21,8 +19,6 @@ use Utopia\Validator\Text; class Update extends StringUpdate { - use HTTP; - public static function getName(): string { return 'updateStringColumn'; @@ -35,8 +31,6 @@ class Update extends StringUpdate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/string/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php index 0e6fe7cff3..84c488ccfc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\URL; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\URL\Create as URLCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -10,15 +9,12 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\URL; class Create extends URLCreate { - use HTTP; - public static function getName(): string { return 'createUrlColumn'; @@ -31,8 +27,6 @@ class Create extends URLCreate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/url') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php index 6f3698c0cf..d3681b9358 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns\URL; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\URL\Update as URLUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,7 +10,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Nullable; @@ -19,8 +17,6 @@ use Utopia\Validator\URL; class Update extends URLUpdate { - use HTTP; - public static function getName(): string { return 'updateUrlColumn'; @@ -33,8 +29,6 @@ class Update extends URLUpdate public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/url/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php index c6ceb35f48..29a108f180 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Columns; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\XList as AttributesXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; @@ -10,13 +9,10 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Columns; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class XList extends AttributesXList { - use HTTP; - public static function getName(): string { return 'listColumns'; @@ -29,8 +25,6 @@ class XList extends AttributesXList public function __construct() { - $this->setContext(Context::DATABASE_COLUMNS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php index c20865d110..273791f154 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Create as CollectionCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -12,15 +11,12 @@ use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Text; class Create extends CollectionCreate { - use HTTP; - public static function getName(): string { return 'createTable'; @@ -33,8 +29,6 @@ class Create extends CollectionCreate public function __construct() { - $this->setContext(Context::DATABASE_TABLES); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php index 85e52ac37d..0a20a20f54 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Delete as CollectionDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -10,13 +9,10 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Delete extends CollectionDelete { - use HTTP; - public static function getName(): string { return 'deleteTable'; @@ -29,8 +25,6 @@ class Delete extends CollectionDelete public function __construct() { - $this->setContext(Context::DATABASE_TABLES); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php index 473dfb6273..7f565231f9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Get as CollectionGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -10,13 +9,10 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Get extends CollectionGet { - use HTTP; - public static function getName(): string { return 'getTable'; @@ -29,8 +25,6 @@ class Get extends CollectionGet public function __construct() { - $this->setContext(Context::DATABASE_TABLES); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php index e57e962e87..b11892e0f9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Create as IndexCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -12,7 +11,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Integer; @@ -21,8 +19,6 @@ use Utopia\Validator\WhiteList; class Create extends IndexCreate { - use HTTP; - public static function getName(): string { return 'createColumnIndex'; @@ -35,8 +31,6 @@ class Create extends IndexCreate public function __construct() { - $this->setContext(Context::DATABASE_COLUMN_INDEX); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php index 7cda1ce471..4ff9638f27 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Delete as IndexDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,13 +10,10 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Delete extends IndexDelete { - use HTTP; - public static function getName(): string { return 'updateColumnIndex'; @@ -34,8 +30,6 @@ class Delete extends IndexDelete public function __construct() { - $this->setContext(Context::DATABASE_COLUMN_INDEX); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php index 3bee87de4a..79529fda66 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Get as IndexGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,13 +10,10 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Get extends IndexGet { - use HTTP; - public static function getName(): string { return 'getColumnIndex'; @@ -30,8 +26,6 @@ class Get extends IndexGet public function __construct() { - $this->setContext(Context::DATABASE_COLUMN_INDEX); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes/:key') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php index 1af13dc82e..12581a4fc3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Indexes; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\XList as IndexXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,13 +10,10 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Indexes; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class XList extends IndexXList { - use HTTP; - public static function getName(): string { return 'listColumnIndexes'; @@ -30,8 +26,6 @@ class XList extends IndexXList public function __construct() { - $this->setContext(Context::DATABASE_COLUMN_INDEX); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php index 244cebe3ad..8e652c5416 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Logs; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Logs\XList as CollectionLogXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -12,13 +11,10 @@ use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class XList extends CollectionLogXList { - use HTTP; - public static function getName(): string { return 'listTableLogs'; @@ -26,8 +22,6 @@ class XList extends CollectionLogXList public function __construct() { - $this->setContext(Context::DATABASE_TABLES); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/logs') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php index 9ddff818e3..945450aee3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Bulk; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Delete as DocumentsDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -10,15 +9,12 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Text; class Delete extends DocumentsDelete { - use HTTP; - public static function getName(): string { return 'deleteRows'; @@ -31,8 +27,6 @@ class Delete extends DocumentsDelete public function __construct() { - $this->setContext(Context::DATABASE_ROWS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php index 1b9ddb60ab..916d683491 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Bulk; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Update as DocumentsUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -10,7 +9,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\JSON; @@ -18,8 +16,6 @@ use Utopia\Validator\Text; class Update extends DocumentsUpdate { - use HTTP; - public static function getName(): string { return 'updateRows'; @@ -32,8 +28,6 @@ class Update extends DocumentsUpdate public function __construct() { - $this->setContext(Context::DATABASE_ROWS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php index 2b4117c23e..65c848a7c4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Bulk; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bulk\Upsert as DocumentsUpsert; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -10,15 +9,12 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\JSON; class Upsert extends DocumentsUpsert { - use HTTP; - public static function getName(): string { return 'upsertRows'; @@ -31,8 +27,6 @@ class Upsert extends DocumentsUpsert public function __construct() { - $this->setContext(Context::DATABASE_ROWS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php index 128d578cde..916c051d8a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Column; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Attribute\Decrement as DecrementDocumentAttribute; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,14 +10,11 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Numeric; class Decrement extends DecrementDocumentAttribute { - use HTTP; - public static function getName(): string { return 'decrementRowColumn'; @@ -31,8 +27,6 @@ class Decrement extends DecrementDocumentAttribute public function __construct() { - $this->setContext(Context::DATABASE_ROWS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId/:column/decrement') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php index a3e256d561..ba78833744 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Column; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Attribute\Increment as IncrementDocumentAttribute; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,14 +10,11 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Numeric; class Increment extends IncrementDocumentAttribute { - use HTTP; - public static function getName(): string { return 'incrementRowColumn'; @@ -31,8 +27,6 @@ class Increment extends IncrementDocumentAttribute public function __construct() { - $this->setContext(Context::DATABASE_ROWS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId/:column/increment') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php index 03e5548ddb..ba2b461d6e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Create as DocumentCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -14,15 +13,12 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\JSON; class Create extends DocumentCreate { - use HTTP; - public static function getName(): string { return 'createRow'; @@ -40,8 +36,6 @@ class Create extends DocumentCreate public function __construct() { - $this->setContext(Context::DATABASE_ROWS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php index 5edf4e0b73..27fe101f1d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Delete as DocumentDelete; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -10,13 +9,10 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class Delete extends DocumentDelete { - use HTTP; - public static function getName(): string { return 'deleteRow'; @@ -35,8 +31,6 @@ class Delete extends DocumentDelete public function __construct() { - $this->setContext(Context::DATABASE_ROWS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php index 74e1f90497..8100abbea5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Get as DocumentGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -10,15 +9,12 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Text; class Get extends DocumentGet { - use HTTP; - public static function getName(): string { return 'getRow'; @@ -31,8 +27,6 @@ class Get extends DocumentGet public function __construct() { - $this->setContext(Context::DATABASE_ROWS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php index 1cc5202152..f39a77323f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows\Logs; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Logs\XList as DocumentLogXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -12,13 +11,10 @@ use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; class XList extends DocumentLogXList { - use HTTP; - public static function getName(): string { return 'listRowLogs'; @@ -26,8 +22,6 @@ class XList extends DocumentLogXList public function __construct() { - $this->setContext(Context::DATABASE_ROWS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId/logs') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php index d37f5cc92f..9fa596ecc0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Update as DocumentUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -12,14 +11,11 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\JSON; class Update extends DocumentUpdate { - use HTTP; - public static function getName(): string { return 'updateRow'; @@ -32,8 +28,6 @@ class Update extends DocumentUpdate public function __construct() { - $this->setContext(Context::DATABASE_ROWS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php index 800efa9cde..5c0fde708b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Upsert as DocumentUpsert; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -12,14 +11,11 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\JSON; class Upsert extends DocumentUpsert { - use HTTP; - public static function getName(): string { return 'upsertRow'; @@ -32,8 +28,6 @@ class Upsert extends DocumentUpsert public function __construct() { - $this->setContext(Context::DATABASE_ROWS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php index 9d03603a0e..b7ad763e36 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Rows; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\XList as DocumentXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -10,15 +9,12 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Text; class XList extends DocumentXList { - use HTTP; - public static function getName(): string { return 'listRows'; @@ -31,8 +27,6 @@ class XList extends DocumentXList public function __construct() { - $this->setContext(Context::DATABASE_ROWS); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php index ab71634fb2..210b281e57 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Update as CollectionUpdate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,15 +10,12 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Text; class Update extends CollectionUpdate { - use HTTP; - public static function getName(): string { return 'updateTable'; @@ -32,8 +28,6 @@ class Update extends CollectionUpdate public function __construct() { - $this->setContext(Context::DATABASE_TABLES); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php index 9fb5fc8c17..c82eaae7c5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables\Usage; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Usage\Get as CollectionUsageGet; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -10,14 +9,11 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\WhiteList; class Get extends CollectionUsageGet { - use HTTP; - public static function getName(): string { return 'getTableUsage'; @@ -30,8 +26,6 @@ class Get extends CollectionUsageGet public function __construct() { - $this->setContext(Context::DATABASE_TABLES); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/usage') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php index f6f48ace40..391b91a3dd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php @@ -2,7 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Tables; -use Appwrite\Platform\Modules\Databases\Context; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\XList as CollectionXList; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,14 +10,11 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Tables; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Text; class XList extends CollectionXList { - use HTTP; - public static function getName(): string { return 'listTables'; @@ -31,8 +27,6 @@ class XList extends CollectionXList public function __construct() { - $this->setContext(Context::DATABASE_TABLES); - $this ->setHttpMethod(self::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/databases/:databaseId/tables') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Update.php index a0e440c657..a746f4ce4c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Update.php @@ -12,15 +12,12 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Boolean; use Utopia\Validator\Text; class Update extends Action { - use HTTP; - public static function getName(): string { return 'updateDatabase'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php index 1a85380767..5482d25269 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -15,14 +15,11 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\WhiteList; class Get extends Action { - use HTTP; - public static function getName(): string { return 'getUsage'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php index 2d551465db..fd3a95cd24 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -13,14 +13,11 @@ use Utopia\Database\Document; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\WhiteList; class XList extends Action { - use HTTP; - public static function getName(): string { return 'listUsages'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php index 7179be90ec..52f3fd2b55 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php @@ -16,14 +16,11 @@ use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Query\Cursor; use Utopia\Platform\Action; -use Utopia\Platform\Scope\HTTP; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Text; class XList extends Action { - use HTTP; - public static function getName(): string { return 'listDatabases'; diff --git a/src/Appwrite/Platform/Modules/Databases/Module.php b/src/Appwrite/Platform/Modules/Databases/Module.php index f8686999dd..bf336413d4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Module.php +++ b/src/Appwrite/Platform/Modules/Databases/Module.php @@ -2,6 +2,8 @@ namespace Appwrite\Platform\Modules\Databases; +require_once __DIR__ . '/Constants.php'; + use Appwrite\Platform\Modules\Databases\Services\Http; use Appwrite\Platform\Modules\Databases\Services\Workers; use Utopia\Platform; diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Http.php b/src/Appwrite/Platform/Modules/Databases/Services/Http.php index a877c89345..d2f66f3657 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Http.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Http.php @@ -14,8 +14,10 @@ class Http extends Service { $this->type = Service::TYPE_HTTP; + // Project database timeout init hook! + $this->addAction(Timeout::getName(), new Timeout()); + foreach ([ - Timeout::class, DatabasesRegistry::class, CollectionsRegistry::class, TablesRegistry::class, diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php index d036d2fd7b..bb0002ed47 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php @@ -35,6 +35,7 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Bul use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Create as CreateDocument; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Delete as DeleteDocument; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Get as GetDocument; +use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Logs\XList as ListDocumentLogs; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Update as UpdateDocument; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Upsert as UpsertDocument; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\XList as ListDocuments; @@ -90,6 +91,7 @@ class Collections extends Base $service->addAction(DeleteDocument::getName(), new DeleteDocument()); $service->addAction(DeleteDocuments::getName(), new DeleteDocuments()); $service->addAction(ListDocuments::getName(), new ListDocuments()); + $service->addAction(ListDocumentLogs::getName(), new ListDocumentLogs()); $service->addAction(IncrementDocumentAttribute::getName(), new IncrementDocumentAttribute()); $service->addAction(DecrementDocumentAttribute::getName(), new DecrementDocumentAttribute()); From 03b40262331cfae6a01b8fff5913ab3c79b9a25c Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 19 Jun 2025 14:33:23 +0530 Subject: [PATCH 205/343] remove: leftover. --- .../Http/Databases/Collections/Documents/Attribute/Increment.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php index 90694d1c69..6755d313c0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php @@ -99,7 +99,6 @@ class Increment extends Action } catch (ConflictException) { throw new Exception($this->getConflictException()); } catch (NotFoundException) { - // todo: @itznotabug what do we name this exception now? throw new Exception($this->getStructureNotFoundException()); } catch (LimitException) { throw new Exception($this->getLimitException(), $this->getSdkNamespace() . ' "' . $attribute . '" has reached the maximum value of ' . $max); From 60ab787894f963b38fb6a3449ca26e848d3d4a21 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 19 Jun 2025 14:33:58 +0530 Subject: [PATCH 206/343] address comments. --- .../Databases/Http/Databases/Collections/Attributes/Action.php | 2 +- .../Databases/Http/Databases/Collections/Attributes/Delete.php | 2 +- .../Databases/Http/Databases/Collections/Attributes/Get.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 0a977bce32..3f331edc9a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -221,7 +221,7 @@ abstract class Action extends UtopiaAction /** * Get the proper column/attribute type based on set context. */ - final protected function getCorrectModel(string $type, string $format): string + final protected function getModel(string $type, string $format): string { $isCollections = $this->isCollectionsAPI(); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 5dba0860e2..271ea56f29 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -138,7 +138,7 @@ class Delete extends Action $type = $attribute->getAttribute('type'); $format = $attribute->getAttribute('format'); - $model = $this->getCorrectModel($type, $format); + $model = $this->getModel($type, $format); $queueForEvents ->setContext('database', $db) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index d751e8def0..579f7883e0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -91,7 +91,7 @@ class Get extends Action $attribute->setAttribute($key, $option); } - $model = $this->getCorrectModel($type, $format); + $model = $this->getModel($type, $format); $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); From 3d6acaa19c7e25bce884bbb0397d3ff4b6993a36 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 19 Jun 2025 14:49:42 +0530 Subject: [PATCH 207/343] address comments. --- .../Platform/Modules/Databases/Http/Databases/Tables/Create.php | 2 +- .../Platform/Modules/Databases/Http/Databases/Tables/Update.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php index 273791f154..92b29ffdc6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php @@ -57,7 +57,7 @@ class Create extends CollectionCreate ->param('tableId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('name', '', new Text(128), 'Table name. Max length: 128 chars.') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) - ->param('rowSecurity', false, new Boolean(true), 'Enables configuring permissions for individual rows. A user needs one of row or table level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->param('rowSecurity', false, new Boolean(true), 'Enables configuring permissions for individual rows. A user needs one of row or table level permissions to access a row. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('enabled', true, new Boolean(), 'Is table enabled? When set to \'disabled\', users cannot access the table but Server SDKs with and API key can still read and write to the table. No data is lost when this is toggled.', true) ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php index 210b281e57..62a1b3bdee 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php @@ -54,7 +54,7 @@ class Update extends CollectionUpdate )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID.') - ->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.') + ->param('name', null, new Text(128), 'Table name. Max length: 128 chars.') ->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('rowSecurity', false, new Boolean(true), 'Enables configuring permissions for individual rows. A user needs one of row or table level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('enabled', true, new Boolean(), 'Is table enabled? When set to \'disabled\', users cannot access the table but Server SDKs with and API key can still read and write to the table. No data is lost when this is toggled.', true) From caf23083003a4ac44897018a684ffe38ff6328a0 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 19 Jun 2025 14:50:15 +0530 Subject: [PATCH 208/343] address comment. --- .../Modules/Databases/Http/Databases/Collections/XList.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index ae63a40e64..3a9868dec2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -65,11 +65,6 @@ class XList extends Action public function action(string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject): void { - print_r(json_encode([ - 'context' => $this->getContext(), - 'model' => $this->getResponseModel() - ], JSON_PRETTY_PRINT)); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { From 5287a3d6190960320888ab2ebe7bb88779927f41 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 19 Jun 2025 14:52:01 +0530 Subject: [PATCH 209/343] address comment. --- .../Databases/Http/Databases/Collections/Attributes/Delete.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 271ea56f29..5816de31a2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -26,7 +26,6 @@ class Delete extends Action protected function getResponseModel(): string|array { - // we should correctly & carefully set the context later. return UtopiaResponse::MODEL_NONE; } From 7ebe8f6c9e687b665166d481697c60866a9addc6 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 19 Jun 2025 17:34:16 +0530 Subject: [PATCH 210/343] revert: legacy tests namespacing to old. --- tests/e2e/Services/GraphQL/Base.php | 80 ++++++------ .../{Collections => Legacy}/AbuseTest.php | 2 +- .../{Collections => Legacy}/AuthTest.php | 8 +- .../DatabaseClientTest.php | 22 ++-- .../DatabaseServerTest.php | 118 +++++++++--------- 5 files changed, 115 insertions(+), 115 deletions(-) rename tests/e2e/Services/GraphQL/{Collections => Legacy}/AbuseTest.php (99%) rename tests/e2e/Services/GraphQL/{Collections => Legacy}/AuthTest.php (96%) rename tests/e2e/Services/GraphQL/{Collections => Legacy}/DatabaseClientTest.php (94%) rename tests/e2e/Services/GraphQL/{Collections => Legacy}/DatabaseServerTest.php (91%) diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index f001265caf..3da4dc11a3 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -626,7 +626,7 @@ trait Base }'; case self::$CREATE_STRING_ATTRIBUTE: return 'mutation createStringAttribute($databaseId: String!, $collectionId: String!, $key: String!, $size: Int!, $required: Boolean!, $default: String, $array: Boolean){ - collectionsCreateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, size: $size, required: $required, default: $default, array: $array) { + databasesCreateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, size: $size, required: $required, default: $default, array: $array) { key required default @@ -635,7 +635,7 @@ trait Base }'; case self::$CREATE_INTEGER_ATTRIBUTE: return 'mutation createIntegerAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Int, $max: Int, $default: Int, $array: Boolean){ - collectionsCreateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { + databasesCreateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { key required min @@ -646,7 +646,7 @@ trait Base }'; case self::$CREATE_FLOAT_ATTRIBUTE: return 'mutation createFloatAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Float, $max: Float, $default: Float, $array: Boolean){ - collectionsCreateFloatAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { + databasesCreateFloatAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default, array: $array) { key required min @@ -657,7 +657,7 @@ trait Base }'; case self::$CREATE_BOOLEAN_ATTRIBUTE: return 'mutation createBooleanAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: Boolean, $array: Boolean){ - collectionsCreateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + databasesCreateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default @@ -666,7 +666,7 @@ trait Base }'; case self::$CREATE_URL_ATTRIBUTE: return 'mutation createUrlAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - collectionsCreateUrlAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + databasesCreateUrlAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default @@ -675,7 +675,7 @@ trait Base }'; case self::$CREATE_EMAIL_ATTRIBUTE: return 'mutation createEmailAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - collectionsCreateEmailAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + databasesCreateEmailAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default @@ -684,7 +684,7 @@ trait Base }'; case self::$CREATE_IP_ATTRIBUTE: return 'mutation createIpAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - collectionsCreateIpAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + databasesCreateIpAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default @@ -693,7 +693,7 @@ trait Base }'; case self::$CREATE_ENUM_ATTRIBUTE: return 'mutation createEnumAttribute($databaseId: String!, $collectionId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String, $array: Boolean){ - collectionsCreateEnumAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, elements: $elements, required: $required, default: $default, array: $array) { + databasesCreateEnumAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, elements: $elements, required: $required, default: $default, array: $array) { key elements required @@ -703,7 +703,7 @@ trait Base }'; case self::$CREATE_DATETIME_ATTRIBUTE: return 'mutation createDatetimeAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ - collectionsCreateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { + databasesCreateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default, array: $array) { key required default @@ -712,7 +712,7 @@ trait Base }'; case self::$CREATE_RELATIONSHIP_ATTRIBUTE: return 'mutation createRelationshipAttribute($databaseId: String!, $collectionId: String!, $relatedCollectionId: String!, $type: String!, $twoWay: Boolean, $key: String, $twoWayKey: String, $onDelete: String){ - collectionsCreateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, relatedCollectionId: $relatedCollectionId, type: $type, twoWay: $twoWay, key: $key, twoWayKey: $twoWayKey, onDelete: $onDelete) { + databasesCreateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, relatedCollectionId: $relatedCollectionId, type: $type, twoWay: $twoWay, key: $key, twoWayKey: $twoWayKey, onDelete: $onDelete) { relatedCollection relationType twoWay @@ -723,14 +723,14 @@ trait Base }'; case self::$UPDATE_STRING_ATTRIBUTE: return 'mutation updateStringAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - collectionsUpdateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + databasesUpdateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; case self::$UPDATE_INTEGER_ATTRIBUTE: return 'mutation updateIntegerAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Int!, $max: Int!, $default: Int){ - collectionsUpdateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, min: $min, max: $max, default: $default) { + databasesUpdateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, min: $min, max: $max, default: $default) { required min max @@ -739,7 +739,7 @@ trait Base }'; case self::$UPDATE_FLOAT_ATTRIBUTE: return 'mutation updateFloatAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $min: Float!, $max: Float!, $default: Float){ - collectionsUpdateFloatAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default) { + databasesUpdateFloatAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, min: $min, max: $max, required: $required, default: $default) { required min max @@ -748,35 +748,35 @@ trait Base }'; case self::$UPDATE_BOOLEAN_ATTRIBUTE: return 'mutation updateBooleanAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: Boolean){ - collectionsUpdateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + databasesUpdateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; case self::$UPDATE_URL_ATTRIBUTE: return 'mutation updateUrlAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - collectionsUpdateUrlAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + databasesUpdateUrlAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; case self::$UPDATE_EMAIL_ATTRIBUTE: return 'mutation updateEmailAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - collectionsUpdateEmailAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + databasesUpdateEmailAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; case self::$UPDATE_IP_ATTRIBUTE: return 'mutation updateIpAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - collectionsUpdateIpAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + databasesUpdateIpAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; case self::$UPDATE_ENUM_ATTRIBUTE: return 'mutation updateEnumAttribute($databaseId: String!, $collectionId: String!, $key: String!, $elements: [String!]!, $required: Boolean!, $default: String){ - collectionsUpdateEnumAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, elements: $elements, required: $required, default: $default) { + databasesUpdateEnumAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, elements: $elements, required: $required, default: $default) { elements required default @@ -784,14 +784,14 @@ trait Base }'; case self::$UPDATE_DATETIME_ATTRIBUTE: return 'mutation updateDatetimeAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ - collectionsUpdateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { + databasesUpdateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { required default } }'; case self::$UPDATE_RELATIONSHIP_ATTRIBUTE: return 'mutation updateRelationshipAttribute($databaseId: String!, $collectionId: String!, $key: String!, $onDelete: String){ - collectionsUpdateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, onDelete: $onDelete) { + databasesUpdateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, onDelete: $onDelete) { relatedCollection relationType twoWay @@ -978,7 +978,7 @@ trait Base }'; case self::$CREATE_INDEX: return 'mutation createIndex($databaseId: String!, $collectionId: String!, $key: String!, $type: String!, $attributes: [String!]!, $orders: [String!]){ - collectionsCreateIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key, type: $type, attributes: $attributes, orders: $orders) { + databasesCreateIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key, type: $type, attributes: $attributes, orders: $orders) { key type status @@ -986,7 +986,7 @@ trait Base }'; case self::$GET_INDEXES: return 'query listIndexes($databaseId: String!, $collectionId: String!) { - collectionsListIndexes(databaseId: $databaseId, collectionId: $collectionId) { + databasesListIndexes(databaseId: $databaseId, collectionId: $collectionId) { total indexes { key @@ -997,7 +997,7 @@ trait Base }'; case self::$GET_INDEX: return 'query getIndex($databaseId: String!, $collectionId: String!, $key: String!) { - collectionsGetIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key) { + databasesGetIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key) { key type status @@ -1005,7 +1005,7 @@ trait Base }'; case self::$DELETE_INDEX: return 'mutation deleteIndex($databaseId: String!, $collectionId: String!, $key: String!) { - collectionsDeleteIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key) { + databasesDeleteIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key) { status } }'; @@ -1044,7 +1044,7 @@ trait Base }'; case self::$GET_ATTRIBUTES: return 'query listAttributes($databaseId: String!, $collectionId: String!) { - collectionsListAttributes(databaseId: $databaseId, collectionId: $collectionId) { + databasesListAttributes(databaseId: $databaseId, collectionId: $collectionId) { total attributes { ...attributeProperties @@ -1053,13 +1053,13 @@ trait Base }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; case self::$GET_ATTRIBUTE: return 'query getAttribute($databaseId: String!, $collectionId: String!, $key: String!) { - collectionsGetAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { + databasesGetAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { ...attributeProperties } }' . PHP_EOL . self::$FRAGMENT_ATTRIBUTES; case self::$DELETE_ATTRIBUTE: return 'mutation deleteAttribute($databaseId: String!, $collectionId: String!, $key: String!) { - collectionsDeleteAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { + databasesDeleteAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key) { status } }'; @@ -1087,7 +1087,7 @@ trait Base case self::$GET_DOCUMENT: return 'query getDocument($databaseId: String!, $collectionId: String!, $documentId: String!) { - collectionsGetDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { + databasesGetDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { _id _collectionId _permissions @@ -1096,7 +1096,7 @@ trait Base }'; case self::$GET_DOCUMENTS: return 'query listDocuments($databaseId: String!, $collectionId: String!){ - collectionsListDocuments(databaseId: $databaseId, collectionId: $collectionId) { + databasesListDocuments(databaseId: $databaseId, collectionId: $collectionId) { total documents { _id @@ -1108,7 +1108,7 @@ trait Base }'; case self::$CREATE_DOCUMENT: return 'mutation createDocument($databaseId: String!, $collectionId: String!, $documentId: String!, $data: Json!, $permissions: [String!]){ - collectionsCreateDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { + databasesCreateDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { _id _collectionId _permissions @@ -1116,7 +1116,7 @@ trait Base }'; case self::$CREATE_DOCUMENTS: return 'mutation createDocuments($databaseId: String!, $collectionId: String!, $documents: [Json!]!) { - collectionsCreateDocuments(databaseId: $databaseId, collectionId: $collectionId, documents: $documents) { + databasesCreateDocuments(databaseId: $databaseId, collectionId: $collectionId, documents: $documents) { documents { _id _collectionId @@ -1227,7 +1227,7 @@ trait Base }'; case self::$UPDATE_DOCUMENT: return 'mutation updateDocument($databaseId: String!, $collectionId: String!, $documentId: String!, $data: Json!, $permissions: [String!]){ - collectionsUpdateDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { + databasesUpdateDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { _id _collectionId data @@ -1235,7 +1235,7 @@ trait Base }'; case self::$UPSERT_DOCUMENT: return 'mutation upsertDocument($databaseId: String!, $collectionId: String!, $documentId: String!, $data: Json!, $permissions: [String!] = []) { - collectionsUpsertDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { + databasesUpsertDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId, data: $data, permissions: $permissions) { _id _databaseId _collectionId @@ -1244,7 +1244,7 @@ trait Base }'; case self::$UPDATE_DOCUMENTS: return 'mutation updateDocuments($databaseId: String!, $collectionId: String!, $data: Json!, $queries: [String!]) { - collectionsUpdateDocuments(databaseId: $databaseId, collectionId: $collectionId, data: $data, queries: $queries) { + databasesUpdateDocuments(databaseId: $databaseId, collectionId: $collectionId, data: $data, queries: $queries) { total documents { _id @@ -1257,7 +1257,7 @@ trait Base }'; case self::$UPSERT_DOCUMENTS: return 'mutation upsertDocuments($databaseId: String!, $collectionId: String!, $documents: [Json!]!) { - collectionsUpsertDocuments(databaseId: $databaseId, collectionId: $collectionId, documents: $documents) { + databasesUpsertDocuments(databaseId: $databaseId, collectionId: $collectionId, documents: $documents) { total documents { _id @@ -1270,7 +1270,7 @@ trait Base }'; case self::$DELETE_DOCUMENTS: return 'mutation deleteDocuments($databaseId: String!, $collectionId: String!, $queries: [String!] = []) { - collectionsDeleteDocuments(databaseId: $databaseId, collectionId: $collectionId, queries: $queries) { + databasesDeleteDocuments(databaseId: $databaseId, collectionId: $collectionId, queries: $queries) { total documents { _id @@ -1282,7 +1282,7 @@ trait Base }'; case self::$DELETE_DOCUMENT: return 'mutation deleteDocument($databaseId: String!, $collectionId: String!, $documentId: String!){ - collectionsDeleteDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { + databasesDeleteDocument(databaseId: $databaseId, collectionId: $collectionId, documentId: $documentId) { status } }'; @@ -2844,7 +2844,7 @@ trait Base status } } - collectionsCreateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "name", size: 255, required: true) { + databasesCreateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "name", size: 255, required: true) { key type status @@ -2853,7 +2853,7 @@ trait Base default array } - collectionsCreateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "age", min: 0, max: 150, required: true) { + databasesCreateIntegerAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "age", min: 0, max: 150, required: true) { key type status @@ -2863,7 +2863,7 @@ trait Base default array } - collectionsCreateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "alive", required: false, default: true) { + databasesCreateBooleanAttribute(databaseId: $databaseId, collectionId: $collectionId, key: "alive", required: false, default: true) { key type status diff --git a/tests/e2e/Services/GraphQL/Collections/AbuseTest.php b/tests/e2e/Services/GraphQL/Legacy/AbuseTest.php similarity index 99% rename from tests/e2e/Services/GraphQL/Collections/AbuseTest.php rename to tests/e2e/Services/GraphQL/Legacy/AbuseTest.php index a58a57ec5a..d579ddb128 100644 --- a/tests/e2e/Services/GraphQL/Collections/AbuseTest.php +++ b/tests/e2e/Services/GraphQL/Legacy/AbuseTest.php @@ -1,6 +1,6 @@ [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], - 'documentId' => $document['body']['data']['collectionsCreateDocument']['_id'], + 'documentId' => $document['body']['data']['databasesCreateDocument']['_id'], ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', [ @@ -188,7 +188,7 @@ class AuthTest extends Scope 'cookie' => 'a_session_' . $projectId . '=' . $this->token1, ], $gqlPayload); - $this->assertIsArray($document['body']['data']['collectionsGetDocument']); + $this->assertIsArray($document['body']['data']['databasesGetDocument']); $this->assertArrayNotHasKey('errors', $document['body']); // Try to read as account 2 @@ -238,7 +238,7 @@ class AuthTest extends Scope 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], 'collectionId' => $this->collection['body']['data']['databasesCreateCollection']['_id'], - 'documentId' => $document['body']['data']['collectionsCreateDocument']['_id'], + 'documentId' => $document['body']['data']['databasesCreateDocument']['_id'], ] ]; $document = $this->client->call(Client::METHOD_POST, '/graphql', [ diff --git a/tests/e2e/Services/GraphQL/Collections/DatabaseClientTest.php b/tests/e2e/Services/GraphQL/Legacy/DatabaseClientTest.php similarity index 94% rename from tests/e2e/Services/GraphQL/Collections/DatabaseClientTest.php rename to tests/e2e/Services/GraphQL/Legacy/DatabaseClientTest.php index 349d580d64..c2c63e41c0 100644 --- a/tests/e2e/Services/GraphQL/Collections/DatabaseClientTest.php +++ b/tests/e2e/Services/GraphQL/Legacy/DatabaseClientTest.php @@ -1,6 +1,6 @@ assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsCreateStringAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateStringAttribute']); return $data; } @@ -141,7 +141,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsCreateIntegerAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateIntegerAttribute']); return $data; } @@ -182,7 +182,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['collectionsCreateDocument']; + $document = $document['body']['data']['databasesCreateDocument']; $this->assertIsArray($document); return [ @@ -215,7 +215,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $documents['body']); $this->assertIsArray($documents['body']['data']); - $this->assertIsArray($documents['body']['data']['collectionsListDocuments']); + $this->assertIsArray($documents['body']['data']['databasesListDocuments']); } /** @@ -242,7 +242,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $this->assertIsArray($document['body']['data']['collectionsGetDocument']); + $this->assertIsArray($document['body']['data']['databasesGetDocument']); } /** @@ -272,7 +272,7 @@ class DatabaseClientTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['collectionsUpdateDocument']; + $document = $document['body']['data']['databasesUpdateDocument']; $this->assertIsArray($document); $this->assertStringContainsString('New Document Name', $document['data']); @@ -377,7 +377,7 @@ class DatabaseClientTest extends Scope ]; $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); $this->assertArrayNotHasKey('errors', $res['body']); - $this->assertCount(10, $res['body']['data']['collectionsCreateDocuments']['documents']); + $this->assertCount(10, $res['body']['data']['databasesCreateDocuments']['documents']); return [ 'databaseId' => $databaseId, @@ -418,7 +418,7 @@ class DatabaseClientTest extends Scope ]; $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); $this->assertArrayNotHasKey('errors', $res['body']); - $this->assertCount(10, $res['body']['data']['collectionsUpdateDocuments']['documents']); + $this->assertCount(10, $res['body']['data']['databasesUpdateDocuments']['documents']); return $data; } @@ -449,7 +449,7 @@ class DatabaseClientTest extends Scope ]; $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); $this->assertArrayNotHasKey('errors', $res['body']); - $this->assertCount(2, $res['body']['data']['collectionsUpsertDocuments']['documents']); + $this->assertCount(2, $res['body']['data']['databasesUpsertDocuments']['documents']); return $data; } @@ -475,7 +475,7 @@ class DatabaseClientTest extends Scope ]; $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); $this->assertArrayNotHasKey('errors', $res['body']); - $this->assertCount(11, $res['body']['data']['collectionsDeleteDocuments']['documents']); + $this->assertCount(11, $res['body']['data']['databasesDeleteDocuments']['documents']); return $data; } diff --git a/tests/e2e/Services/GraphQL/Collections/DatabaseServerTest.php b/tests/e2e/Services/GraphQL/Legacy/DatabaseServerTest.php similarity index 91% rename from tests/e2e/Services/GraphQL/Collections/DatabaseServerTest.php rename to tests/e2e/Services/GraphQL/Legacy/DatabaseServerTest.php index 3e5b457308..3ecc96eaa0 100644 --- a/tests/e2e/Services/GraphQL/Collections/DatabaseServerTest.php +++ b/tests/e2e/Services/GraphQL/Legacy/DatabaseServerTest.php @@ -1,6 +1,6 @@ assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsCreateStringAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateStringAttribute']); return $data; } @@ -170,9 +170,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsUpdateStringAttribute']); - $this->assertFalse($attribute['body']['data']['collectionsUpdateStringAttribute']['required']); - $this->assertEquals('Default Value', $attribute['body']['data']['collectionsUpdateStringAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateStringAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateStringAttribute']['required']); + $this->assertEquals('Default Value', $attribute['body']['data']['databasesUpdateStringAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -205,7 +205,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsCreateIntegerAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateIntegerAttribute']); return $data; } @@ -240,11 +240,11 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsUpdateIntegerAttribute']); - $this->assertFalse($attribute['body']['data']['collectionsUpdateIntegerAttribute']['required']); - $this->assertEquals(12, $attribute['body']['data']['collectionsUpdateIntegerAttribute']['min']); - $this->assertEquals(160, $attribute['body']['data']['collectionsUpdateIntegerAttribute']['max']); - $this->assertEquals(50, $attribute['body']['data']['collectionsUpdateIntegerAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateIntegerAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateIntegerAttribute']['required']); + $this->assertEquals(12, $attribute['body']['data']['databasesUpdateIntegerAttribute']['min']); + $this->assertEquals(160, $attribute['body']['data']['databasesUpdateIntegerAttribute']['max']); + $this->assertEquals(50, $attribute['body']['data']['databasesUpdateIntegerAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -275,7 +275,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsCreateBooleanAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateBooleanAttribute']); return $data; } @@ -308,9 +308,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsUpdateBooleanAttribute']); - $this->assertFalse($attribute['body']['data']['collectionsUpdateBooleanAttribute']['required']); - $this->assertTrue($attribute['body']['data']['collectionsUpdateBooleanAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateBooleanAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateBooleanAttribute']['required']); + $this->assertTrue($attribute['body']['data']['databasesUpdateBooleanAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -344,7 +344,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsCreateFloatAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateFloatAttribute']); return $data; } @@ -379,11 +379,11 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsUpdateFloatAttribute']); - $this->assertFalse($attribute['body']['data']['collectionsUpdateFloatAttribute']['required']); - $this->assertEquals(100.0, $attribute['body']['data']['collectionsUpdateFloatAttribute']['min']); - $this->assertEquals(1000000.0, $attribute['body']['data']['collectionsUpdateFloatAttribute']['max']); - $this->assertEquals(2500.0, $attribute['body']['data']['collectionsUpdateFloatAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateFloatAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateFloatAttribute']['required']); + $this->assertEquals(100.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['min']); + $this->assertEquals(1000000.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['max']); + $this->assertEquals(2500.0, $attribute['body']['data']['databasesUpdateFloatAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -414,7 +414,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsCreateEmailAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateEmailAttribute']); return $data; } @@ -447,9 +447,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsUpdateEmailAttribute']); - $this->assertFalse($attribute['body']['data']['collectionsUpdateEmailAttribute']['required']); - $this->assertEquals('torsten@appwrite.io', $attribute['body']['data']['collectionsUpdateEmailAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateEmailAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateEmailAttribute']['required']); + $this->assertEquals('torsten@appwrite.io', $attribute['body']['data']['databasesUpdateEmailAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -485,7 +485,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsCreateEnumAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateEnumAttribute']); return $data; } @@ -524,11 +524,11 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsUpdateEnumAttribute']); - $this->assertFalse($attribute['body']['data']['collectionsUpdateEnumAttribute']['required']); - $this->assertEquals('tech', $attribute['body']['data']['collectionsUpdateEnumAttribute']['default']); - $this->assertContains('tech', $attribute['body']['data']['collectionsUpdateEnumAttribute']['elements']); - $this->assertNotContains('guest', $attribute['body']['data']['collectionsUpdateEnumAttribute']['elements']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateEnumAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateEnumAttribute']['required']); + $this->assertEquals('tech', $attribute['body']['data']['databasesUpdateEnumAttribute']['default']); + $this->assertContains('tech', $attribute['body']['data']['databasesUpdateEnumAttribute']['elements']); + $this->assertNotContains('guest', $attribute['body']['data']['databasesUpdateEnumAttribute']['elements']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -559,7 +559,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsCreateDatetimeAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateDatetimeAttribute']); return $data; } @@ -592,9 +592,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsUpdateDatetimeAttribute']); - $this->assertFalse($attribute['body']['data']['collectionsUpdateDatetimeAttribute']['required']); - $this->assertEquals('2000-01-01T00:00:00Z', $attribute['body']['data']['collectionsUpdateDatetimeAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateDatetimeAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateDatetimeAttribute']['required']); + $this->assertEquals('2000-01-01T00:00:00Z', $attribute['body']['data']['databasesUpdateDatetimeAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -627,7 +627,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsCreateRelationshipAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateRelationshipAttribute']); return $data; } @@ -658,7 +658,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsUpdateRelationshipAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateRelationshipAttribute']); return $data; } @@ -689,7 +689,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsCreateIpAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateIpAttribute']); return $data; } @@ -722,9 +722,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsUpdateIpAttribute']); - $this->assertFalse($attribute['body']['data']['collectionsUpdateIpAttribute']['required']); - $this->assertEquals('127.0.0.1', $attribute['body']['data']['collectionsUpdateIpAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateIpAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateIpAttribute']['required']); + $this->assertEquals('127.0.0.1', $attribute['body']['data']['databasesUpdateIpAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); return $data; @@ -756,7 +756,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsCreateUrlAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesCreateUrlAttribute']); return $data; } @@ -789,9 +789,9 @@ class DatabaseServerTest extends Scope ], $this->getHeaders()), $gqlPayload); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsUpdateUrlAttribute']); - $this->assertFalse($attribute['body']['data']['collectionsUpdateUrlAttribute']['required']); - $this->assertEquals('https://cloud.appwrite.io', $attribute['body']['data']['collectionsUpdateUrlAttribute']['default']); + $this->assertIsArray($attribute['body']['data']['databasesUpdateUrlAttribute']); + $this->assertFalse($attribute['body']['data']['databasesUpdateUrlAttribute']['required']); + $this->assertEquals('https://cloud.appwrite.io', $attribute['body']['data']['databasesUpdateUrlAttribute']['default']); $this->assertEquals(200, $attribute['headers']['status-code']); } @@ -825,12 +825,12 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $index['body']); $this->assertIsArray($index['body']['data']); - $this->assertIsArray($index['body']['data']['collectionsCreateIndex']); + $this->assertIsArray($index['body']['data']['databasesCreateIndex']); return [ 'database' => $data['database'], 'collection' => $data['collection'], - 'index' => $index['body']['data']['collectionsCreateIndex'], + 'index' => $index['body']['data']['databasesCreateIndex'], ]; } @@ -876,7 +876,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['collectionsCreateDocument']; + $document = $document['body']['data']['databasesCreateDocument']; $this->assertIsArray($document); return [ @@ -1044,7 +1044,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attributes['body']); $this->assertIsArray($attributes['body']['data']); - $this->assertIsArray($attributes['body']['data']['collectionsListAttributes']); + $this->assertIsArray($attributes['body']['data']['databasesListAttributes']); } /** @@ -1071,7 +1071,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $attribute['body']); $this->assertIsArray($attribute['body']['data']); - $this->assertIsArray($attribute['body']['data']['collectionsGetAttribute']); + $this->assertIsArray($attribute['body']['data']['databasesGetAttribute']); } /** @@ -1097,7 +1097,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $indices['body']); $this->assertIsArray($indices['body']['data']); - $this->assertIsArray($indices['body']['data']['collectionsListIndexes']); + $this->assertIsArray($indices['body']['data']['databasesListIndexes']); } /** @@ -1124,7 +1124,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $index['body']); $this->assertIsArray($index['body']['data']); - $this->assertIsArray($index['body']['data']['collectionsGetIndex']); + $this->assertIsArray($index['body']['data']['databasesGetIndex']); } /** @@ -1150,7 +1150,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $documents['body']); $this->assertIsArray($documents['body']['data']); - $this->assertIsArray($documents['body']['data']['collectionsListDocuments']); + $this->assertIsArray($documents['body']['data']['databasesListDocuments']); } /** @@ -1177,7 +1177,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $this->assertIsArray($document['body']['data']['collectionsGetDocument']); + $this->assertIsArray($document['body']['data']['databasesGetDocument']); } // /** @@ -1308,7 +1308,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $document['body']); $this->assertIsArray($document['body']['data']); - $document = $document['body']['data']['collectionsUpdateDocument']; + $document = $document['body']['data']['databasesUpdateDocument']; $this->assertIsArray($document); $this->assertStringContainsString('New Document Name', $document['data']); } @@ -1538,7 +1538,7 @@ class DatabaseServerTest extends Scope ]; $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); $this->assertArrayNotHasKey('errors', $res['body']); - $this->assertCount(10, $res['body']['data']['collectionsCreateDocuments']['documents']); + $this->assertCount(10, $res['body']['data']['databasesCreateDocuments']['documents']); return [ 'databaseId' => $databaseId, @@ -1578,7 +1578,7 @@ class DatabaseServerTest extends Scope ]; $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); $this->assertArrayNotHasKey('errors', $res['body']); - $this->assertCount(10, $res['body']['data']['collectionsUpdateDocuments']['documents']); + $this->assertCount(10, $res['body']['data']['databasesUpdateDocuments']['documents']); return $data; } @@ -1608,7 +1608,7 @@ class DatabaseServerTest extends Scope ]; $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); $this->assertArrayNotHasKey('errors', $res['body']); - $this->assertCount(2, $res['body']['data']['collectionsUpsertDocuments']['documents']); + $this->assertCount(2, $res['body']['data']['databasesUpsertDocuments']['documents']); return $data; } @@ -1633,7 +1633,7 @@ class DatabaseServerTest extends Scope ]; $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); $this->assertArrayNotHasKey('errors', $res['body']); - $this->assertCount(11, $res['body']['data']['collectionsDeleteDocuments']['documents']); + $this->assertCount(11, $res['body']['data']['databasesDeleteDocuments']['documents']); return $data; } From 531f50a2c74b279a98ab85b9aaf61f53f0f81e1d Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 19 Jun 2025 17:59:29 +0530 Subject: [PATCH 211/343] fix: sdk namespacing and graphql tests. --- .../Http/Databases/Collections/Action.php | 8 ++++++++ .../Http/Databases/Tables/Columns/XList.php | 2 +- .../Http/Databases/Tables/Create.php | 6 +++--- .../Http/Databases/Tables/Delete.php | 6 +++--- .../Databases/Http/Databases/Tables/Get.php | 6 +++--- .../Http/Databases/Tables/Update.php | 6 +++--- .../Http/Databases/Tables/Usage/Get.php | 2 +- .../Databases/Http/Databases/Tables/XList.php | 8 ++++---- .../Database/Validator/Queries/Attributes.php | 2 +- .../Validator/Queries/Collections.php | 2 +- .../Database/Validator/Queries/Columns.php | 4 ++-- .../Database/Validator/Queries/Tables.php | 6 +++--- tests/e2e/Services/GraphQL/Base.php | 20 +++++++++---------- .../e2e/Services/GraphQL/Tables/AbuseTest.php | 4 ++-- .../e2e/Services/GraphQL/Tables/AuthTest.php | 10 +++++----- .../GraphQL/Tables/DatabaseClientTest.php | 4 ++-- .../GraphQL/Tables/DatabaseServerTest.php | 12 +++++------ 17 files changed, 58 insertions(+), 50 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php index 0e3202d979..9329300ffa 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php @@ -59,6 +59,14 @@ abstract class Action extends UtopiaAction return $this->isCollectionsAPI() ? 'collections' : 'tables'; } + /** + * Get the SDK namespace for the current action. + */ + final protected function getSdkNamespace(): string + { + return $this->isCollectionsAPI() ? 'databases' : 'tables'; + } + /** * Get the exception to throw when the resource already exists. */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php index 29a108f180..8190f2ec71 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php @@ -47,7 +47,7 @@ class XList extends AttributesXList )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID.') - ->param('queries', [], new Columns(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Columns::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new Columns(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Columns::ALLOWED_COLUMNS), true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php index 92b29ffdc6..0bfdef5249 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php @@ -19,7 +19,7 @@ class Create extends CollectionCreate { public static function getName(): string { - return 'createTable'; + return 'create'; } protected function getResponseModel(): string @@ -40,8 +40,8 @@ class Create extends CollectionCreate ->label('audits.event', 'table.create') ->label('audits.resource', 'database/{request.databaseId}/table/{response.$id}') ->label('sdk', new Method( - namespace: 'databases', - group: $this->getSdkGroup(), + namespace: $this->getSdkNamespace(), + group: null, name: self::getName(), description: '/docs/references/databases/create-collection.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php index 0a20a20f54..caa7197acb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php @@ -15,7 +15,7 @@ class Delete extends CollectionDelete { public static function getName(): string { - return 'deleteTable'; + return 'delete'; } protected function getResponseModel(): string @@ -36,8 +36,8 @@ class Delete extends CollectionDelete ->label('audits.event', 'table.delete') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', - group: $this->getSdkGroup(), + namespace: $this->getSdkNamespace(), + group: null, name: self::getName(), description: '/docs/references/databases/delete-collection.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php index 7f565231f9..40672ba51f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php @@ -15,7 +15,7 @@ class Get extends CollectionGet { public static function getName(): string { - return 'getTable'; + return 'get'; } protected function getResponseModel(): string @@ -33,8 +33,8 @@ class Get extends CollectionGet ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', - group: $this->getSdkGroup(), + namespace: $this->getSdkNamespace(), + group: null, name: self::getName(), description: '/docs/references/databases/get-collection.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php index 62a1b3bdee..f800e7b1de 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php @@ -18,7 +18,7 @@ class Update extends CollectionUpdate { public static function getName(): string { - return 'updateTable'; + return 'update'; } protected function getResponseModel(): string @@ -39,8 +39,8 @@ class Update extends CollectionUpdate ->label('audits.event', 'table.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: 'databases', - group: $this->getSdkGroup(), + namespace: $this->getSdkNamespace(), + group: null, name: self::getName(), description: '/docs/references/databases/update-collection.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php index c82eaae7c5..ca990eeab6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php @@ -34,7 +34,7 @@ class Get extends CollectionUsageGet ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: null, name: self::getName(), description: '/docs/references/databases/get-collection-usage.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php index 391b91a3dd..34000d97b1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php @@ -17,7 +17,7 @@ class XList extends CollectionXList { public static function getName(): string { - return 'listTables'; + return 'list'; } protected function getResponseModel(): string @@ -35,8 +35,8 @@ class XList extends CollectionXList ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', - group: $this->getSdkGroup(), + namespace: $this->getSdkNamespace(), + group: null, name: self::getName(), description: '/docs/references/databases/list-collections.md', auth: [AuthType::KEY], @@ -49,7 +49,7 @@ class XList extends CollectionXList contentType: ContentType::JSON )) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('queries', [], new Tables(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Tables::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new Tables(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Tables::ALLOWED_COLUMNS), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php index 4a35c82b73..953948c045 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Database\Validator\Queries; class Attributes extends Base { - public const ALLOWED_ATTRIBUTES = [ + public const array ALLOWED_ATTRIBUTES = [ 'key', 'type', 'size', diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php b/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php index 6e8fcb8339..cdaaa104dc 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Database\Validator\Queries; class Collections extends Base { - public const ALLOWED_ATTRIBUTES = [ + public const array ALLOWED_ATTRIBUTES = [ 'name', 'enabled', 'documentSecurity' diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Columns.php b/src/Appwrite/Utopia/Database/Validator/Queries/Columns.php index 3c2742bfdd..c990dfc18a 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Columns.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Columns.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Database\Validator\Queries; class Columns extends Base { - public const ALLOWED_ATTRIBUTES = [ + public const array ALLOWED_COLUMNS = [ 'key', 'type', 'size', @@ -20,6 +20,6 @@ class Columns extends Base */ public function __construct() { - parent::__construct('attributes', self::ALLOWED_ATTRIBUTES); + parent::__construct('attributes', self::ALLOWED_COLUMNS); } } diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Tables.php b/src/Appwrite/Utopia/Database/Validator/Queries/Tables.php index 5a1fc4ec6d..f3aadb69ac 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Tables.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Tables.php @@ -4,10 +4,10 @@ namespace Appwrite\Utopia\Database\Validator\Queries; class Tables extends Base { - public const ALLOWED_ATTRIBUTES = [ + public const array ALLOWED_COLUMNS = [ 'name', 'enabled', - 'documentSecurity' + 'rowSecurity' ]; /** @@ -16,6 +16,6 @@ class Tables extends Base */ public function __construct() { - parent::__construct('collections', self::ALLOWED_ATTRIBUTES); + parent::__construct('collections', self::ALLOWED_COLUMNS); } } diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 3da4dc11a3..bd3c792248 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -580,8 +580,8 @@ trait Base } }'; case self::$GET_TABLE: - return 'query getTable($databaseId: String!, $tableId: String!) { - databasesGetTable(databaseId: $databaseId, tableId: $tableId) { + return 'query tablesGet($databaseId: String!, $tableId: String!) { + tablesGet(databaseId: $databaseId, tableId: $tableId) { _id _permissions rowSecurity @@ -589,8 +589,8 @@ trait Base } }'; case self::$GET_TABLES: - return 'query listTables($databaseId: String!) { - databasesListTables(databaseId: $databaseId) { + return 'query tablesList($databaseId: String!) { + tablesList(databaseId: $databaseId) { total tables { _id @@ -601,8 +601,8 @@ trait Base } }'; case self::$CREATE_TABLE: - return 'mutation createTable($databaseId: String!, $tableId: String!, $name: String!, $rowSecurity: Boolean!, $permissions: [String!]!) { - databasesCreateTable(databaseId: $databaseId, tableId: $tableId, name: $name, rowSecurity: $rowSecurity, permissions: $permissions) { + return 'mutation tablesCreate($databaseId: String!, $tableId: String!, $name: String!, $rowSecurity: Boolean!, $permissions: [String!]!) { + tablesCreate(databaseId: $databaseId, tableId: $tableId, name: $name, rowSecurity: $rowSecurity, permissions: $permissions) { _id _permissions rowSecurity @@ -610,8 +610,8 @@ trait Base } }'; case self::$UPDATE_TABLE: - return 'mutation updateTable($databaseId: String!, $tableId: String!, $name: String!, $rowSecurity: Boolean!, $permissions: [String!], $enabled: Boolean) { - databasesUpdateTable(databaseId: $databaseId, tableId: $tableId, name: $name, rowSecurity: $rowSecurity, permissions: $permissions, enabled: $enabled) { + return 'mutation tablesUpdate($databaseId: String!, $tableId: String!, $name: String!, $rowSecurity: Boolean!, $permissions: [String!], $enabled: Boolean) { + tablesUpdate(databaseId: $databaseId, tableId: $tableId, name: $name, rowSecurity: $rowSecurity, permissions: $permissions, enabled: $enabled) { _id _permissions rowSecurity @@ -619,8 +619,8 @@ trait Base } }'; case self::$DELETE_TABLE: - return 'mutation deleteTable($databaseId: String!, $tableId: String!) { - databasesDeleteTable(databaseId: $databaseId, tableId: $tableId) { + return 'mutation tablesDelete($databaseId: String!, $tableId: String!) { + tablesDelete(databaseId: $databaseId, tableId: $tableId) { status } }'; diff --git a/tests/e2e/Services/GraphQL/Tables/AbuseTest.php b/tests/e2e/Services/GraphQL/Tables/AbuseTest.php index abb5019d55..8b759aa1ce 100644 --- a/tests/e2e/Services/GraphQL/Tables/AbuseTest.php +++ b/tests/e2e/Services/GraphQL/Tables/AbuseTest.php @@ -132,7 +132,7 @@ class AbuseTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'], ], $gqlPayload); - $databaseId = $response['body']['data']['databasesCreate']['_id']; + $databaseId = $response['body']['data']['tablesCreate']['_id']; $query = $this->getQuery(self::$CREATE_TABLE); $gqlPayload = [ @@ -155,7 +155,7 @@ class AbuseTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'], ], $gqlPayload); - $tableId = $response['body']['data']['databasesCreateTable']['_id']; + $tableId = $response['body']['data']['tablesCreate']['_id']; $query = $this->getQuery(self::$CREATE_STRING_COLUMN); $gqlPayload = [ diff --git a/tests/e2e/Services/GraphQL/Tables/AuthTest.php b/tests/e2e/Services/GraphQL/Tables/AuthTest.php index 681607d599..21d581d207 100644 --- a/tests/e2e/Services/GraphQL/Tables/AuthTest.php +++ b/tests/e2e/Services/GraphQL/Tables/AuthTest.php @@ -128,7 +128,7 @@ class AuthTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'tableId' => $this->table['body']['data']['tablesCreate']['_id'], 'key' => 'name', 'size' => 256, 'required' => true, @@ -154,7 +154,7 @@ class AuthTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'tableId' => $this->table['body']['data']['tablesCreate']['_id'], 'rowId' => ID::unique(), 'data' => [ 'name' => 'John Doe', @@ -178,7 +178,7 @@ class AuthTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'tableId' => $this->table['body']['data']['tablesCreate']['_id'], 'rowId' => $row['body']['data']['tablesCreateRow']['_id'], ] ]; @@ -213,7 +213,7 @@ class AuthTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'tableId' => $this->table['body']['data']['tablesCreate']['_id'], 'rowId' => ID::unique(), 'data' => [ 'name' => 'John Doe', @@ -237,7 +237,7 @@ class AuthTest extends Scope 'query' => $query, 'variables' => [ 'databaseId' => $this->database['body']['data']['databasesCreate']['_id'], - 'tableId' => $this->table['body']['data']['databasesCreateTable']['_id'], + 'tableId' => $this->table['body']['data']['tablesCreate']['_id'], 'rowId' => $row['body']['data']['tablesCreateRow']['_id'], ] ]; diff --git a/tests/e2e/Services/GraphQL/Tables/DatabaseClientTest.php b/tests/e2e/Services/GraphQL/Tables/DatabaseClientTest.php index c5cba6c47f..5ff8e65922 100644 --- a/tests/e2e/Services/GraphQL/Tables/DatabaseClientTest.php +++ b/tests/e2e/Services/GraphQL/Tables/DatabaseClientTest.php @@ -75,7 +75,7 @@ class DatabaseClientTest extends Scope $this->assertIsArray($table['body']['data']); $this->assertArrayNotHasKey('errors', $table['body']); - $table = $table['body']['data']['databasesCreateTable']; + $table = $table['body']['data']['tablesCreate']; $this->assertEquals('Actors', $table['name']); return [ @@ -349,7 +349,7 @@ class DatabaseClientTest extends Scope $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); $this->assertArrayNotHasKey('errors', $res['body']); - $tableId = $res['body']['data']['databasesCreateTable']['_id']; + $tableId = $res['body']['data']['tablesCreate']['_id']; // Step 3: Create column $query = $this->getQuery(self::$CREATE_STRING_COLUMN); diff --git a/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php b/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php index 61cb57911a..e4e9b34f35 100644 --- a/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php +++ b/tests/e2e/Services/GraphQL/Tables/DatabaseServerTest.php @@ -75,7 +75,7 @@ class DatabaseServerTest extends Scope $this->assertIsArray($table['body']['data']); $this->assertArrayNotHasKey('errors', $table['body']); - $table = $table['body']['data']['databasesCreateTable']; + $table = $table['body']['data']['tablesCreate']; $this->assertEquals('Actors', $table['name']); $gqlPayload = [ @@ -101,7 +101,7 @@ class DatabaseServerTest extends Scope $this->assertIsArray($table2['body']['data']); $this->assertArrayNotHasKey('errors', $table2['body']); - $table2 = $table2['body']['data']['databasesCreateTable']; + $table2 = $table2['body']['data']['tablesCreate']; $this->assertEquals('Movies', $table2['name']); return [ @@ -992,7 +992,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $tables['body']); $this->assertIsArray($tables['body']['data']); - $this->assertIsArray($tables['body']['data']['databasesListTables']); + $this->assertIsArray($tables['body']['data']['tablesList']); } /** @@ -1018,7 +1018,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $table['body']); $this->assertIsArray($table['body']['data']); - $this->assertIsArray($table['body']['data']['databasesGetTable']); + $this->assertIsArray($table['body']['data']['tablesGet']); } /** @@ -1279,7 +1279,7 @@ class DatabaseServerTest extends Scope $this->assertArrayNotHasKey('errors', $table['body']); $this->assertIsArray($table['body']['data']); - $this->assertIsArray($table['body']['data']['databasesUpdateTable']); + $this->assertIsArray($table['body']['data']['tablesUpdate']); } /** @@ -1510,7 +1510,7 @@ class DatabaseServerTest extends Scope $res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload); $this->assertArrayNotHasKey('errors', $res['body']); - $tableId = $res['body']['data']['databasesCreateTable']['_id']; + $tableId = $res['body']['data']['tablesCreate']['_id']; // Step 3: Create column $query = $this->getQuery(self::$CREATE_STRING_COLUMN); From c1f46fc20b3f5d7d9957e343c383aeee98bd0c7f Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 19 Jun 2025 18:00:58 +0530 Subject: [PATCH 212/343] chore: update cli --- app/config/platforms.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/platforms.php b/app/config/platforms.php index ca536c95ff..63ad307ea2 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -217,7 +217,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '8.0.1', + 'version' => '8.0.2', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, From 4521302cb87edb7419a1585b2b0a389bb8e8dc66 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 19 Jun 2025 18:36:32 +0530 Subject: [PATCH 213/343] fix: graphql test for complex queries. --- tests/e2e/Services/GraphQL/Base.php | 2 +- tests/e2e/Services/GraphQL/Tables/AbuseTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index bd3c792248..554f84e616 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -3070,7 +3070,7 @@ trait Base _id name } - databasesCreateTable(databaseId: $databaseId, tableId: $tableId, name: $tableName, rowSecurity: $rowSecurity, permissions: $tablePermissions) { + tablesCreate(databaseId: $databaseId, tableId: $tableId, name: $tableName, rowSecurity: $rowSecurity, permissions: $tablePermissions) { _id _createdAt _updatedAt diff --git a/tests/e2e/Services/GraphQL/Tables/AbuseTest.php b/tests/e2e/Services/GraphQL/Tables/AbuseTest.php index 8b759aa1ce..88c216dd5a 100644 --- a/tests/e2e/Services/GraphQL/Tables/AbuseTest.php +++ b/tests/e2e/Services/GraphQL/Tables/AbuseTest.php @@ -132,7 +132,7 @@ class AbuseTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'], ], $gqlPayload); - $databaseId = $response['body']['data']['tablesCreate']['_id']; + $databaseId = $response['body']['data']['databasesCreate']['_id']; $query = $this->getQuery(self::$CREATE_TABLE); $gqlPayload = [ From 68fc0f898f5d238c67dab5322d482aafd7678754 Mon Sep 17 00:00:00 2001 From: shimon Date: Thu, 19 Jun 2025 17:15:43 +0300 Subject: [PATCH 214/343] set log projectId on the router method --- app/controllers/general.php | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index f3470bc206..ab2aa73e4d 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -56,7 +56,7 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) +function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { $host = $request->getHostname() ?? ''; if (!empty($previewHostname)) { @@ -118,11 +118,11 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $project->setAttribute('accessedAt', DateTime::now()); Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } - /** - * Override project resource to update hooks, since x-appwrite-project is not available when executing custom domain function - */ - App::setResource('project', fn () => $project); + /** + * Set projectId to update the Error hook logger, since x-appwrite-project is not available when executing custom domain function + */ + $log->addTag('projectId', $project->getId()); } if (array_key_exists('proxy', $project->getAttribute('services', []))) { @@ -792,6 +792,7 @@ App::init() ->inject('swooleRequest') ->inject('request') ->inject('response') + ->inject('log') ->inject('console') ->inject('project') ->inject('dbForPlatform') @@ -809,7 +810,7 @@ App::init() ->inject('previewHostname') ->inject('devKey') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey) { /* * Appwrite Router */ @@ -817,7 +818,7 @@ App::init() $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1099,7 +1100,7 @@ App::options() $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1272,7 +1273,12 @@ App::error() $log->addTag('url', $request->getURI()); $log->addTag('verboseType', get_class($error)); $log->addTag('code', $error->getCode()); - $log->addTag('projectId', $project->getId()); + + $tags = $log->getTags(); + if (isset($tags['projectId'])){ + $log->addTag('projectId', $project->getId()); + } + $log->addTag('hostname', $request->getHostname()); $log->addTag('locale', (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', ''))); @@ -1408,7 +1414,7 @@ App::get('/robots.txt') $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1440,7 +1446,7 @@ App::get('/humans.txt') $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); } else { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } From d8c88fb420a7e0b22fde01680cec333613776eb0 Mon Sep 17 00:00:00 2001 From: shimon Date: Thu, 19 Jun 2025 19:44:33 +0300 Subject: [PATCH 215/343] composer --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index ab2aa73e4d..f06c46e8d9 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1275,7 +1275,7 @@ App::error() $log->addTag('code', $error->getCode()); $tags = $log->getTags(); - if (isset($tags['projectId'])){ + if (isset($tags['projectId'])) { $log->addTag('projectId', $project->getId()); } From 1319bf7ec1532026b20c1753c2767499668922db Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Sat, 21 Jun 2025 01:41:41 +0400 Subject: [PATCH 216/343] Fix connect to existing repo flow --- docker-compose.yml | 2 +- src/Appwrite/Platform/Modules/Functions/Workers/Builds.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 0b653af8c2..51d54a7d78 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -213,7 +213,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:6.0.41 + image: appwrite/console:6.1.2 restart: unless-stopped networks: - appwrite diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 8ff1690da9..67bbe2dbef 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -445,7 +445,7 @@ class Builds extends Action Console::execute('rsync -av --exclude \'.git\' ' . \escapeshellarg($tmpTemplateDirectory . '/' . $templateRootDirectory . '/') . ' ' . \escapeshellarg($tmpDirectory . '/' . $rootDirectory), '', $stdout, $stderr); // Commit and push - $exit = Console::execute('git config --global user.email "team@appwrite.io" && git config --global user.name "Appwrite" && cd ' . \escapeshellarg($tmpDirectory) . ' && git add . && git commit -m "Create ' . \escapeshellarg($resource->getAttribute('name', '')) . ' function" && git push origin ' . \escapeshellarg($branchName), '', $stdout, $stderr); + $exit = Console::execute('git config --global user.email "team@appwrite.io" && git config --global user.name "Appwrite" && cd ' . \escapeshellarg($tmpDirectory) . ' && git checkout -b ' . \escapeshellarg($branchName) . ' && git add . && git commit -m "Create ' . \escapeshellarg($resource->getAttribute('name', '')) . ' function" && git push origin ' . \escapeshellarg($branchName), '', $stdout, $stderr); if ($exit !== 0) { throw new \Exception('Unable to push code repository: ' . $stderr); From 6d55299836464b3ff55798ec1d9ae633fda898e7 Mon Sep 17 00:00:00 2001 From: Steven Nguyen <1477010+stnguyen90@users.noreply.github.com> Date: Fri, 20 Jun 2025 18:40:04 -0700 Subject: [PATCH 217/343] Revert "worker: Graceful shutdown on SIGTERM" --- app/worker.php | 13 ++----------- bin/doctor | 2 +- bin/install | 2 +- bin/maintenance | 2 +- bin/migrate | 2 +- bin/queue-count-failed | 2 +- bin/queue-count-processing | 2 +- bin/queue-count-success | 2 +- bin/queue-retry | 2 +- bin/realtime | 2 +- bin/schedule-executions | 2 +- bin/schedule-functions | 2 +- bin/schedule-messages | 2 +- bin/screenshot | 2 +- bin/sdks | 2 +- bin/specs | 2 +- bin/ssl | 2 +- bin/stats-resources | 2 +- bin/test | 2 +- bin/upgrade | 2 +- bin/vars | 2 +- bin/worker-audits | 2 +- bin/worker-builds | 2 +- bin/worker-certificates | 2 +- bin/worker-databases | 2 +- bin/worker-deletes | 2 +- bin/worker-functions | 2 +- bin/worker-mails | 2 +- bin/worker-messaging | 2 +- bin/worker-migrations | 2 +- bin/worker-stats-resources | 2 +- bin/worker-stats-usage | 2 +- bin/worker-webhooks | 2 +- 33 files changed, 34 insertions(+), 43 deletions(-) diff --git a/app/worker.php b/app/worker.php index e57aae91d2..845914c923 100644 --- a/app/worker.php +++ b/app/worker.php @@ -18,9 +18,7 @@ use Appwrite\Event\StatsUsage; use Appwrite\Event\Webhook; use Appwrite\Platform\Appwrite; use Executor\Executor; -use Swoole\Process; use Swoole\Runtime; -use Swoole\Timer; use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\Cache\Adapter\Sharding; @@ -484,15 +482,8 @@ $worker }); $worker->workerStart() - ->action(function () use ($worker, $workerName) { - Console::info("Worker $workerName started"); - - Process::signal(SIGTERM, function () use ($worker, $workerName) { - Console::info("Stopping worker $workerName."); - - $worker->stop(); - Timer::clearAll(); - }); + ->action(function () use ($workerName) { + Console::info("Worker $workerName started"); }); $worker->start(); diff --git a/bin/doctor b/bin/doctor index 92b3cf6bf8..b2a4547156 100755 --- a/bin/doctor +++ b/bin/doctor @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php doctor $@ +php /usr/src/code/app/cli.php doctor $@ \ No newline at end of file diff --git a/bin/install b/bin/install index 126d5373bf..e669e91e6b 100755 --- a/bin/install +++ b/bin/install @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php install $@ +php /usr/src/code/app/cli.php install $@ \ No newline at end of file diff --git a/bin/maintenance b/bin/maintenance index 70273feb61..099551cb32 100644 --- a/bin/maintenance +++ b/bin/maintenance @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php maintenance $@ +php /usr/src/code/app/cli.php maintenance $@ \ No newline at end of file diff --git a/bin/migrate b/bin/migrate index 32bf7ee2f4..28ebbd19e7 100755 --- a/bin/migrate +++ b/bin/migrate @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php migrate $@ +php /usr/src/code/app/cli.php migrate $@ \ No newline at end of file diff --git a/bin/queue-count-failed b/bin/queue-count-failed index 93a6b3136c..ca8f2b4291 100644 --- a/bin/queue-count-failed +++ b/bin/queue-count-failed @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php queue-count --type=failed $@ +php /usr/src/code/app/cli.php queue-count --type=failed $@ \ No newline at end of file diff --git a/bin/queue-count-processing b/bin/queue-count-processing index 18e89664bd..325d86111d 100644 --- a/bin/queue-count-processing +++ b/bin/queue-count-processing @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php queue-count --type=processing $@ +php /usr/src/code/app/cli.php queue-count --type=processing $@ \ No newline at end of file diff --git a/bin/queue-count-success b/bin/queue-count-success index b38bfa2159..34fc54b4c1 100644 --- a/bin/queue-count-success +++ b/bin/queue-count-success @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php queue-count --type=success $@ +php /usr/src/code/app/cli.php queue-count --type=success $@ \ No newline at end of file diff --git a/bin/queue-retry b/bin/queue-retry index 2224a66b3b..f9473e6b07 100644 --- a/bin/queue-retry +++ b/bin/queue-retry @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php queue-retry $@ +php /usr/src/code/app/cli.php queue-retry $@ \ No newline at end of file diff --git a/bin/realtime b/bin/realtime index debd4baf2a..e43dc269e0 100644 --- a/bin/realtime +++ b/bin/realtime @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/realtime.php $@ +php /usr/src/code/app/realtime.php $@ \ No newline at end of file diff --git a/bin/schedule-executions b/bin/schedule-executions index 5d503e374c..f239cad206 100644 --- a/bin/schedule-executions +++ b/bin/schedule-executions @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php schedule-executions $@ +php /usr/src/code/app/cli.php schedule-executions $@ \ No newline at end of file diff --git a/bin/schedule-functions b/bin/schedule-functions index beca1a0420..10edbe8226 100644 --- a/bin/schedule-functions +++ b/bin/schedule-functions @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php schedule-functions $@ +php /usr/src/code/app/cli.php schedule-functions $@ \ No newline at end of file diff --git a/bin/schedule-messages b/bin/schedule-messages index 3f17a279b5..fa7219f6ea 100644 --- a/bin/schedule-messages +++ b/bin/schedule-messages @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php schedule-messages $@ +php /usr/src/code/app/cli.php schedule-messages $@ \ No newline at end of file diff --git a/bin/screenshot b/bin/screenshot index aef15eb96f..4d8ceb998f 100755 --- a/bin/screenshot +++ b/bin/screenshot @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php screenshot $@ \ No newline at end of file +php /usr/src/code/app/cli.php screenshot $@ \ No newline at end of file diff --git a/bin/sdks b/bin/sdks index 3180813ea1..ab73414829 100644 --- a/bin/sdks +++ b/bin/sdks @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php sdks $@ +php /usr/src/code/app/cli.php sdks $@ \ No newline at end of file diff --git a/bin/specs b/bin/specs index 52875a1675..e77d1487d4 100644 --- a/bin/specs +++ b/bin/specs @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php specs $@ +php /usr/src/code/app/cli.php specs $@ \ No newline at end of file diff --git a/bin/ssl b/bin/ssl index 0cc12375d0..83dcf6a026 100755 --- a/bin/ssl +++ b/bin/ssl @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php ssl $@ +php /usr/src/code/app/cli.php ssl $@ \ No newline at end of file diff --git a/bin/stats-resources b/bin/stats-resources index 9cc67fb4a6..3104bab896 100644 --- a/bin/stats-resources +++ b/bin/stats-resources @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php stats-resources $@ +php /usr/src/code/app/cli.php stats-resources $@ \ No newline at end of file diff --git a/bin/test b/bin/test index c3b0d9b74c..a2153fc536 100755 --- a/bin/test +++ b/bin/test @@ -1,3 +1,3 @@ #!/bin/sh -exec /usr/src/code/vendor/bin/phpunit --configuration /usr/src/code/phpunit.xml $@ +/usr/src/code/vendor/bin/phpunit --configuration /usr/src/code/phpunit.xml $@ \ No newline at end of file diff --git a/bin/upgrade b/bin/upgrade index fd1f35b65a..ce32b9ca30 100755 --- a/bin/upgrade +++ b/bin/upgrade @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php upgrade $@ +php /usr/src/code/app/cli.php upgrade $@ \ No newline at end of file diff --git a/bin/vars b/bin/vars index 238d004675..19e3f1ebf2 100644 --- a/bin/vars +++ b/bin/vars @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/cli.php vars $@ +php /usr/src/code/app/cli.php vars $@ \ No newline at end of file diff --git a/bin/worker-audits b/bin/worker-audits index 9bf81b93e2..3df65d65e8 100644 --- a/bin/worker-audits +++ b/bin/worker-audits @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/worker.php audits $@ +php /usr/src/code/app/worker.php audits $@ \ No newline at end of file diff --git a/bin/worker-builds b/bin/worker-builds index 7ddf5792de..3400111cb5 100644 --- a/bin/worker-builds +++ b/bin/worker-builds @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/worker.php builds $@ +php /usr/src/code/app/worker.php builds $@ \ No newline at end of file diff --git a/bin/worker-certificates b/bin/worker-certificates index 958627bc33..901688c4c8 100755 --- a/bin/worker-certificates +++ b/bin/worker-certificates @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/worker.php certificates $@ +php /usr/src/code/app/worker.php certificates $@ \ No newline at end of file diff --git a/bin/worker-databases b/bin/worker-databases index 235c16927c..61e09aa9f1 100644 --- a/bin/worker-databases +++ b/bin/worker-databases @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/worker.php databases $@ +php /usr/src/code/app/worker.php databases $@ diff --git a/bin/worker-deletes b/bin/worker-deletes index c9711a4e66..7c9793e6cb 100644 --- a/bin/worker-deletes +++ b/bin/worker-deletes @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/worker.php deletes $@ +php /usr/src/code/app/worker.php deletes $@ \ No newline at end of file diff --git a/bin/worker-functions b/bin/worker-functions index e82506d0e2..4757b1b72a 100644 --- a/bin/worker-functions +++ b/bin/worker-functions @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/worker.php functions $@ +php /usr/src/code/app/worker.php functions $@ \ No newline at end of file diff --git a/bin/worker-mails b/bin/worker-mails index ffb4f7ea77..fee8a96da7 100644 --- a/bin/worker-mails +++ b/bin/worker-mails @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/worker.php mails $@ +php /usr/src/code/app/worker.php mails $@ \ No newline at end of file diff --git a/bin/worker-messaging b/bin/worker-messaging index 6f39348419..e6edf80f06 100644 --- a/bin/worker-messaging +++ b/bin/worker-messaging @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/worker.php messaging $@ +php /usr/src/code/app/worker.php messaging $@ \ No newline at end of file diff --git a/bin/worker-migrations b/bin/worker-migrations index 2728d9d22c..32d4aef468 100644 --- a/bin/worker-migrations +++ b/bin/worker-migrations @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/worker.php migrations $@ +php /usr/src/code/app/worker.php migrations $@ \ No newline at end of file diff --git a/bin/worker-stats-resources b/bin/worker-stats-resources index 70bfacbe52..9c5d2bebff 100644 --- a/bin/worker-stats-resources +++ b/bin/worker-stats-resources @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/worker.php stats-resources $@ +php /usr/src/code/app/worker.php stats-resources $@ \ No newline at end of file diff --git a/bin/worker-stats-usage b/bin/worker-stats-usage index e6dd849a48..2c267d805e 100644 --- a/bin/worker-stats-usage +++ b/bin/worker-stats-usage @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/worker.php stats-usage $@ +php /usr/src/code/app/worker.php stats-usage $@ \ No newline at end of file diff --git a/bin/worker-webhooks b/bin/worker-webhooks index 63fc13e3c5..93f8027a81 100644 --- a/bin/worker-webhooks +++ b/bin/worker-webhooks @@ -1,3 +1,3 @@ #!/bin/sh -exec php /usr/src/code/app/worker.php webhooks $@ +php /usr/src/code/app/worker.php webhooks $@ \ No newline at end of file From 2ac4d9f901864adfb7b7df8212116c17ede01b05 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Sat, 21 Jun 2025 07:59:54 +0530 Subject: [PATCH 218/343] chore: update executor to fix s3 endpoint bug --- 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 e3699662a4..89facfe0f1 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -864,7 +864,7 @@ $image = $this->getParam('image', ''); <<: *x-logging restart: unless-stopped stop_signal: SIGINT - image: openruntimes/executor:0.7.20 + image: openruntimes/executor:0.7.22 networks: - appwrite - runtimes diff --git a/docker-compose.yml b/docker-compose.yml index 0b653af8c2..ecb46de057 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -951,7 +951,7 @@ services: hostname: exc1 <<: *x-logging stop_signal: SIGINT - image: openruntimes/executor:0.7.20 + image: openruntimes/executor:0.7.22 restart: unless-stopped networks: - appwrite From 7238e11bdbf1d0d822cba1ba0d0867e48c7f0da1 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Fri, 20 Jun 2025 20:31:26 -0700 Subject: [PATCH 219/343] fix: pin utopia-php/queue to 0.11.0 With the revert of PLA-2762, we need to pin the utopia-php/queue package to version 0.11.0 to avoid using the graceful shutdown feature that was introduced in version 0.11.1. --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 18507e04f1..4c36ab125d 100644 --- a/composer.json +++ b/composer.json @@ -67,7 +67,7 @@ "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", "utopia-php/preloader": "0.2.*", - "utopia-php/queue": "0.11.*", + "utopia-php/queue": "0.11.0", "utopia-php/registry": "0.5.*", "utopia-php/storage": "0.18.*", "utopia-php/swoole": "0.8.*", diff --git a/composer.lock b/composer.lock index 984f3e9fd3..bb80539305 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1557e469b3074a6478a0b2fd522e1a2a", + "content-hash": "55bc52686a08d64930e6af7411ac0654", "packages": [ { "name": "adhocore/jwt", @@ -4251,16 +4251,16 @@ }, { "name": "utopia-php/queue", - "version": "0.11.1", + "version": "0.11.0", "source": { "type": "git", "url": "https://github.com/utopia-php/queue.git", - "reference": "498bbbef418b1db71b51e1bb62f5d1d752ddd8d6" + "reference": "06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/queue/zipball/498bbbef418b1db71b51e1bb62f5d1d752ddd8d6", - "reference": "498bbbef418b1db71b51e1bb62f5d1d752ddd8d6", + "url": "https://api.github.com/repos/utopia-php/queue/zipball/06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5", + "reference": "06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5", "shasum": "" }, "require": { @@ -4311,9 +4311,9 @@ ], "support": { "issues": "https://github.com/utopia-php/queue/issues", - "source": "https://github.com/utopia-php/queue/tree/0.11.1" + "source": "https://github.com/utopia-php/queue/tree/0.11.0" }, - "time": "2025-05-30T11:50:34+00:00" + "time": "2025-05-30T09:52:38+00:00" }, { "name": "utopia-php/registry", From b52c49389c6cfc820b977d9b3b05ca926a172170 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 23 Jun 2025 12:28:14 +0530 Subject: [PATCH 220/343] fix: oha as per latest updates. --- .github/workflows/benchmark.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 6d73787d00..6b159985f2 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -65,7 +65,7 @@ jobs: sudo apt update sudo apt install oha - name: Benchmark PR - run: 'oha -z 180s http://localhost/v1/health/version -j > benchmark.json' + run: 'oha -z 180s http://localhost/v1/health/version -o json > benchmark.json' - name: Cleaning run: docker compose down -v - name: Installing latest version @@ -78,7 +78,7 @@ jobs: docker compose up -d sleep 10 - name: Benchmark Latest - run: oha -z 180s http://localhost/v1/health/version -j > benchmark-latest.json + run: 'oha -z 180s http://localhost/v1/health/version -o json > benchmark-latest.json' - name: Prepare comment run: | echo '## :sparkles: Benchmark results' > benchmark.txt From 6a74273564dd43ded759befa6e265dbdbe148d41 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 23 Jun 2025 12:45:34 +0530 Subject: [PATCH 221/343] fix: oha as per latest updates. --- .github/workflows/benchmark.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 6b159985f2..262c79ab3d 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -65,7 +65,7 @@ jobs: sudo apt update sudo apt install oha - name: Benchmark PR - run: 'oha -z 180s http://localhost/v1/health/version -o json > benchmark.json' + run: 'oha -z 180s http://localhost/v1/health/version --output-format json --output benchmark.json' - name: Cleaning run: docker compose down -v - name: Installing latest version @@ -78,7 +78,7 @@ jobs: docker compose up -d sleep 10 - name: Benchmark Latest - run: 'oha -z 180s http://localhost/v1/health/version -o json > benchmark-latest.json' + run: 'oha -z 180s http://localhost/v1/health/version --output-format json --output benchmark-latest.json' - name: Prepare comment run: | echo '## :sparkles: Benchmark results' > benchmark.txt From c1bd493fbea286836675458c9f797a886a84f834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 23 Jun 2025 11:28:18 +0200 Subject: [PATCH 222/343] Move refferer to resource; re-use in OPTIONS; re-use in platform check --- app/controllers/general.php | 50 +++++++----------------------------- app/init/resources.php | 51 +++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 41 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 61a9cc9bfa..a47ae510fa 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -793,7 +793,6 @@ App::init() ->inject('getProjectDB') ->inject('locale') ->inject('localeCodes') - ->inject('clients') ->inject('geodb') ->inject('queueForStatsUsage') ->inject('queueForEvents') @@ -804,7 +803,9 @@ App::init() ->inject('previewHostname') ->inject('devKey') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey) { + ->inject('httpReferrer') + ->inject('httpReferrerSafe') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, string $httpReferrer, string $httpReferrerSafe) { /* * Appwrite Router */ @@ -936,42 +937,9 @@ App::init() $locale->setDefault($localeParam); } - $referrer = $request->getReferer(); - $origin = \parse_url($request->getOrigin($referrer), PHP_URL_HOST); - $protocol = \parse_url($request->getOrigin($referrer), PHP_URL_SCHEME); - $port = \parse_url($request->getOrigin($referrer), PHP_URL_PORT); - - $refDomainOrigin = 'localhost'; - $validator = new Hostname($clients); - if ($validator->isValid($origin)) { - $refDomainOrigin = $origin; - } elseif (!empty($origin)) { - // Auto-allow domains with linked rule - if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($origin ?? ''))); - } else { - $rule = Authorization::skip( - fn () => $dbForPlatform->find('rules', [ - Query::equal('domain', [$origin]), - Query::limit(1) - ]) - )[0] ?? new Document(); - } - - if (!$rule->isEmpty() && $rule->getAttribute('projectInternalId') === $project->getSequence()) { - $refDomainOrigin = $origin; - } - } - - $refDomain = (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $refDomainOrigin . (!empty($port) ? ':' . $port : ''); - - $refDomain = (!$route->getLabel('origin', false)) // This route is publicly accessible - ? $refDomain - : (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $origin . (!empty($port) ? ':' . $port : ''); - + $origin = \parse_url($request->getOrigin($httpReferrer), PHP_URL_HOST); $selfDomain = new Domain($request->getHostname()); $endDomain = new Domain((string)$origin); - Config::setParam( 'domainVerification', ($selfDomain->getRegisterable() === $endDomain->getRegisterable()) && @@ -1043,7 +1011,7 @@ App::init() ->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE') ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Dev-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Forwarded-For, X-Forwarded-User-Agent') ->addHeader('Access-Control-Expose-Headers', 'X-Appwrite-Session, X-Fallback-Cookies') - ->addHeader('Access-Control-Allow-Origin', $refDomain) + ->addHeader('Access-Control-Allow-Origin', $httpReferrerSafe) ->addHeader('Access-Control-Allow-Credentials', 'true'); if (!$devKey->isEmpty()) { @@ -1064,6 +1032,7 @@ App::init() && \in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE]) && $route->getLabel('origin', false) !== '*' && empty($request->getHeader('x-appwrite-key', '')) + && \parse_url($httpReferrerSafe, PHP_URL_HOST) === 'localhost' ) { throw new AppwriteException(AppwriteException::GENERAL_UNKNOWN_ORIGIN, $originValidator->getDescription()); } @@ -1086,7 +1055,8 @@ App::options() ->inject('project') ->inject('devKey') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey) { + ->inject('httpReferrerSafe') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, string $httpReferrerSafe) { /* * Appwrite Router */ @@ -1099,14 +1069,12 @@ App::options() } } - $origin = $request->getOrigin(); - $response ->addHeader('Server', 'Appwrite') ->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE') ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Dev-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Appwrite-Session, X-Fallback-Cookies, X-Forwarded-For, X-Forwarded-User-Agent') ->addHeader('Access-Control-Expose-Headers', 'X-Appwrite-Session, X-Fallback-Cookies') - ->addHeader('Access-Control-Allow-Origin', $origin) + ->addHeader('Access-Control-Allow-Origin', $httpReferrerSafe) ->addHeader('Access-Control-Allow-Credentials', 'true') ->noContent(); diff --git a/app/init/resources.php b/app/init/resources.php index 5f65fe683f..eb77598adc 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -944,3 +944,54 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { } return new Document([]); }, ['project', 'dbForProject', 'request']); + +App::setResource('httpReferrer', function (Request $request): string { + $referrer = $request->getReferer(); + return $referrer; +}, ['request']); + +App::setResource('httpReferrerSafe', function (Request $request, string $httpReferrer, array $clients, Database $dbForPlatform, Document $project, App $utopia): string { + $origin = \parse_url($request->getOrigin($httpReferrer), PHP_URL_HOST); + + // Safe if route is public + $route = $utopia->getRoute(); + if (!$route->getLabel('origin', false)) { + goto originToUrl; + } + + // Safe if added as web platform + $validator = new Hostname($clients); + if ($validator->isValid($origin)) { + goto originToUrl; + } + + // Safe if rule with same project ID exists + if (!empty($origin)) { + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { + $rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($origin ?? ''))); + } else { + $rule = Authorization::skip( + fn () => $dbForPlatform->find('rules', [ + Query::equal('domain', [$origin]), + Query::limit(1) + ]) + )[0] ?? new Document(); + } + + if (!$rule->isEmpty() && $rule->getAttribute('projectInternalId') === $project->getSequence()) { + goto originToUrl; + } + } + + // Unsafe; Localhost is always safe for ease of local development + $origin = 'localhost'; + + originToUrl: + + $protocol = \parse_url($request->getOrigin($httpReferrer), PHP_URL_SCHEME); + $port = \parse_url($request->getOrigin($httpReferrer), PHP_URL_PORT); + + $referrer = (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $origin . (!empty($port) ? ':' . $port : ''); + + return $referrer; +}, ['request', 'httpReferrer', 'clients', 'dbForPlatform', 'project', 'utopia']); From b69ff36ddb2dc59d4699fd0a86d188c2513faaf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 23 Jun 2025 11:57:06 +0200 Subject: [PATCH 223/343] Manual QA fixes --- app/controllers/general.php | 7 ++++--- app/init/resources.php | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index a47ae510fa..3745a41c9a 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1055,8 +1055,7 @@ App::options() ->inject('project') ->inject('devKey') ->inject('apiKey') - ->inject('httpReferrerSafe') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, string $httpReferrerSafe) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey) { /* * Appwrite Router */ @@ -1069,12 +1068,14 @@ App::options() } } + $origin = $request->getOrigin(); + $response ->addHeader('Server', 'Appwrite') ->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE') ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Dev-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Appwrite-Session, X-Fallback-Cookies, X-Forwarded-For, X-Forwarded-User-Agent') ->addHeader('Access-Control-Expose-Headers', 'X-Appwrite-Session, X-Fallback-Cookies') - ->addHeader('Access-Control-Allow-Origin', $httpReferrerSafe) + ->addHeader('Access-Control-Allow-Origin', $origin) ->addHeader('Access-Control-Allow-Credentials', 'true') ->noContent(); diff --git a/app/init/resources.php b/app/init/resources.php index eb77598adc..18203869df 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -953,9 +953,9 @@ App::setResource('httpReferrer', function (Request $request): string { App::setResource('httpReferrerSafe', function (Request $request, string $httpReferrer, array $clients, Database $dbForPlatform, Document $project, App $utopia): string { $origin = \parse_url($request->getOrigin($httpReferrer), PHP_URL_HOST); - // Safe if route is public + // Safe if route is publicly accessible $route = $utopia->getRoute(); - if (!$route->getLabel('origin', false)) { + if ($route->getLabel('origin', false)) { goto originToUrl; } From 54748b7d3274b521ada36bc7fd952d77e79e203f Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Mon, 23 Jun 2025 20:50:59 +0400 Subject: [PATCH 224/343] Update app/controllers/general.php Co-authored-by: Steven Nguyen <1477010+stnguyen90@users.noreply.github.com> --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index f06c46e8d9..943743d956 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1275,7 +1275,7 @@ App::error() $log->addTag('code', $error->getCode()); $tags = $log->getTags(); - if (isset($tags['projectId'])) { + if (!isset($tags['projectId'])) { $log->addTag('projectId', $project->getId()); } From 3059eecbeb48ee62e6a997d0c2704c4d3d3f2f24 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 23 Jun 2025 20:27:12 +0300 Subject: [PATCH 225/343] benchmark cli --- .github/workflows/benchmark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 6d73787d00..5ca639849e 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -65,7 +65,7 @@ jobs: sudo apt update sudo apt install oha - name: Benchmark PR - run: 'oha -z 180s http://localhost/v1/health/version -j > benchmark.json' + run: 'oha -z 180s http://localhost/v1/health/version --j > benchmark.json' - name: Cleaning run: docker compose down -v - name: Installing latest version From 4e0faf67f7c6c6311cf1ac6b5a283e75dee09bb8 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 23 Jun 2025 20:39:52 +0300 Subject: [PATCH 226/343] benchmark cli --- .github/workflows/benchmark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 5ca639849e..799f1192cc 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -65,7 +65,7 @@ jobs: sudo apt update sudo apt install oha - name: Benchmark PR - run: 'oha -z 180s http://localhost/v1/health/version --j > benchmark.json' + run: 'oha -z 180s http://localhost/v1/health/version > benchmark.json' - name: Cleaning run: docker compose down -v - name: Installing latest version From 213b1ae20e96393888c114ddcd859d730c4f7074 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 23 Jun 2025 20:57:39 +0300 Subject: [PATCH 227/343] benchmark cli --- .github/workflows/benchmark.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 799f1192cc..f1051497a8 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -65,7 +65,7 @@ jobs: sudo apt update sudo apt install oha - name: Benchmark PR - run: 'oha -z 180s http://localhost/v1/health/version > benchmark.json' + run: 'oha -z 180s http://localhost/v1/health/version --output-format json > benchmark.json' - name: Cleaning run: docker compose down -v - name: Installing latest version @@ -78,7 +78,7 @@ jobs: docker compose up -d sleep 10 - name: Benchmark Latest - run: oha -z 180s http://localhost/v1/health/version -j > benchmark-latest.json + run: oha -z 180s http://localhost/v1/health/version --output-format json > benchmark-latest.json - name: Prepare comment run: | echo '## :sparkles: Benchmark results' > benchmark.txt From 47594076962227290a2b0a304d3c892e120d6aaf Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 24 Jun 2025 14:57:30 +0400 Subject: [PATCH 228/343] chore: update composer.json and composer.lock to include appwrite-labs/php-amqplib and adjust utopia-php/queue version --- composer.json | 2 +- composer.lock | 215 +++++++++++++++++++++++++++----------------------- 2 files changed, 119 insertions(+), 98 deletions(-) diff --git a/composer.json b/composer.json index 4c36ab125d..4dc877d69e 100644 --- a/composer.json +++ b/composer.json @@ -67,7 +67,7 @@ "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", "utopia-php/preloader": "0.2.*", - "utopia-php/queue": "0.11.0", + "utopia-php/queue": "dev-feat-swoole-amqp-adapter as 0.11.1", "utopia-php/registry": "0.5.*", "utopia-php/storage": "0.18.*", "utopia-php/swoole": "0.8.*", diff --git a/composer.lock b/composer.lock index bb80539305..ed085f92e9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "55bc52686a08d64930e6af7411ac0654", + "content-hash": "783e4b89e54e4d58f3c177c1a700da7c", "packages": [ { "name": "adhocore/jwt", @@ -67,6 +67,99 @@ ], "time": "2025-02-18T01:00:50+00:00" }, + { + "name": "appwrite-labs/php-amqplib", + "version": "0.1.0", + "source": { + "type": "git", + "url": "https://github.com/appwrite-labs/php-amqplib.git", + "reference": "30d709df7510e784d16ad7a7f817d26fe79615a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/appwrite-labs/php-amqplib/zipball/30d709df7510e784d16ad7a7f817d26fe79615a0", + "reference": "30d709df7510e784d16ad7a7f817d26fe79615a0", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-sockets": "*", + "php": "^7.2||^8.0", + "phpseclib/phpseclib": "^2.0|^3.0" + }, + "conflict": { + "php": "7.4.0 - 7.4.1" + }, + "replace": { + "php-amqplib/php-amqplib": "self.version", + "videlalvaro/php-amqplib": "self.version" + }, + "require-dev": { + "ext-curl": "*", + "nategood/httpful": "^0.2.20", + "phpunit/phpunit": "^7.5|^9.5", + "squizlabs/php_codesniffer": "^3.6", + "swoole/ide-helper": "^5.0" + }, + "suggest": { + "ext-swoole": "For Swoole coroutine support" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpAmqpLib\\": "PhpAmqpLib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Appwrite Labs", + "email": "team@appwrite.io", + "role": "Fork Maintainer" + }, + { + "name": "Alvaro Videla", + "role": "Original Maintainer" + }, + { + "name": "Raúl Araya", + "email": "nubeiro@gmail.com", + "role": "Maintainer" + }, + { + "name": "Luke Bakken", + "email": "luke@bakken.io", + "role": "Maintainer" + }, + { + "name": "Ramūnas Dronga", + "email": "github@ramuno.lt", + "role": "Maintainer" + } + ], + "description": "Fork of php-amqplib with Swoole coroutine support. A pure PHP implementation of the AMQP protocol tested against RabbitMQ.", + "homepage": "https://github.com/appwrite-labs/php-amqplib/", + "keywords": [ + "async", + "coroutine", + "message", + "queue", + "rabbitmq", + "swoole" + ], + "support": { + "source": "https://github.com/appwrite-labs/php-amqplib/tree/0.1.0" + }, + "time": "2025-06-13T21:45:04+00:00" + }, { "name": "appwrite/appwrite", "version": "11.1.0", @@ -1631,87 +1724,6 @@ }, "time": "2020-10-15T08:29:30+00:00" }, - { - "name": "php-amqplib/php-amqplib", - "version": "v3.7.3", - "source": { - "type": "git", - "url": "https://github.com/php-amqplib/php-amqplib.git", - "reference": "9f50fe69a9f1a19e2cb25596a354d705de36fe59" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/9f50fe69a9f1a19e2cb25596a354d705de36fe59", - "reference": "9f50fe69a9f1a19e2cb25596a354d705de36fe59", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "ext-sockets": "*", - "php": "^7.2||^8.0", - "phpseclib/phpseclib": "^2.0|^3.0" - }, - "conflict": { - "php": "7.4.0 - 7.4.1" - }, - "replace": { - "videlalvaro/php-amqplib": "self.version" - }, - "require-dev": { - "ext-curl": "*", - "nategood/httpful": "^0.2.20", - "phpunit/phpunit": "^7.5|^9.5", - "squizlabs/php_codesniffer": "^3.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "psr-4": { - "PhpAmqpLib\\": "PhpAmqpLib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-2.1-or-later" - ], - "authors": [ - { - "name": "Alvaro Videla", - "role": "Original Maintainer" - }, - { - "name": "Raúl Araya", - "email": "nubeiro@gmail.com", - "role": "Maintainer" - }, - { - "name": "Luke Bakken", - "email": "luke@bakken.io", - "role": "Maintainer" - }, - { - "name": "Ramūnas Dronga", - "email": "github@ramuno.lt", - "role": "Maintainer" - } - ], - "description": "Formerly videlalvaro/php-amqplib. This library is a pure PHP implementation of the AMQP protocol. It's been tested against RabbitMQ.", - "homepage": "https://github.com/php-amqplib/php-amqplib/", - "keywords": [ - "message", - "queue", - "rabbitmq" - ], - "support": { - "issues": "https://github.com/php-amqplib/php-amqplib/issues", - "source": "https://github.com/php-amqplib/php-amqplib/tree/v3.7.3" - }, - "time": "2025-02-18T20:11:13+00:00" - }, { "name": "php-http/discovery", "version": "1.20.0", @@ -1874,16 +1886,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.44", + "version": "3.0.45", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "1d0b5e7e1434678411787c5a0535e68907cf82d9" + "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/1d0b5e7e1434678411787c5a0535e68907cf82d9", - "reference": "1d0b5e7e1434678411787c5a0535e68907cf82d9", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/bd81b90d5963c6b9d87de50357585375223f4dd8", + "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8", "shasum": "" }, "require": { @@ -1964,7 +1976,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.44" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.45" }, "funding": [ { @@ -1980,7 +1992,7 @@ "type": "tidelift" } ], - "time": "2025-06-15T09:59:26+00:00" + "time": "2025-06-22T22:54:43+00:00" }, { "name": "psr/container", @@ -4251,21 +4263,21 @@ }, { "name": "utopia-php/queue", - "version": "0.11.0", + "version": "dev-feat-swoole-amqp-adapter", "source": { "type": "git", "url": "https://github.com/utopia-php/queue.git", - "reference": "06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5" + "reference": "080639c0cd05abf5d897c1486825cf74c1ad1961" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/queue/zipball/06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5", - "reference": "06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5", + "url": "https://api.github.com/repos/utopia-php/queue/zipball/080639c0cd05abf5d897c1486825cf74c1ad1961", + "reference": "080639c0cd05abf5d897c1486825cf74c1ad1961", "shasum": "" }, "require": { + "appwrite-labs/php-amqplib": "0.1.0", "php": ">=8.3", - "php-amqplib/php-amqplib": "^3.7", "utopia-php/cli": "0.15.*", "utopia-php/fetch": "0.4.*", "utopia-php/framework": "0.33.*", @@ -4311,9 +4323,9 @@ ], "support": { "issues": "https://github.com/utopia-php/queue/issues", - "source": "https://github.com/utopia-php/queue/tree/0.11.0" + "source": "https://github.com/utopia-php/queue/tree/feat-swoole-amqp-adapter" }, - "time": "2025-05-30T09:52:38+00:00" + "time": "2025-06-24T10:55:47+00:00" }, { "name": "utopia-php/registry", @@ -8231,9 +8243,18 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/queue", + "version": "dev-feat-swoole-amqp-adapter", + "alias": "0.11.1", + "alias_normalized": "0.11.1.0" + } + ], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/queue": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { From fe080153e6405579500c324583392be8953fbe0a Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 24 Jun 2025 15:28:07 +0400 Subject: [PATCH 229/343] chore: update benchmark workflow to use JSON output format --- .github/workflows/benchmark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 6d73787d00..ba55a4a88b 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -78,7 +78,7 @@ jobs: docker compose up -d sleep 10 - name: Benchmark Latest - run: oha -z 180s http://localhost/v1/health/version -j > benchmark-latest.json + run: oha -z 180s http://localhost/v1/health/version --output-format json > benchmark-latest.json - name: Prepare comment run: | echo '## :sparkles: Benchmark results' > benchmark.txt From 6996cc28a0a607a8bc8a47ef69bff915c83f4b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 24 Jun 2025 14:47:47 +0200 Subject: [PATCH 230/343] Fix logs order --- .../Modules/Functions/Workers/Builds.php | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 8ff1690da9..7fe5e77114 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -845,11 +845,6 @@ class Builds extends Action $logs = \substr($logs, 0, $separator); } - if ($resource->getCollection() === 'sites') { - $date = \date('H:i:s'); - $logs .= "[$date] [appwrite] Screenshot capturing started. \n"; - } - $deployment->setAttribute('buildLogs', $logs); if ($resource->getCollection() === 'sites' && !empty($detectionLogs)) { @@ -877,16 +872,24 @@ class Builds extends Action } } - $deployment->setAttribute('buildLogs', $logs); - - $this->afterBuildSuccess($dbForProject, $deployment); - $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); - $queueForRealtime ->setPayload($deployment->getArrayCopy()) ->trigger(); + + $this->afterBuildSuccess($queueForRealtime, $dbForProject, $deployment); + + if ($resource->getCollection() === 'sites') { + $date = \date('H:i:s'); + $logs .= "[$date] [appwrite] Screenshot capturing started. \n"; + $deployment->setAttribute('buildLogs', $logs); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + } + /** Screenshot site */ if ($resource->getCollection() === 'sites') { try { @@ -1319,12 +1322,14 @@ class Builds extends Action /** * Hook to run after build success * + * @param Realtime $queueForRealtime * @param Database $dbForProject * @param Document $deployment * @return void */ - protected function afterBuildSuccess(Database $dbForProject, Document &$deployment): void + protected function afterBuildSuccess(Realtime $queueForRealtime, Database $dbForProject, Document &$deployment): void { + assert($queueForRealtime instanceof Realtime); assert($dbForProject instanceof Database); assert($deployment instanceof Document); } From 5dcc50887047a4e8a2723f77028a2bb8fdae45d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 24 Jun 2025 15:38:39 +0200 Subject: [PATCH 231/343] Fix logs parsing --- .../Platform/Modules/Functions/Workers/Builds.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 7fe5e77114..725cc89510 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -838,11 +838,9 @@ class Builds extends Action $detectionLogs = ''; $separator = \strpos($logs, '{APPWRITE_DETECTION_SEPARATOR_START}'); if ($separator !== false) { - $detectionLogs = \substr($logs, $separator + strlen('{APPWRITE_DETECTION_SEPARATOR}')); - $separatorEnd = \strpos($detectionLogs, '{APPWRITE_DETECTION_SEPARATOR_END}'); - $logs .= \substr($detectionLogs, $separatorEnd + strlen('{APPWRITE_DETECTION_SEPARATOR_END}')); - $detectionLogs = \substr($detectionLogs, 0, $separatorEnd); - $logs = \substr($logs, 0, $separator); + [$logsBefore, $detectionLogsStart] = \explode('{APPWRITE_DETECTION_SEPARATOR_START}', $logs, 2); + [$detectionLogs, $logsAfter] = \explode('{APPWRITE_DETECTION_SEPARATOR_END}', $detectionLogsStart, 2); + $logs = $logsBefore . $logsAfter; } $deployment->setAttribute('buildLogs', $logs); @@ -877,7 +875,6 @@ class Builds extends Action ->setPayload($deployment->getArrayCopy()) ->trigger(); - $this->afterBuildSuccess($queueForRealtime, $dbForProject, $deployment); if ($resource->getCollection() === 'sites') { From b5bc240c0dc73a27d9b4e032ea362210bd733a76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 24 Jun 2025 15:56:06 +0200 Subject: [PATCH 232/343] Fix ssr separation; add edge debugging logs --- .../Modules/Functions/Workers/Builds.php | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 725cc89510..1338ebdd73 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -747,6 +747,13 @@ class Builds extends Action if ($separator !== false) { $logs = \substr($logs, 0, $separator); $insideSeparation = true; + + $leftover = \substr($logs, $separator + strlen('{APPWRITE_DETECTION_SEPARATOR_START}')); + $separator = \strpos($leftover, '{APPWRITE_DETECTION_SEPARATOR_END}'); + if ($separator !== false) { + $logs .= \substr($leftover, $separator + strlen('{APPWRITE_DETECTION_SEPARATOR_END}')); + $insideSeparation = false; + } } } else { $separator = \strpos($logs, '{APPWRITE_DETECTION_SEPARATOR_END}'); @@ -836,11 +843,10 @@ class Builds extends Action // Separate logs for SSR detection $detectionLogs = ''; - $separator = \strpos($logs, '{APPWRITE_DETECTION_SEPARATOR_START}'); - if ($separator !== false) { + if (\str_contains($logs, '{APPWRITE_DETECTION_SEPARATOR_START}')) { [$logsBefore, $detectionLogsStart] = \explode('{APPWRITE_DETECTION_SEPARATOR_START}', $logs, 2); [$detectionLogs, $logsAfter] = \explode('{APPWRITE_DETECTION_SEPARATOR_END}', $detectionLogsStart, 2); - $logs = $logsBefore . $logsAfter; + $logs = ($logsBefore ?? '') . ($logsAfter ?? ''); } $deployment->setAttribute('buildLogs', $logs); @@ -877,6 +883,10 @@ class Builds extends Action $this->afterBuildSuccess($queueForRealtime, $dbForProject, $deployment); + \var_dump("After edge finish:"); + \var_dump($deployment); + \var_dump('---'); + if ($resource->getCollection() === 'sites') { $date = \date('H:i:s'); $logs .= "[$date] [appwrite] Screenshot capturing started. \n"; @@ -1225,12 +1235,8 @@ class Builds extends Action $message = "" . $message; } - $separator = \strpos($message, '{APPWRITE_DETECTION_SEPARATOR_START}'); - if ($separator !== false) { - $error = \substr($message, $separator + strlen('{APPWRITE_DETECTION_SEPARATOR_START}')); - $message = \substr($message, 0, $separator); - $message .= "\n" . $error; - } + $message = \str_replace('{APPWRITE_DETECTION_SEPARATOR_START}', '', $message, 1); + $message = \str_replace('{APPWRITE_DETECTION_SEPARATOR_END}', '', $message, 1); // Combine with previous logs if deployment got past build process $previousLogs = ''; From c04c2d271c1f2462e5207289afa52b36cf53b1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 24 Jun 2025 16:03:28 +0200 Subject: [PATCH 233/343] Remove logs, fix edge logs missing --- src/Appwrite/Platform/Modules/Functions/Workers/Builds.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 1338ebdd73..b086bd402e 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -882,10 +882,7 @@ class Builds extends Action ->trigger(); $this->afterBuildSuccess($queueForRealtime, $dbForProject, $deployment); - - \var_dump("After edge finish:"); - \var_dump($deployment); - \var_dump('---'); + $logs = $deployment->getAttribute('buildLogs', ''); if ($resource->getCollection() === 'sites') { $date = \date('H:i:s'); From b646eb7758eb3d3b73e129b8ef2ed5c71310c042 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 25 Jun 2025 00:23:21 +0400 Subject: [PATCH 234/343] chore: update composer.json and composer.lock to upgrade utopia-php/queue to version 0.12.0 and appwrite-labs/php-amqplib to version 0.1.1 --- composer.json | 2 +- composer.lock | 55 +++++++++++++++++++++------------------------------ 2 files changed, 24 insertions(+), 33 deletions(-) diff --git a/composer.json b/composer.json index 4dc877d69e..76b7146b96 100644 --- a/composer.json +++ b/composer.json @@ -67,7 +67,7 @@ "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", "utopia-php/preloader": "0.2.*", - "utopia-php/queue": "dev-feat-swoole-amqp-adapter as 0.11.1", + "utopia-php/queue": "^0.12.0", "utopia-php/registry": "0.5.*", "utopia-php/storage": "0.18.*", "utopia-php/swoole": "0.8.*", diff --git a/composer.lock b/composer.lock index ed085f92e9..4c0a92d3af 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "783e4b89e54e4d58f3c177c1a700da7c", + "content-hash": "dbd3be6cce9f2a5e551be564cdabcbe5", "packages": [ { "name": "adhocore/jwt", @@ -69,16 +69,16 @@ }, { "name": "appwrite-labs/php-amqplib", - "version": "0.1.0", + "version": "0.1.1", "source": { "type": "git", "url": "https://github.com/appwrite-labs/php-amqplib.git", - "reference": "30d709df7510e784d16ad7a7f817d26fe79615a0" + "reference": "bd380cbd63c8c0f063a3893b7a0b889d40876861" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite-labs/php-amqplib/zipball/30d709df7510e784d16ad7a7f817d26fe79615a0", - "reference": "30d709df7510e784d16ad7a7f817d26fe79615a0", + "url": "https://api.github.com/repos/appwrite-labs/php-amqplib/zipball/bd380cbd63c8c0f063a3893b7a0b889d40876861", + "reference": "bd380cbd63c8c0f063a3893b7a0b889d40876861", "shasum": "" }, "require": { @@ -156,9 +156,9 @@ "swoole" ], "support": { - "source": "https://github.com/appwrite-labs/php-amqplib/tree/0.1.0" + "source": "https://github.com/appwrite-labs/php-amqplib/tree/0.1.1" }, - "time": "2025-06-13T21:45:04+00:00" + "time": "2025-06-24T18:12:57+00:00" }, { "name": "appwrite/appwrite", @@ -4108,16 +4108,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.8", + "version": "0.7.9", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "e3a4536c46f10988b1a446ec6b8dd8a9914be854" + "reference": "b061f523513b071ef7168e6dc1441364eb73f308" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/e3a4536c46f10988b1a446ec6b8dd8a9914be854", - "reference": "e3a4536c46f10988b1a446ec6b8dd8a9914be854", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/b061f523513b071ef7168e6dc1441364eb73f308", + "reference": "b061f523513b071ef7168e6dc1441364eb73f308", "shasum": "" }, "require": { @@ -4126,7 +4126,7 @@ "php": ">=8.0", "utopia-php/cli": "0.15.*", "utopia-php/framework": "0.33.*", - "utopia-php/queue": "0.11.*" + "utopia-php/queue": "^0.12.0" }, "require-dev": { "laravel/pint": "1.*", @@ -4152,9 +4152,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.8" + "source": "https://github.com/utopia-php/platform/tree/0.7.9" }, - "time": "2025-05-30T10:05:43+00:00" + "time": "2025-06-24T20:21:05+00:00" }, { "name": "utopia-php/pools", @@ -4263,20 +4263,20 @@ }, { "name": "utopia-php/queue", - "version": "dev-feat-swoole-amqp-adapter", + "version": "0.12.0", "source": { "type": "git", "url": "https://github.com/utopia-php/queue.git", - "reference": "080639c0cd05abf5d897c1486825cf74c1ad1961" + "reference": "3a7603ee712c592bfc54af4a76f0426c428b5574" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/queue/zipball/080639c0cd05abf5d897c1486825cf74c1ad1961", - "reference": "080639c0cd05abf5d897c1486825cf74c1ad1961", + "url": "https://api.github.com/repos/utopia-php/queue/zipball/3a7603ee712c592bfc54af4a76f0426c428b5574", + "reference": "3a7603ee712c592bfc54af4a76f0426c428b5574", "shasum": "" }, "require": { - "appwrite-labs/php-amqplib": "0.1.0", + "appwrite-labs/php-amqplib": "^0.1", "php": ">=8.3", "utopia-php/cli": "0.15.*", "utopia-php/fetch": "0.4.*", @@ -4323,9 +4323,9 @@ ], "support": { "issues": "https://github.com/utopia-php/queue/issues", - "source": "https://github.com/utopia-php/queue/tree/feat-swoole-amqp-adapter" + "source": "https://github.com/utopia-php/queue/tree/0.12.0" }, - "time": "2025-06-24T10:55:47+00:00" + "time": "2025-06-24T18:58:38+00:00" }, { "name": "utopia-php/registry", @@ -8243,18 +8243,9 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [ - { - "package": "utopia-php/queue", - "version": "dev-feat-swoole-amqp-adapter", - "alias": "0.11.1", - "alias_normalized": "0.11.1.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/queue": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From c331a3caae7345eb27dbeaf4221fd008735e662c Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 25 Jun 2025 11:00:07 +0530 Subject: [PATCH 235/343] chore: minor fixes --- .github/workflows/tests.yml | 2 -- src/Appwrite/Network/Platform.php | 5 ++++- src/Appwrite/Network/Validator/Origin.php | 2 +- tests/e2e/Scopes/Scope.php | 2 ++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 97f3696e67..a69e11b892 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -283,8 +283,6 @@ jobs: name: E2E Service Test (Dev Keys) runs-on: ubuntu-latest needs: setup - strategy: - fail-fast: false steps: - name: checkout uses: actions/checkout@v4 diff --git a/src/Appwrite/Network/Platform.php b/src/Appwrite/Network/Platform.php index ab7b73cd17..cc59bd4508 100644 --- a/src/Appwrite/Network/Platform.php +++ b/src/Appwrite/Network/Platform.php @@ -69,7 +69,9 @@ class Platform switch ($type) { case self::TYPE_WEB: case self::TYPE_FLUTTER_WEB: - $hostnames[] = $hostname; + if (!empty($hostname)) { + $hostnames[] = $hostname; + } break; case self::TYPE_FLUTTER_IOS: case self::TYPE_FLUTTER_ANDROID: @@ -83,6 +85,7 @@ class Platform case self::TYPE_APPLE_TVOS: case self::TYPE_REACT_NATIVE_IOS: case self::TYPE_REACT_NATIVE_ANDROID: + case self::TYPE_UNITY: if (!empty($key)) { $hostnames[] = $key; } diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 53598da324..b0aa4bd49b 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -16,7 +16,7 @@ class Origin extends Validator /** * Constructor * - * @param array $platforms + * @param array<\Utopia\Database\Document> $platforms */ public function __construct(array $platforms) { diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index dddc97e3a0..80eac2acc3 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -189,6 +189,8 @@ abstract class Scope extends TestCase 'name' => $name, ]); + fwrite(STDERR, json_encode($user, JSON_PRETTY_PRINT)); + $this->assertEquals(201, $user['headers']['status-code']); $session = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ From 7f4d6233a2f8e8e80d5bbbf6b2486ef49cf60888 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 25 Jun 2025 11:00:09 +0530 Subject: [PATCH 236/343] add: validators to swagger2. --- src/Appwrite/SDK/Specification/Format/Swagger2.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Appwrite/SDK/Specification/Format/Swagger2.php b/src/Appwrite/SDK/Specification/Format/Swagger2.php index 4c4016e7e7..79b26399fd 100644 --- a/src/Appwrite/SDK/Specification/Format/Swagger2.php +++ b/src/Appwrite/SDK/Specification/Format/Swagger2.php @@ -415,6 +415,8 @@ class Swagger2 extends Format case 'Utopia\Database\Validator\Queries': case 'Utopia\Database\Validator\Queries\Document': case 'Utopia\Database\Validator\Queries\Documents': + case 'Appwrite\Utopia\Database\Validator\Queries\Columns': + case 'Appwrite\Utopia\Database\Validator\Queries\Tables': $node['type'] = 'array'; $node['collectionFormat'] = 'multi'; $node['items'] = [ From 6dda6e1fdabd6fc105641a3c85bddd57264efbe0 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 25 Jun 2025 11:25:39 +0530 Subject: [PATCH 237/343] chore: remove console log --- tests/e2e/Scopes/Scope.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index 80eac2acc3..dddc97e3a0 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -189,8 +189,6 @@ abstract class Scope extends TestCase 'name' => $name, ]); - fwrite(STDERR, json_encode($user, JSON_PRETTY_PRINT)); - $this->assertEquals(201, $user['headers']['status-code']); $session = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ From 65b5af1b003b522f8cb90462f97ad8147df6a86c Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 25 Jun 2025 11:27:23 +0530 Subject: [PATCH 238/343] chore: fix tests --- tests/e2e/Services/Projects/ProjectsConsoleClientTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index aea1971be7..2a27587999 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -4637,7 +4637,6 @@ class ProjectsConsoleClientTest extends Scope 'failure' => 'https://example.com' ]); $this->assertEquals(400, $response['headers']['status-code']); - $this->assertStringContainsString('Invalid `success` param: URL host must be one of: localhost, appwrite.io, *.appwrite.io', $response['body']); /** Test oauth2 with devKey and now get oauth2 is disabled */ $response = $this->client->call(Client::METHOD_GET, '/account/sessions/oauth2/' . $provider, [ @@ -4660,7 +4659,6 @@ class ProjectsConsoleClientTest extends Scope 'url' => 'https://example.com', ]); $this->assertEquals(400, $response['headers']['status-code']); - $this->assertEquals('Invalid `url` param: URL host must be one of: localhost, appwrite.io, *.appwrite.io', $response['body']['message']); /** Test hostname in Magic URL with devKey */ $response = $this->client->call(Client::METHOD_POST, '/account/sessions/magic-url', [ From 789064e295566e815c759066199b71f3f6214469 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 25 Jun 2025 11:29:45 +0530 Subject: [PATCH 239/343] add: new scopes to the api. --- app/config/roles.php | 8 ++++++++ app/config/scopes.php | 18 ++++++++++++++++++ app/config/templates/function.php | 18 +++++++++--------- .../Tables/Columns/Boolean/Create.php | 2 +- .../Tables/Columns/Boolean/Update.php | 2 +- .../Tables/Columns/Datetime/Create.php | 2 +- .../Tables/Columns/Datetime/Update.php | 2 +- .../Http/Databases/Tables/Columns/Delete.php | 2 +- .../Databases/Tables/Columns/Email/Create.php | 2 +- .../Databases/Tables/Columns/Email/Update.php | 2 +- .../Databases/Tables/Columns/Enum/Create.php | 2 +- .../Databases/Tables/Columns/Enum/Update.php | 2 +- .../Databases/Tables/Columns/Float/Create.php | 2 +- .../Databases/Tables/Columns/Float/Update.php | 2 +- .../Http/Databases/Tables/Columns/Get.php | 2 +- .../Databases/Tables/Columns/IP/Create.php | 2 +- .../Databases/Tables/Columns/IP/Update.php | 2 +- .../Tables/Columns/Integer/Create.php | 2 +- .../Tables/Columns/Integer/Update.php | 2 +- .../Tables/Columns/Relationship/Create.php | 2 +- .../Tables/Columns/Relationship/Update.php | 2 +- .../Databases/Tables/Columns/String/Create.php | 2 +- .../Databases/Tables/Columns/String/Update.php | 2 +- .../Databases/Tables/Columns/URL/Create.php | 2 +- .../Databases/Tables/Columns/URL/Update.php | 2 +- .../Http/Databases/Tables/Columns/XList.php | 2 +- .../Databases/Http/Databases/Tables/Create.php | 2 +- .../Databases/Http/Databases/Tables/Delete.php | 2 +- .../Databases/Http/Databases/Tables/Get.php | 2 +- .../Http/Databases/Tables/Indexes/Create.php | 2 +- .../Http/Databases/Tables/Indexes/Delete.php | 2 +- .../Http/Databases/Tables/Indexes/Get.php | 2 +- .../Http/Databases/Tables/Indexes/XList.php | 2 +- .../Http/Databases/Tables/Logs/XList.php | 2 +- .../Http/Databases/Tables/Rows/Bulk/Delete.php | 2 +- .../Http/Databases/Tables/Rows/Bulk/Update.php | 2 +- .../Http/Databases/Tables/Rows/Bulk/Upsert.php | 2 +- .../Databases/Tables/Rows/Column/Decrement.php | 2 +- .../Databases/Tables/Rows/Column/Increment.php | 2 +- .../Http/Databases/Tables/Rows/Create.php | 2 +- .../Http/Databases/Tables/Rows/Delete.php | 2 +- .../Http/Databases/Tables/Rows/Get.php | 2 +- .../Http/Databases/Tables/Rows/Logs/XList.php | 2 +- .../Http/Databases/Tables/Rows/Update.php | 2 +- .../Http/Databases/Tables/Rows/Upsert.php | 2 +- .../Http/Databases/Tables/Rows/XList.php | 2 +- .../Databases/Http/Databases/Tables/Update.php | 2 +- .../Http/Databases/Tables/Usage/Get.php | 2 +- .../Databases/Http/Databases/Tables/XList.php | 2 +- tests/e2e/Scopes/ProjectCustom.php | 4 ++++ 50 files changed, 85 insertions(+), 55 deletions(-) diff --git a/app/config/roles.php b/app/config/roles.php index bccc2837f5..4b06e0a6c1 100644 --- a/app/config/roles.php +++ b/app/config/roles.php @@ -14,6 +14,8 @@ $member = [ 'teams.write', 'documents.read', 'documents.write', + 'rows.read', + 'rows.write', 'files.read', 'files.write', 'projects.read', @@ -37,6 +39,8 @@ $admins = [ 'teams.write', 'documents.read', 'documents.write', + 'rows.read', + 'rows.write', 'files.read', 'files.write', 'buckets.read', @@ -47,6 +51,8 @@ $admins = [ 'databases.write', 'collections.read', 'collections.write', + 'tables.read', + 'tables.write', 'platforms.read', 'platforms.write', 'projects.write', @@ -97,6 +103,8 @@ return [ 'sessions.write', 'documents.read', 'documents.write', + 'rows.read', + 'rows.write', 'files.read', 'files.write', 'locale.read', diff --git a/app/config/scopes.php b/app/config/scopes.php index 7dea7b1cd5..d90ca2eabf 100644 --- a/app/config/scopes.php +++ b/app/config/scopes.php @@ -28,12 +28,24 @@ return [ // List of publicly visible scopes 'collections.write' => [ 'description' => 'Access to create, update, and delete your project\'s database collections', ], + 'tables.read' => [ + 'description' => 'Access to read your project\'s database tables', + ], + 'tables.write' => [ + 'description' => 'Access to create, update, and delete your project\'s database tables', + ], 'attributes.read' => [ 'description' => 'Access to read your project\'s database collection\'s attributes', ], 'attributes.write' => [ 'description' => 'Access to create, update, and delete your project\'s database collection\'s attributes', ], + 'columns.read' => [ + 'description' => 'Access to read your project\'s database table\'s columns', + ], + 'columns.write' => [ + 'description' => 'Access to create, update, and delete your project\'s database table\'s columns', + ], 'indexes.read' => [ 'description' => 'Access to read your project\'s database collection\'s indexes', ], @@ -46,6 +58,12 @@ return [ // List of publicly visible scopes 'documents.write' => [ 'description' => 'Access to create, update, and delete your project\'s database documents', ], + 'rows.read' => [ + 'description' => 'Access to read your project\'s database rows', + ], + 'rows.write' => [ + 'description' => 'Access to create, update, and delete your project\'s database rows', + ], 'files.read' => [ 'description' => 'Access to read your project\'s storage files and preview images', ], diff --git a/app/config/templates/function.php b/app/config/templates/function.php index 960bc1d65e..9a905c83b1 100644 --- a/app/config/templates/function.php +++ b/app/config/templates/function.php @@ -635,7 +635,7 @@ return [ 'type' => 'url' ] ], - 'scopes' => ['databases.read', 'databases.write', 'collections.write', 'attributes.write', 'documents.read', 'documents.write'] + 'scopes' => ['databases.read', 'databases.write', 'collections.write', 'tables.write', 'attributes.write', 'columns.write', 'documents.read', 'rows.read', 'documents.write', 'rows.write'] ], [ 'icon' => 'icon-algolia', @@ -717,7 +717,7 @@ return [ 'type' => 'password' ], ], - 'scopes' => ['databases.read', 'collections.read', 'documents.read'] + 'scopes' => ['databases.read', 'collections.read', 'tables.read', 'documents.read', 'rows.read'] ], [ 'icon' => 'icon-meilisearch', @@ -811,7 +811,7 @@ return [ 'type' => 'text' ], ], - 'scopes' => ['databases.read', 'collections.read', 'documents.read'] + 'scopes' => ['databases.read', 'collections.read', 'tables.read', 'documents.read', 'rows.read'] ], [ 'icon' => 'icon-vonage', @@ -1139,7 +1139,7 @@ return [ 'type' => 'text' ] ], - 'scopes' => ['databases.read', 'databases.write', 'collections.write', 'attributes.write', 'documents.read', 'documents.write'] + 'scopes' => ['databases.read', 'databases.write', 'collections.write', 'tables.write', 'attributes.write', 'columns.write', 'documents.read', 'rows.read', 'documents.write', 'rows.write'] ], [ 'icon' => 'icon-chat', @@ -1268,7 +1268,7 @@ return [ 'type' => 'password' ] ], - 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.write', 'documents.read', 'documents.write', 'buckets.read', 'buckets.write', 'files.read'] + 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'tables.read', 'collections.write', 'tables.write', 'attributes.write', 'columns.write', 'documents.read', 'rows.read', 'documents.write', 'rows.write', 'buckets.read', 'buckets.write', 'files.read'] ], [ 'icon' => 'icon-eye', @@ -1327,7 +1327,7 @@ return [ 'type' => 'password' ] ], - 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.write', 'documents.read', 'documents.write', 'buckets.read', 'buckets.write', 'files.read'] + 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'tables.read', 'collections.write', 'tables.write', 'attributes.write', 'columns.write', 'documents.read', 'rows.read', 'documents.write', 'rows.write', 'buckets.read', 'buckets.write', 'files.read'] ], [ 'icon' => 'icon-text', @@ -1386,7 +1386,7 @@ return [ 'type' => 'password' ] ], - 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'collections.write', 'attributes.write', 'documents.read', 'documents.write', 'buckets.read', 'buckets.write', 'files.read'] + 'scopes' => ['databases.read', 'databases.write', 'collections.read', 'tables.read', 'collections.write', 'tables.write', 'attributes.write', 'columns.write', 'documents.read', 'rows.read', 'documents.write', 'rows.write', 'buckets.read', 'buckets.write', 'files.read'] ], [ 'icon' => 'icon-chat', @@ -1669,7 +1669,7 @@ return [ 'type' => 'text' ] ], - 'scopes' => ['databases.read', 'collections.read', 'documents.read'] + 'scopes' => ['databases.read', 'collections.read', 'tables.read', 'documents.read', 'rows.read'] ], [ 'icon' => 'icon-chip', @@ -1733,7 +1733,7 @@ return [ 'type' => 'text' ] ], - 'scopes' => ['databases.read', 'collections.read', 'documents.read'] + 'scopes' => ['databases.read', 'collections.read', 'tables.read', 'documents.read', 'rows.read'] ], [ 'icon' => 'icon-chat', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php index 9e65e6e5b3..30972e8458 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Create.php @@ -32,7 +32,7 @@ class Create extends BooleanCreate ->desc('Create boolean column') ->groups(['api', 'database', 'schema']) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php index f7eff81ae3..82e7d9526d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Boolean/Update.php @@ -33,7 +33,7 @@ class Update extends BooleanUpdate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/boolean/:key') ->desc('Update boolean column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') ->label('audits.event', 'column.update') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php index 5bb83733a4..44e9cf9cd3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Create.php @@ -33,7 +33,7 @@ class Create extends DatetimeCreate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/datetime') ->desc('Create datetime column') ->groups(['api', 'database']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('audits.event', 'column.create') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php index 6710f76aaa..27f5f3e82b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Datetime/Update.php @@ -35,7 +35,7 @@ class Update extends DatetimeUpdate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/datetime/:key') ->desc('Update dateTime column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') ->label('audits.event', 'column.update') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php index b85248e8c3..ce3e66a85f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Delete.php @@ -32,7 +32,7 @@ class Delete extends AttributesDelete ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key') ->desc('Delete column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') ->label('audits.event', 'column.delete') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php index 6aade1aa50..c497b9d78c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Create.php @@ -32,7 +32,7 @@ class Create extends EmailCreate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/email') ->desc('Create email column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('audits.event', 'column.create') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php index 10213c87bb..267d5b80e7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Email/Update.php @@ -34,7 +34,7 @@ class Update extends EmailUpdate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/email/:key') ->desc('Update email column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') ->label('audits.event', 'column.update') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php index 8e9a658aa8..38b7ac231a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Create.php @@ -34,7 +34,7 @@ class Create extends EnumCreate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/enum') ->desc('Create enum column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('audits.event', 'column.create') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php index d1418e5144..97785b1121 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Enum/Update.php @@ -36,7 +36,7 @@ class Update extends EnumUpdate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/enum/:key') ->desc('Update enum column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') ->label('audits.event', 'column.update') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php index 5c99b90f52..4a96165b32 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Create.php @@ -32,7 +32,7 @@ class Create extends FloatCreate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/float') ->desc('Create float column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('audits.event', 'column.create') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php index 5360ca0304..d570ce4857 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Float/Update.php @@ -34,7 +34,7 @@ class Update extends FloatUpdate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/float/:key') ->desc('Update float column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') ->label('audits.event', 'column.update') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php index 17777409d2..85ac43b63d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Get.php @@ -41,7 +41,7 @@ class Get extends AttributesGet ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key') ->desc('Get column') ->groups(['api', 'database']) - ->label('scope', 'collections.read') + ->label('scope', 'tables.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: $this->getSdkNamespace(), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php index cb58a14cbe..874c0f2132 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Create.php @@ -32,7 +32,7 @@ class Create extends IPCreate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/ip') ->desc('Create IP address column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('audits.event', 'column.create') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php index ef4c62a51f..73a73bccac 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/IP/Update.php @@ -34,7 +34,7 @@ class Update extends IPUpdate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/ip/:key') ->desc('Update IP address column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') ->label('audits.event', 'column.update') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php index 6ca6cc4b93..11a36c1e3c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Create.php @@ -32,7 +32,7 @@ class Create extends IntegerCreate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/integer') ->desc('Create integer column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('audits.event', 'column.create') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php index 764ae31f35..292eb3de7b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Integer/Update.php @@ -34,7 +34,7 @@ class Update extends IntegerUpdate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/integer/:key') ->desc('Update integer column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') ->label('audits.event', 'column.update') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php index 20e89396a0..583f8bb16c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Create.php @@ -33,7 +33,7 @@ class Create extends RelationshipCreate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/relationship') ->desc('Create relationship column') ->groups(['api', 'database']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('audits.event', 'column.create') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php index 508c5da57a..d17cf9def2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/Relationship/Update.php @@ -33,7 +33,7 @@ class Update extends RelationshipUpdate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/:key/relationship') ->desc('Update relationship column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') ->label('audits.event', 'column.update') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php index a11ee3464e..9d86fc8c8e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Create.php @@ -34,7 +34,7 @@ class Create extends StringCreate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/string') ->desc('Create string column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('audits.event', 'column.create') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php index 92df091866..8106ccf626 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/String/Update.php @@ -36,7 +36,7 @@ class Update extends StringUpdate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/string/:key') ->desc('Update string column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') ->label('audits.event', 'column.update') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php index 84c488ccfc..340b120c5c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Create.php @@ -32,7 +32,7 @@ class Create extends URLCreate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/url') ->desc('Create URL column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') ->label('audits.event', 'column.create') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php index d3681b9358..82ab8fa614 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/URL/Update.php @@ -34,7 +34,7 @@ class Update extends URLUpdate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns/url/:key') ->desc('Update URL column') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update') ->label('audits.event', 'column.update') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php index 8190f2ec71..b6578777b0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Columns/XList.php @@ -30,7 +30,7 @@ class XList extends AttributesXList ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/columns') ->desc('List columns') ->groups(['api', 'database']) - ->label('scope', 'collections.read') + ->label('scope', 'tables.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: $this->getSdkNamespace(), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php index 0bfdef5249..b80cf4f773 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Create.php @@ -35,7 +35,7 @@ class Create extends CollectionCreate ->desc('Create table') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].tables.[tableId].create') - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'table.create') ->label('audits.resource', 'database/{request.databaseId}/table/{response.$id}') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php index caa7197acb..2465496023 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Delete.php @@ -30,7 +30,7 @@ class Delete extends CollectionDelete ->setHttpPath('/v1/databases/:databaseId/tables/:tableId') ->desc('Delete table') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].delete') ->label('audits.event', 'table.delete') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php index 40672ba51f..dec3a879a4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Get.php @@ -30,7 +30,7 @@ class Get extends CollectionGet ->setHttpPath('/v1/databases/:databaseId/tables/:tableId') ->desc('Get table') ->groups(['api', 'database']) - ->label('scope', 'collections.read') + ->label('scope', 'tables.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: $this->getSdkNamespace(), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php index b11892e0f9..92397cd460 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Create.php @@ -37,7 +37,7 @@ class Create extends IndexCreate ->desc('Create index') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].create') - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'index.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php index 4ff9638f27..eb8e2c5833 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php @@ -35,7 +35,7 @@ class Delete extends IndexDelete ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes/:key') ->desc('Delete index') ->groups(['api', 'database']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].update') ->label('audits.event', 'index.delete') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php index 79529fda66..9a63fa79c3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Get.php @@ -31,7 +31,7 @@ class Get extends IndexGet ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes/:key') ->desc('Get index') ->groups(['api', 'database']) - ->label('scope', 'collections.read') + ->label('scope', 'tables.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: $this->getSdkNamespace(), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php index 12581a4fc3..85685cdd6c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/XList.php @@ -31,7 +31,7 @@ class XList extends IndexXList ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/indexes') ->desc('List indexes') ->groups(['api', 'database']) - ->label('scope', 'collections.read') + ->label('scope', 'tables.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: $this->getSdkNamespace(), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php index 8e652c5416..afe33597e2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php @@ -27,7 +27,7 @@ class XList extends CollectionLogXList ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/logs') ->desc('List table logs') ->groups(['api', 'database']) - ->label('scope', 'collections.read') + ->label('scope', 'tables.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php index 945450aee3..a29d73aeee 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Delete.php @@ -32,7 +32,7 @@ class Delete extends DocumentsDelete ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') ->desc('Delete rows') ->groups(['api', 'database']) - ->label('scope', 'documents.write') + ->label('scope', 'rows.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'rows.delete') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php index 916d683491..529d4b0b96 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Update.php @@ -33,7 +33,7 @@ class Update extends DocumentsUpdate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') ->desc('Update rows') ->groups(['api', 'database']) - ->label('scope', 'documents.write') + ->label('scope', 'rows.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'rows.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php index 65c848a7c4..2bda5f0172 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Bulk/Upsert.php @@ -32,7 +32,7 @@ class Upsert extends DocumentsUpsert ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') ->desc('Create or update rows') ->groups(['api', 'database']) - ->label('scope', 'documents.write') + ->label('scope', 'rows.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'row.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php index 916c051d8a..a0761f0bd2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Decrement.php @@ -33,7 +33,7 @@ class Decrement extends DecrementDocumentAttribute ->desc('Decrement row column') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].decrement') - ->label('scope', 'documents.write') + ->label('scope', 'rows.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'rows.decrement') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php index ba78833744..d28b2a3968 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Column/Increment.php @@ -33,7 +33,7 @@ class Increment extends IncrementDocumentAttribute ->desc('Increment row column') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].increment') - ->label('scope', 'documents.write') + ->label('scope', 'rows.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'rows.increment') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php index ba2b461d6e..bba4960b69 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Create.php @@ -41,7 +41,7 @@ class Create extends DocumentCreate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') ->desc('Create row') ->groups(['api', 'database']) - ->label('scope', 'documents.write') + ->label('scope', 'rows.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'row.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php index 27fe101f1d..22c25d5b16 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Delete.php @@ -36,7 +36,7 @@ class Delete extends DocumentDelete ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') ->desc('Delete row') ->groups(['api', 'database']) - ->label('scope', 'documents.write') + ->label('scope', 'rows.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].delete') ->label('audits.event', 'row.delete') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php index 8100abbea5..0266781728 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Get.php @@ -32,7 +32,7 @@ class Get extends DocumentGet ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId') ->desc('Get row') ->groups(['api', 'database']) - ->label('scope', 'documents.read') + ->label('scope', 'rows.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: $this->getSdkNamespace(), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php index f39a77323f..ad42f16f44 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Logs/XList.php @@ -27,7 +27,7 @@ class XList extends DocumentLogXList ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows/:rowId/logs') ->desc('List row logs') ->groups(['api', 'database']) - ->label('scope', 'documents.read') + ->label('scope', 'rows.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: $this->getSdkNamespace(), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php index 9fa596ecc0..15796c3b6b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Update.php @@ -34,7 +34,7 @@ class Update extends DocumentUpdate ->desc('Update row') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].update') - ->label('scope', 'documents.write') + ->label('scope', 'rows.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'row.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}/row/{response.$id}') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php index 5c0fde708b..42a79e8a72 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/Upsert.php @@ -34,7 +34,7 @@ class Upsert extends DocumentUpsert ->desc('Create or update a row') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].upsert') - ->label('scope', 'documents.write') + ->label('scope', 'rows.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'row.upsert') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}/row/{response.$id}') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php index b7ad763e36..7e942f4842 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Rows/XList.php @@ -32,7 +32,7 @@ class XList extends DocumentXList ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/rows') ->desc('List rows') ->groups(['api', 'database']) - ->label('scope', 'documents.read') + ->label('scope', 'rows.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: $this->getSdkNamespace(), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php index f800e7b1de..b19dc143b9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php @@ -33,7 +33,7 @@ class Update extends CollectionUpdate ->setHttpPath('/v1/databases/:databaseId/tables/:tableId') ->desc('Update table') ->groups(['api', 'database', 'schema']) - ->label('scope', 'collections.write') + ->label('scope', 'tables.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('event', 'databases.[databaseId].tables.[tableId].update') ->label('audits.event', 'table.update') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php index ca990eeab6..cede0762d8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Usage/Get.php @@ -31,7 +31,7 @@ class Get extends CollectionUsageGet ->setHttpPath('/v1/databases/:databaseId/tables/:tableId/usage') ->desc('Get table usage stats') ->groups(['api', 'database', 'usage']) - ->label('scope', 'collections.read') + ->label('scope', 'tables.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: $this->getSdkNamespace(), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php index 34000d97b1..24034f7f0a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/XList.php @@ -32,7 +32,7 @@ class XList extends CollectionXList ->setHttpPath('/v1/databases/:databaseId/tables') ->desc('List tables') ->groups(['api', 'database']) - ->label('scope', 'collections.read') + ->label('scope', 'tables.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: $this->getSdkNamespace(), diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index 51aebeaef7..ea27318390 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -70,8 +70,12 @@ trait ProjectCustom 'databases.write', 'collections.read', 'collections.write', + 'tables.read', + 'tables.write', 'documents.read', 'documents.write', + 'rows.read', + 'rows.write', 'files.read', 'files.write', 'buckets.read', From 1a9664a679ab1f8cc7bb7a29e4ec55968ee57ee7 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 25 Jun 2025 11:43:18 +0530 Subject: [PATCH 240/343] chore: fix benchmark --- .github/workflows/benchmark.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 6d73787d00..f1051497a8 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -65,7 +65,7 @@ jobs: sudo apt update sudo apt install oha - name: Benchmark PR - run: 'oha -z 180s http://localhost/v1/health/version -j > benchmark.json' + run: 'oha -z 180s http://localhost/v1/health/version --output-format json > benchmark.json' - name: Cleaning run: docker compose down -v - name: Installing latest version @@ -78,7 +78,7 @@ jobs: docker compose up -d sleep 10 - name: Benchmark Latest - run: oha -z 180s http://localhost/v1/health/version -j > benchmark-latest.json + run: oha -z 180s http://localhost/v1/health/version --output-format json > benchmark-latest.json - name: Prepare comment run: | echo '## :sparkles: Benchmark results' > benchmark.txt From d7d8dbdbd47c1b0788c13232f9e264bfd045dcb6 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 25 Jun 2025 11:53:21 +0530 Subject: [PATCH 241/343] fix: name. --- .../Modules/Databases/Http/Databases/Tables/Indexes/Delete.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php index eb8e2c5833..0fec37eec3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Indexes/Delete.php @@ -16,7 +16,7 @@ class Delete extends IndexDelete { public static function getName(): string { - return 'updateColumnIndex'; + return 'deleteColumnIndex'; } /** From 4b1966997b3389787b75478ba826fb68e40e5a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 25 Jun 2025 10:30:07 +0200 Subject: [PATCH 242/343] Fix build duration calculation --- .../Modules/Functions/Workers/Builds.php | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 8ff1690da9..3d2b42346d 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -209,6 +209,9 @@ class Builds extends Action Executor $executor, array $plan ): void { + $startTime = DateTime::now(); + $durationStart = \microtime(true); + $resourceKey = match ($resource->getCollection()) { 'functions' => 'functionId', 'sites' => 'siteId', @@ -260,9 +263,6 @@ class Builds extends Action ->setParam($resourceKey, $resource->getId()) ->setParam('deploymentId', $deployment->getId()); - $startTime = DateTime::now(); - $durationStart = \microtime(true); - if ($deployment->getAttribute('status') === 'canceled') { Console::info('Build has been canceled'); return; @@ -810,9 +810,6 @@ class Builds extends Action throw $err; } - $endTime = DateTime::now(); - $durationEnd = \microtime(true); - $buildSizeLimit = (int)System::getEnv('_APP_COMPUTE_BUILD_SIZE_LIMIT', '2000000000'); if (isset($plan['buildSize'])) { $buildSizeLimit = $plan['buildSize'] * 1000 * 1000; @@ -821,10 +818,6 @@ class Builds extends Action throw new \Exception('Build size should be less than ' . number_format($buildSizeLimit / (1000 * 1000), 2) . ' MBs.'); } - /** Update the build document */ - $deployment->setAttribute('buildStartedAt', DateTime::format((new \DateTime())->setTimestamp(floor($response['startTime'])))); - $deployment->setAttribute('buildEndedAt', $endTime); - $deployment->setAttribute('buildDuration', \intval(\ceil($durationEnd - $durationStart))); $deployment->setAttribute('buildPath', $response['path']); $deployment->setAttribute('buildSize', $response['size']); $deployment->setAttribute('totalSize', $deployment->getAttribute('buildSize', 0) + $deployment->getAttribute('sourceSize', 0)); @@ -1191,6 +1184,15 @@ class Builds extends Action } } + $endTime = DateTime::now(); + $durationEnd = \microtime(true); + $deployment->setAttribute('buildEndedAt', $endTime); + $deployment->setAttribute('buildDuration', \intval(\ceil($durationEnd - $durationStart))); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') { Console::info('Build has been canceled'); return; From 17428ef433dc3c8453bc392e53a759644bc917d9 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 25 Jun 2025 14:18:22 +0400 Subject: [PATCH 243/343] refactor: replace Console loop with Swoole Timer for stats resource management --- src/Appwrite/Platform/Tasks/StatsResources.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index a0b5056b0f..eb707835e5 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -4,6 +4,7 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Event\StatsResources as EventStatsResources; use Appwrite\Platform\Action; +use Swoole\Timer; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; @@ -58,7 +59,7 @@ class StatsResources extends Action Console::success('Stats resources: started'); $interval = (int) System::getEnv('_APP_STATS_RESOURCES_INTERVAL', '3600'); - Console::loop(function () use ($queue) { + Timer::tick($interval, function () use ($queue) { Authorization::disable(); Authorization::setDefaultStatus(false); @@ -75,7 +76,7 @@ class StatsResources extends Action ->trigger(); Console::success('project: ' . $project->getId() . '(' . $project->getSequence() . ')' . ' queued'); }); - }, $interval); + }); Console::log("Stats resources: exited"); } From c268b632fb4686781a79b61e086fb2ef1679ff22 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 25 Jun 2025 14:52:13 +0400 Subject: [PATCH 244/343] chore: update benchmark command to use JSON output format and adjust timer interval in StatsResources --- .github/workflows/benchmark.yml | 2 +- src/Appwrite/Platform/Tasks/StatsResources.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 6d73787d00..62256a41c6 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -65,7 +65,7 @@ jobs: sudo apt update sudo apt install oha - name: Benchmark PR - run: 'oha -z 180s http://localhost/v1/health/version -j > benchmark.json' + run: 'oha -z 180s http://localhost/v1/health/version --output-format json > benchmark.json' - name: Cleaning run: docker compose down -v - name: Installing latest version diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index eb707835e5..30ed3033b6 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -59,7 +59,7 @@ class StatsResources extends Action Console::success('Stats resources: started'); $interval = (int) System::getEnv('_APP_STATS_RESOURCES_INTERVAL', '3600'); - Timer::tick($interval, function () use ($queue) { + Timer::tick($interval * 1000, function () use ($queue) { Authorization::disable(); Authorization::setDefaultStatus(false); From b6d4baf4dc40bf2deda0104734295cc3fe4da9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 25 Jun 2025 13:14:08 +0200 Subject: [PATCH 245/343] Fix tests --- .../Platform/Modules/Functions/Workers/Builds.php | 2 +- .../Services/Realtime/RealtimeConsoleClientTest.php | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 3d2b42346d..817cc58c9f 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1236,7 +1236,7 @@ class Builds extends Action // Combine with previous logs if deployment got past build process $previousLogs = ''; - if (!empty($deployment->getAttribute('buildEndedAt', ''))) { + if (!is_null($deployment->getAttribute('buildSize', null))) { $previousLogs = $deployment->getAttribute('buildLogs', ''); if (!empty($previousLogs)) { $message = $previousLogs . "\n" . $message; diff --git a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php index ba2d18694a..1f60f9fde6 100644 --- a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php @@ -607,10 +607,8 @@ class RealtimeConsoleClientTest extends Scope $this->assertContains("projects.{$projectId}", $response['data']['channels']); $this->assertArrayHasKey('buildLogs', $response['data']['payload']); - if (!empty($response['data']['payload']['buildEndedAt'])) { - $this->assertNotEmpty($response['data']['payload']['buildEndedAt']); + if (!empty($response['data']['payload']['buildSize'])) { $this->assertNotEmpty($response['data']['payload']['buildStartedAt']); - $this->assertNotEmpty($response['data']['payload']['buildDuration']); $this->assertNotEmpty($response['data']['payload']['buildPath']); $this->assertNotEmpty($response['data']['payload']['buildSize']); $this->assertNotEmpty($response['data']['payload']['totalSize']); @@ -634,6 +632,13 @@ class RealtimeConsoleClientTest extends Scope $this->assertContains("projects.{$projectId}", $response['data']['channels']); $this->assertEquals("ready", $response['data']['payload']['status']); + $response = json_decode($client->receive(), true); + $this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.update", $response['data']['events']); + $this->assertContains('console', $response['data']['channels']); + $this->assertContains("projects.{$projectId}", $response['data']['channels']); + $this->assertNotEmpty($response['data']['payload']['buildDuration']); + $this->assertNotEmpty($response['data']['payload']['buildEndedAt']); + $client->close(); } } From 347f035105160c4682c58e85e33cbd1329f14e76 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 25 Jun 2025 15:27:51 +0400 Subject: [PATCH 246/343] chore: fix benchmark CI --- .github/workflows/benchmark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 6d73787d00..6726f7b48f 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -65,7 +65,7 @@ jobs: sudo apt update sudo apt install oha - name: Benchmark PR - run: 'oha -z 180s http://localhost/v1/health/version -j > benchmark.json' + run: 'oha -z 180s http://localhost/v1/health/version --output_format json > benchmark.json' - name: Cleaning run: docker compose down -v - name: Installing latest version From 93651c776e178a18f94542d474b01a380aa2a911 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 25 Jun 2025 15:32:19 +0400 Subject: [PATCH 247/343] chore: fix benchmark CI --- .github/workflows/benchmark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 6726f7b48f..562f2223f3 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -78,7 +78,7 @@ jobs: docker compose up -d sleep 10 - name: Benchmark Latest - run: oha -z 180s http://localhost/v1/health/version -j > benchmark-latest.json + run: oha -z 180s http://localhost/v1/health/version --output_format json > benchmark-latest.json - name: Prepare comment run: | echo '## :sparkles: Benchmark results' > benchmark.txt From bce666e81b8fceb418a6a1a7e770f126368c388d Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 25 Jun 2025 17:02:21 +0530 Subject: [PATCH 248/343] add: scopes on migrations and update tests. --- src/Appwrite/Platform/Workers/Migrations.php | 3 +++ tests/e2e/Services/Projects/ProjectsConsoleClientTest.php | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index b59308c288..66f45004ea 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -246,8 +246,11 @@ class Migrations extends Action 'functions.write', 'databases.read', 'collections.read', + 'tables.read', 'documents.read', 'documents.write', + 'rows.read', + 'rows.write', 'tokens.read', 'tokens.write', ] diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 8b34d552f5..5e22a28016 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -2991,7 +2991,7 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'name' => 'Key Test Update', - 'scopes' => ['users.read', 'users.write', 'collections.read'], + 'scopes' => ['users.read', 'users.write', 'collections.read', 'tables.read'], 'expire' => DateTime::addSeconds(new \DateTime(), 360), ]); @@ -3002,6 +3002,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertContains('users.read', $response['body']['scopes']); $this->assertContains('users.write', $response['body']['scopes']); $this->assertContains('collections.read', $response['body']['scopes']); + $this->assertContains('tables.read', $response['body']['scopes']); $this->assertCount(3, $response['body']['scopes']); $this->assertArrayHasKey('sdks', $response['body']); $this->assertEmpty($response['body']['sdks']); @@ -3020,6 +3021,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertContains('users.read', $response['body']['scopes']); $this->assertContains('users.write', $response['body']['scopes']); $this->assertContains('collections.read', $response['body']['scopes']); + $this->assertContains('tables.read', $response['body']['scopes']); $this->assertCount(3, $response['body']['scopes']); $this->assertArrayHasKey('sdks', $response['body']); $this->assertEmpty($response['body']['sdks']); From 56347e42dfa210885c189e179f4f2c8ac98f917d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 25 Jun 2025 14:20:20 +0200 Subject: [PATCH 249/343] Fix syntax bug --- src/Appwrite/Platform/Modules/Functions/Workers/Builds.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index a7528634f0..105db89fe7 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1234,8 +1234,8 @@ class Builds extends Action $message = "" . $message; } - $message = \str_replace('{APPWRITE_DETECTION_SEPARATOR_START}', '', $message, 1); - $message = \str_replace('{APPWRITE_DETECTION_SEPARATOR_END}', '', $message, 1); + $message = \str_replace('{APPWRITE_DETECTION_SEPARATOR_START}', '', $message); + $message = \str_replace('{APPWRITE_DETECTION_SEPARATOR_END}', '', $message); // Combine with previous logs if deployment got past build process $previousLogs = ''; From 67e546faa8d0bb6f4443a25a3ce2c246344f9289 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 25 Jun 2025 17:50:54 +0530 Subject: [PATCH 250/343] fix: namespace for table logs. --- .../Modules/Databases/Http/Databases/Tables/Logs/XList.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php index afe33597e2..d18cae9d6d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Logs/XList.php @@ -30,9 +30,9 @@ class XList extends CollectionLogXList ->label('scope', 'tables.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: 'databases', + namespace: $this->getSdkNamespace(), group: $this->getSdkGroup(), - name: self::getName(), + name: 'listLogs', // getName needs to be different from parent action to avoid conflict in path name description: '/docs/references/databases/get-collection-logs.md', auth: [AuthType::ADMIN], responses: [ From df82340daebd23bdb5c0c1931cf3a7793154bdc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 25 Jun 2025 14:22:55 +0200 Subject: [PATCH 251/343] Improve code quality --- app/init/resources.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/app/init/resources.php b/app/init/resources.php index 18203869df..aa04b46e1f 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -952,17 +952,20 @@ App::setResource('httpReferrer', function (Request $request): string { App::setResource('httpReferrerSafe', function (Request $request, string $httpReferrer, array $clients, Database $dbForPlatform, Document $project, App $utopia): string { $origin = \parse_url($request->getOrigin($httpReferrer), PHP_URL_HOST); + $protocol = \parse_url($request->getOrigin($httpReferrer), PHP_URL_SCHEME); + $port = \parse_url($request->getOrigin($httpReferrer), PHP_URL_PORT); + $referrer = (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $origin . (!empty($port) ? ':' . $port : ''); // Safe if route is publicly accessible $route = $utopia->getRoute(); if ($route->getLabel('origin', false)) { - goto originToUrl; + return $referrer; } // Safe if added as web platform $validator = new Hostname($clients); if ($validator->isValid($origin)) { - goto originToUrl; + return $referrer; } // Safe if rule with same project ID exists @@ -979,19 +982,14 @@ App::setResource('httpReferrerSafe', function (Request $request, string $httpRef } if (!$rule->isEmpty() && $rule->getAttribute('projectInternalId') === $project->getSequence()) { - goto originToUrl; + return $referrer; } } // Unsafe; Localhost is always safe for ease of local development $origin = 'localhost'; - - originToUrl: - $protocol = \parse_url($request->getOrigin($httpReferrer), PHP_URL_SCHEME); $port = \parse_url($request->getOrigin($httpReferrer), PHP_URL_PORT); - $referrer = (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $origin . (!empty($port) ? ':' . $port : ''); - return $referrer; }, ['request', 'httpReferrer', 'clients', 'dbForPlatform', 'project', 'utopia']); From f1590652cbe63085bfc2449898cefd242d6dbc8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 25 Jun 2025 14:30:50 +0200 Subject: [PATCH 252/343] Improve benchmark logging --- .github/workflows/benchmark.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 6d73787d00..f9e86ce332 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -64,6 +64,7 @@ jobs: sudo wget -O /usr/share/keyrings/azlux-archive-keyring.gpg https://azlux.fr/repo.gpg sudo apt update sudo apt install oha + oha --version - name: Benchmark PR run: 'oha -z 180s http://localhost/v1/health/version -j > benchmark.json' - name: Cleaning From 4fff9b94f86daa378cd21317c90b52a45a862e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 25 Jun 2025 14:45:58 +0200 Subject: [PATCH 253/343] Fix benchmark param name --- .github/workflows/benchmark.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 2758eed90e..62b4953e27 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -66,7 +66,7 @@ jobs: sudo apt install oha oha --version - name: Benchmark PR - run: 'oha -z 180s http://localhost/v1/health/version --output_format json > benchmark.json' + run: 'oha -z 180s http://localhost/v1/health/version --output-format json > benchmark.json' - name: Cleaning run: docker compose down -v - name: Installing latest version @@ -79,7 +79,7 @@ jobs: docker compose up -d sleep 10 - name: Benchmark Latest - run: oha -z 180s http://localhost/v1/health/version --output_format json > benchmark-latest.json + run: oha -z 180s http://localhost/v1/health/version --output-format json > benchmark-latest.json - name: Prepare comment run: | echo '## :sparkles: Benchmark results' > benchmark.txt From c85cfe132e30803a6d5ca47428215d3c5128d2a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 25 Jun 2025 15:53:59 +0200 Subject: [PATCH 254/343] Improve flaky tests logging --- tests/e2e/Services/Account/AccountCustomClientTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index f9da3f73cf..86c78d5d81 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -2421,7 +2421,7 @@ class AccountCustomClientTest extends Scope $smsRequest = $this->assertLastRequest(function ($request) { $this->assertArrayHasKey('data', $request); - $this->assertArrayHasKey('message', $request['data']); + $this->assertArrayHasKey('message', $request['data'], "Last request missing message: " . \json_encode($request)); }); /** From 3cd31e2c069a52a9a3f64021efdb209c85f03b6a Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 25 Jun 2025 21:46:15 +0400 Subject: [PATCH 255/343] Add disableSubqueries method to Action class and integrate it into StatsResources initialization --- src/Appwrite/Platform/Action.php | 21 +++++++++++++++++++ .../Platform/Tasks/StatsResources.php | 8 ++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Platform/Action.php b/src/Appwrite/Platform/Action.php index 72c41582ea..cd06df74fe 100644 --- a/src/Appwrite/Platform/Action.php +++ b/src/Appwrite/Platform/Action.php @@ -87,4 +87,25 @@ class Action extends UtopiaAction $latestDocument = $results[array_key_last($results)]; } } + + public function disableSubqueries() + { + $filters = [ + 'subQueryKeys', 'subQueryWebhooks', 'subQueryPlatforms', 'subQueryProjectVariables', 'subQueryBlocks', 'subQueryDevKeys', // Project + 'subQueryAuthenticators', 'subQuerySessions', 'subQueryTokens', 'subQueryChallenges', 'subQueryMemberships', 'subQueryTargets', 'subQueryTopicTargets',// Users + 'subQueryVariables', // Sites + ]; + + foreach ($filters as $filter) { + Database::addFilter( + $filter, + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return []; + } + ); + } + } } diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index 0610dd0df6..b64dd61f86 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -4,7 +4,6 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Event\StatsResources as EventStatsResources; use Appwrite\Platform\Action; -use Swoole\Timer; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; @@ -54,12 +53,15 @@ class StatsResources extends Action $this->logError = $logError; $this->dbForPlatform = $dbForPlatform; + $this->disableSubqueries(); + Console::title("Stats resources V1"); Console::success('Stats resources: started'); $interval = (int) System::getEnv('_APP_STATS_RESOURCES_INTERVAL', '3600'); - Timer::tick($interval * 1000, function () use ($queue) { + + Console::loop(function () use ($queue) { Authorization::disable(); Authorization::setDefaultStatus(false); @@ -76,7 +78,7 @@ class StatsResources extends Action ->trigger(); Console::success('project: ' . $project->getId() . '(' . $project->getSequence() . ')' . ' queued'); }); - }); + }, $interval); Console::log("Stats resources: exited"); } From c479a11850934a4c8d01875cd0f8e79e2822afe7 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 25 Jun 2025 21:56:30 +0400 Subject: [PATCH 256/343] Add logging functionality to Action class with dump method and refactor disableSubqueries to use class filters --- src/Appwrite/Platform/Action.php | 38 +++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Action.php b/src/Appwrite/Platform/Action.php index cd06df74fe..96444f9144 100644 --- a/src/Appwrite/Platform/Action.php +++ b/src/Appwrite/Platform/Action.php @@ -3,7 +3,10 @@ namespace Appwrite\Platform; use Swoole\Coroutine as Co; +use Utopia\CLI\Console; use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Document; use Utopia\Database\Query; use Utopia\Platform\Action as UtopiaAction; @@ -16,6 +19,12 @@ class Action extends UtopiaAction */ protected mixed $logError; + protected array $filters = [ + 'subQueryKeys', 'subQueryWebhooks', 'subQueryPlatforms', 'subQueryProjectVariables', 'subQueryBlocks', 'subQueryDevKeys', // Project + 'subQueryAuthenticators', 'subQuerySessions', 'subQueryTokens', 'subQueryChallenges', 'subQueryMemberships', 'subQueryTargets', 'subQueryTopicTargets',// Users + 'subQueryVariables', // Sites + ]; + /** * Foreach Document * Call provided callback for each document in the collection @@ -90,11 +99,7 @@ class Action extends UtopiaAction public function disableSubqueries() { - $filters = [ - 'subQueryKeys', 'subQueryWebhooks', 'subQueryPlatforms', 'subQueryProjectVariables', 'subQueryBlocks', 'subQueryDevKeys', // Project - 'subQueryAuthenticators', 'subQuerySessions', 'subQueryTokens', 'subQueryChallenges', 'subQueryMemberships', 'subQueryTargets', 'subQueryTopicTargets',// Users - 'subQueryVariables', // Sites - ]; + $filters = $this->filters; foreach ($filters as $filter) { Database::addFilter( @@ -108,4 +113,27 @@ class Action extends UtopiaAction ); } } + + public function dump(string $method, string $log, string $type = 'info', ?Document $project = null, string $collectionId = '') + { + if (empty($project)) { + $project = new Document([]); + } + switch ($type) { + case 'success': + Console::success("[" . DateTime::now() . "] " . $method . ' ' . $type . ' ' . $project->getSequence() . ' ' . $project->getId() . ' ' . $collectionId . ' ' . $log); + break; + case 'error': + Console::error("[" . DateTime::now() . "] " . $method . ' ' . $type . ' ' . $project->getSequence() . ' ' . $project->getId() . ' ' . $collectionId . ' ' . $log); + break; + case 'log': + Console::log("[" . DateTime::now() . "] " . $method . ' ' . $type . ' ' . $project->getSequence() . ' ' . $project->getId() . ' ' . $collectionId . ' ' . $log); + break; + case 'warning': + Console::warning("[" . DateTime::now() . "] " . $method . ' ' . $type . ' ' . $project->getSequence() . ' ' . $project->getId() . ' ' . $collectionId . ' ' . $log); + break; + default: + Console::info("[" . DateTime::now() . "] " . $method . ' ' . $type . ' ' . $project->getSequence() . ' ' . $project->getId() . ' ' . $collectionId . ' ' . $log); + } + } } From 92a04535ac41b5398821efeeb03d4fcd921787a7 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 25 Jun 2025 14:35:17 -0400 Subject: [PATCH 257/343] Add database worker job logging --- src/Appwrite/Platform/Workers/Databases.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 37f1c3212a..fb0a4497aa 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -4,6 +4,7 @@ namespace Appwrite\Platform\Workers; use Appwrite\Event\Realtime; use Exception; +use Swoole\Timer; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Document; @@ -39,6 +40,10 @@ class Databases extends Action ->inject('queueForRealtime') ->inject('log') ->callback($this->action(...)); + + Timer::tick(10_000, function () { + Console::info('Databases worker heartbeat'); + }); } /** @@ -64,6 +69,14 @@ class Databases extends Action $document = new Document($payload['document'] ?? []); $database = new Document($payload['database'] ?? []); + Console::info("Processing database operation: \n" . \json_encode([ + 'type' => $type, + 'projectId' => $project->getId(), + 'databaseId' => $database->getId(), + 'collectionId' => $collection->getId(), + 'documentId' => $document->getId(), + ], JSON_PRETTY_PRINT)); + $log->addTag('projectId', $project->getId()); $log->addTag('type', $type); @@ -82,6 +95,14 @@ class Databases extends Action DATABASE_TYPE_DELETE_INDEX => $this->deleteIndex($database, $collection, $document, $project, $dbForPlatform, $dbForProject, $queueForRealtime), default => throw new Exception('No database operation for type: ' . \strval($type)), }; + + Console::info("Finished processing database operation: \n" . \json_encode([ + 'type' => $type, + 'projectId' => $project->getId(), + 'databaseId' => $database->getId(), + 'collectionId' => $collection->getId(), + 'documentId' => $document->getId(), + ], JSON_PRETTY_PRINT)); } /** From d7d7fa3096140819d60122394cb4795528ec780c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 25 Jun 2025 14:47:23 -0400 Subject: [PATCH 258/343] Add trigger logging --- app/controllers/shared/api.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index f99ebbce07..772b83fff5 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -22,6 +22,7 @@ use Utopia\Abuse\Abuse; use Utopia\App; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; +use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; @@ -797,6 +798,10 @@ App::shutdown() } if (!empty($queueForDatabase->getType())) { + Console::info("Triggering database event: \n" . \json_encode([ + 'type' => $queueForDatabase->getType(), + 'project' => $project->getId(), + ])); $queueForDatabase->trigger(); } From e37cea514658b1107b84c53dc33e0f3921baf19f Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 25 Jun 2025 14:50:29 -0400 Subject: [PATCH 259/343] Add more trigger logging --- app/controllers/shared/api.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 772b83fff5..fd2536805d 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -799,8 +799,10 @@ App::shutdown() if (!empty($queueForDatabase->getType())) { Console::info("Triggering database event: \n" . \json_encode([ - 'type' => $queueForDatabase->getType(), - 'project' => $project->getId(), + 'projectId' => $project->getId(), + 'databaseId' => $queueForDatabase->getDatabase()->getId(), + 'collectionId' => $queueForDatabase->getCollection()->getId(), + 'documentId' => $queueForDatabase->getDocument()->getId(), ])); $queueForDatabase->trigger(); } From 255be3babf920921a58d42b1a3931cb2a22cb978 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 25 Jun 2025 14:52:14 -0400 Subject: [PATCH 260/343] Ensure heartbeat is cleared on destruct --- src/Appwrite/Event/Database.php | 10 ++++++++++ src/Appwrite/Platform/Workers/Databases.php | 13 ++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Event/Database.php b/src/Appwrite/Event/Database.php index d2f70dddf2..838870345a 100644 --- a/src/Appwrite/Event/Database.php +++ b/src/Appwrite/Event/Database.php @@ -54,6 +54,16 @@ class Database extends Event return $this; } + /** + * Returns set database for this event. + * + * @return null|Document + */ + public function getDatabase(): ?Document + { + return $this->database; + } + /** * Set the collection for this database event. * diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index fb0a4497aa..0ba55ad97f 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -21,6 +21,8 @@ use Utopia\Queue\Message; class Databases extends Action { + private ?int $heartbeatId = null; + public static function getName(): string { return 'databases'; @@ -41,11 +43,19 @@ class Databases extends Action ->inject('log') ->callback($this->action(...)); - Timer::tick(10_000, function () { + $this->heartbeatId = Timer::tick(10_000, function () { Console::info('Databases worker heartbeat'); }); } + public function __destruct() + { + if ($this->heartbeatId) { + Timer::clear($this->heartbeatId); + $this->heartbeatId = null; + } + } + /** * @param Message $message * @param Document $project @@ -137,6 +147,7 @@ class Databases extends Action $projectId = $project->getId(); $event = "databases.[databaseId].collections.[collectionId].attributes.[attributeId].update"; + /** * TODO @christyjacob4 verify if this is still the case * Fetch attribute from the database, since with Resque float values are loosing informations. From d52d8f7697879db4d87877d003c9e7553ef32da3 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 25 Jun 2025 15:47:57 -0400 Subject: [PATCH 261/343] Fix API dump --- app/controllers/shared/api.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index fd2536805d..735487339f 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -800,9 +800,9 @@ App::shutdown() if (!empty($queueForDatabase->getType())) { Console::info("Triggering database event: \n" . \json_encode([ 'projectId' => $project->getId(), - 'databaseId' => $queueForDatabase->getDatabase()->getId(), - 'collectionId' => $queueForDatabase->getCollection()->getId(), - 'documentId' => $queueForDatabase->getDocument()->getId(), + 'databaseId' => $queueForDatabase->getDatabase()?->getId(), + 'collectionId' => $queueForDatabase->getCollection()?->getId(), + 'documentId' => $queueForDatabase->getDocument()?->getId(), ])); $queueForDatabase->trigger(); } From f0ea206f2957a0b23650fddbef4762d96788117d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 25 Jun 2025 15:56:07 -0400 Subject: [PATCH 262/343] Fix bench --- .github/workflows/benchmark.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 562f2223f3..f1051497a8 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -65,7 +65,7 @@ jobs: sudo apt update sudo apt install oha - name: Benchmark PR - run: 'oha -z 180s http://localhost/v1/health/version --output_format json > benchmark.json' + run: 'oha -z 180s http://localhost/v1/health/version --output-format json > benchmark.json' - name: Cleaning run: docker compose down -v - name: Installing latest version @@ -78,7 +78,7 @@ jobs: docker compose up -d sleep 10 - name: Benchmark Latest - run: oha -z 180s http://localhost/v1/health/version --output_format json > benchmark-latest.json + run: oha -z 180s http://localhost/v1/health/version --output-format json > benchmark-latest.json - name: Prepare comment run: | echo '## :sparkles: Benchmark results' > benchmark.txt From 620266d9d607641e4db1dcb63f513b30e54d4f26 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 25 Jun 2025 16:40:02 -0400 Subject: [PATCH 263/343] Remove heartbeat --- src/Appwrite/Platform/Workers/Databases.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 0ba55ad97f..bf71ba3946 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -21,8 +21,6 @@ use Utopia\Queue\Message; class Databases extends Action { - private ?int $heartbeatId = null; - public static function getName(): string { return 'databases'; @@ -42,18 +40,6 @@ class Databases extends Action ->inject('queueForRealtime') ->inject('log') ->callback($this->action(...)); - - $this->heartbeatId = Timer::tick(10_000, function () { - Console::info('Databases worker heartbeat'); - }); - } - - public function __destruct() - { - if ($this->heartbeatId) { - Timer::clear($this->heartbeatId); - $this->heartbeatId = null; - } } /** From 7508a22ddfe45123282d8d3fc5a7d806b3b4f5ad Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 25 Jun 2025 16:49:12 -0400 Subject: [PATCH 264/343] Lint --- composer.lock | 74 +++++++++++---------- src/Appwrite/Platform/Workers/Databases.php | 1 - 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/composer.lock b/composer.lock index af7a609930..fd6a322076 100644 --- a/composer.lock +++ b/composer.lock @@ -1113,16 +1113,16 @@ }, { "name": "open-telemetry/api", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/api.git", - "reference": "4e3bb38e069876fb73c2ce85c89583bf2b28cd86" + "reference": "b3a9286f9c1c8247c83493c5b1fa475cd0cec7f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/4e3bb38e069876fb73c2ce85c89583bf2b28cd86", - "reference": "4e3bb38e069876fb73c2ce85c89583bf2b28cd86", + "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/b3a9286f9c1c8247c83493c5b1fa475cd0cec7f7", + "reference": "b3a9286f9c1c8247c83493c5b1fa475cd0cec7f7", "shasum": "" }, "require": { @@ -1142,7 +1142,7 @@ ] }, "branch-alias": { - "dev-main": "1.1.x-dev" + "dev-main": "1.4.x-dev" } }, "autoload": { @@ -1179,7 +1179,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-07T12:32:21+00:00" + "time": "2025-06-19T23:36:51+00:00" }, { "name": "open-telemetry/context", @@ -1242,16 +1242,16 @@ }, { "name": "open-telemetry/exporter-otlp", - "version": "1.3.1", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/exporter-otlp.git", - "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e" + "reference": "196f3a1dbce3b2c0f8110d164232c11ac00ddbb2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/8b3ca1f86d01429c73b407bf1a2075d9c187001e", - "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e", + "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/196f3a1dbce3b2c0f8110d164232c11ac00ddbb2", + "reference": "196f3a1dbce3b2c0f8110d164232c11ac00ddbb2", "shasum": "" }, "require": { @@ -1302,7 +1302,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-21T12:02:20+00:00" + "time": "2025-06-16T00:24:51+00:00" }, { "name": "open-telemetry/gen-otlp-protobuf", @@ -1369,22 +1369,22 @@ }, { "name": "open-telemetry/sdk", - "version": "1.5.0", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sdk.git", - "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657" + "reference": "1c0371794e4c0700afd4a9d4d8511cb5e3f78e6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/cd0d7367599717fc29e04eb8838ec061e6c2c657", - "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/1c0371794e4c0700afd4a9d4d8511cb5e3f78e6a", + "reference": "1c0371794e4c0700afd4a9d4d8511cb5e3f78e6a", "shasum": "" }, "require": { "ext-json": "*", "nyholm/psr7-server": "^1.1", - "open-telemetry/api": "~1.0 || ~1.1", + "open-telemetry/api": "~1.4.0", "open-telemetry/context": "^1.0", "open-telemetry/sem-conv": "^1.0", "php": "^8.1", @@ -1407,6 +1407,10 @@ "type": "library", "extra": { "spi": { + "OpenTelemetry\\API\\Configuration\\ConfigEnv\\EnvComponentLoader": [ + "OpenTelemetry\\API\\Instrumentation\\Configuration\\General\\ConfigEnv\\EnvComponentLoaderHttpConfig", + "OpenTelemetry\\API\\Instrumentation\\Configuration\\General\\ConfigEnv\\EnvComponentLoaderPeerConfig" + ], "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" ] @@ -1455,7 +1459,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-22T02:33:34+00:00" + "time": "2025-06-19T23:36:51+00:00" }, { "name": "open-telemetry/sem-conv", @@ -1874,16 +1878,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.44", + "version": "3.0.45", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "1d0b5e7e1434678411787c5a0535e68907cf82d9" + "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/1d0b5e7e1434678411787c5a0535e68907cf82d9", - "reference": "1d0b5e7e1434678411787c5a0535e68907cf82d9", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/bd81b90d5963c6b9d87de50357585375223f4dd8", + "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8", "shasum": "" }, "require": { @@ -1964,7 +1968,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.44" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.45" }, "funding": [ { @@ -1980,7 +1984,7 @@ "type": "tidelift" } ], - "time": "2025-06-15T09:59:26+00:00" + "time": "2025-06-22T22:54:43+00:00" }, { "name": "psr/container", @@ -4807,16 +4811,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.41.6", + "version": "0.41.8", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "bfcebb968c527e17fdf18d40b8986c83d9c18c93" + "reference": "93ffb24b25b376ca4423e3a5caf6f916673af4b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/bfcebb968c527e17fdf18d40b8986c83d9c18c93", - "reference": "bfcebb968c527e17fdf18d40b8986c83d9c18c93", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/93ffb24b25b376ca4423e3a5caf6f916673af4b2", + "reference": "93ffb24b25b376ca4423e3a5caf6f916673af4b2", "shasum": "" }, "require": { @@ -4852,9 +4856,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.41.6" + "source": "https://github.com/appwrite/sdk-generator/tree/0.41.8" }, - "time": "2025-06-12T03:27:26+00:00" + "time": "2025-06-18T13:20:45+00:00" }, { "name": "doctrine/annotations", @@ -5147,16 +5151,16 @@ }, { "name": "matthiasmullie/minify", - "version": "1.3.74", + "version": "1.3.75", "source": { "type": "git", "url": "https://github.com/matthiasmullie/minify.git", - "reference": "a2593286a4135d03c6a6a9e9aeded5d41e931ce4" + "reference": "76ba4a5f555fd7bf4aa408af608e991569076671" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/a2593286a4135d03c6a6a9e9aeded5d41e931ce4", - "reference": "a2593286a4135d03c6a6a9e9aeded5d41e931ce4", + "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/76ba4a5f555fd7bf4aa408af608e991569076671", + "reference": "76ba4a5f555fd7bf4aa408af608e991569076671", "shasum": "" }, "require": { @@ -5205,7 +5209,7 @@ ], "support": { "issues": "https://github.com/matthiasmullie/minify/issues", - "source": "https://github.com/matthiasmullie/minify/tree/1.3.74" + "source": "https://github.com/matthiasmullie/minify/tree/1.3.75" }, "funding": [ { @@ -5213,7 +5217,7 @@ "type": "github" } ], - "time": "2025-06-12T08:06:04+00:00" + "time": "2025-06-25T09:56:19+00:00" }, { "name": "matthiasmullie/path-converter", diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index bf71ba3946..896ec6d32d 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -4,7 +4,6 @@ namespace Appwrite\Platform\Workers; use Appwrite\Event\Realtime; use Exception; -use Swoole\Timer; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Document; From d2753bd491409fe07269d2460ede3e91626598d1 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 26 Jun 2025 12:34:38 +0530 Subject: [PATCH 265/343] add: missing injections. --- app/controllers/general.php | 9 ++++++--- composer.lock | 23 +++++++++++------------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 943743d956..9660108ece 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1080,6 +1080,7 @@ App::options() ->inject('swooleRequest') ->inject('request') ->inject('response') + ->inject('log') ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForEvents') @@ -1092,7 +1093,7 @@ App::options() ->inject('project') ->inject('devKey') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Log $log, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey) { /* * Appwrite Router */ @@ -1396,6 +1397,7 @@ App::get('/robots.txt') ->inject('swooleRequest') ->inject('request') ->inject('response') + ->inject('log') ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForEvents') @@ -1406,7 +1408,7 @@ App::get('/robots.txt') ->inject('isResourceBlocked') ->inject('previewHostname') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Log $log, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); @@ -1428,6 +1430,7 @@ App::get('/humans.txt') ->inject('swooleRequest') ->inject('request') ->inject('response') + ->inject('log') ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForEvents') @@ -1438,7 +1441,7 @@ App::get('/humans.txt') ->inject('isResourceBlocked') ->inject('previewHostname') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); diff --git a/composer.lock b/composer.lock index fd6a322076..9bafdeeea6 100644 --- a/composer.lock +++ b/composer.lock @@ -1463,16 +1463,16 @@ }, { "name": "open-telemetry/sem-conv", - "version": "1.32.0", + "version": "1.32.1", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sem-conv.git", - "reference": "16585cc0dbc3032a318e274043454679430d2ebf" + "reference": "94daa85ea61a8e2b7e1b0af6be0e875bedda7c22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/16585cc0dbc3032a318e274043454679430d2ebf", - "reference": "16585cc0dbc3032a318e274043454679430d2ebf", + "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/94daa85ea61a8e2b7e1b0af6be0e875bedda7c22", + "reference": "94daa85ea61a8e2b7e1b0af6be0e875bedda7c22", "shasum": "" }, "require": { @@ -1516,7 +1516,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-05T03:58:53+00:00" + "time": "2025-06-24T02:32:27+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -2327,21 +2327,20 @@ }, { "name": "ramsey/uuid", - "version": "4.8.1", + "version": "4.9.0", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28" + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", - "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0", + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0", "shasum": "" }, "require": { "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", - "ext-json": "*", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" }, @@ -2400,9 +2399,9 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.8.1" + "source": "https://github.com/ramsey/uuid/tree/4.9.0" }, - "time": "2025-06-01T06:28:46+00:00" + "time": "2025-06-25T14:20:11+00:00" }, { "name": "spomky-labs/otphp", From 8f5b53d16c95c6908637370349e8a159517de08a Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 26 Jun 2025 12:36:37 +0530 Subject: [PATCH 266/343] revert: composer.lock. --- composer.lock | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/composer.lock b/composer.lock index 9bafdeeea6..fd6a322076 100644 --- a/composer.lock +++ b/composer.lock @@ -1463,16 +1463,16 @@ }, { "name": "open-telemetry/sem-conv", - "version": "1.32.1", + "version": "1.32.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sem-conv.git", - "reference": "94daa85ea61a8e2b7e1b0af6be0e875bedda7c22" + "reference": "16585cc0dbc3032a318e274043454679430d2ebf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/94daa85ea61a8e2b7e1b0af6be0e875bedda7c22", - "reference": "94daa85ea61a8e2b7e1b0af6be0e875bedda7c22", + "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/16585cc0dbc3032a318e274043454679430d2ebf", + "reference": "16585cc0dbc3032a318e274043454679430d2ebf", "shasum": "" }, "require": { @@ -1516,7 +1516,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-06-24T02:32:27+00:00" + "time": "2025-05-05T03:58:53+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -2327,20 +2327,21 @@ }, { "name": "ramsey/uuid", - "version": "4.9.0", + "version": "4.8.1", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0" + "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0", - "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", + "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", "shasum": "" }, "require": { "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", + "ext-json": "*", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" }, @@ -2399,9 +2400,9 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.9.0" + "source": "https://github.com/ramsey/uuid/tree/4.8.1" }, - "time": "2025-06-25T14:20:11+00:00" + "time": "2025-06-01T06:28:46+00:00" }, { "name": "spomky-labs/otphp", From 038b5d74183b6547aa613c6c4d745e2247a76787 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 26 Jun 2025 12:40:56 +0530 Subject: [PATCH 267/343] fix: lint. --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 9660108ece..827fd3d525 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1093,7 +1093,7 @@ App::options() ->inject('project') ->inject('devKey') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Log $log, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Log $log, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey) { /* * Appwrite Router */ From 72956d1995f23a4f04d60a0c4e48501a7642edd3 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 26 Jun 2025 13:07:11 +0530 Subject: [PATCH 268/343] fix: misaligned param order. --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 827fd3d525..44a9cff45b 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1093,7 +1093,7 @@ App::options() ->inject('project') ->inject('devKey') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Log $log, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey) { /* * Appwrite Router */ From 8bf3a8bf5df4756a101fbb9ede0d50085d791339 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 26 Jun 2025 13:29:06 +0530 Subject: [PATCH 269/343] chore: add runtimeEntrypoint param --- src/Executor/Executor.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index 15411f18ab..1a04e2f26e 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -64,7 +64,8 @@ class Executor string $destination = '', array $variables = [], string $command = null, - string $outputDirectory = '' + string $outputDirectory = '', + string $runtimeEntrypoint = '' ) { $runtimeId = "$projectId-$deploymentId-build"; $route = "/runtimes"; @@ -87,7 +88,8 @@ class Executor 'memory' => $memory, 'version' => $version, 'timeout' => $timeout, - 'outputDirectory' => $outputDirectory + 'outputDirectory' => $outputDirectory, + 'runtimeEntrypoint' => $runtimeEntrypoint ]; From 276a29439109b3b10028a02a0ad669444f777b02 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 26 Jun 2025 13:37:43 +0530 Subject: [PATCH 270/343] chore: update createExecution --- src/Executor/Executor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index 1a04e2f26e..e0e40f0169 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -188,7 +188,7 @@ class Executor array $headers, float $cpus, int $memory, - string $runtimeEntrypoint = null, + string $runtimeEntrypoint = '', bool $logging, int $requestTimeout = null ) { From dbc7e5b42d0a9b789446cc8b9079d5e708907613 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Thu, 26 Jun 2025 15:05:10 +0400 Subject: [PATCH 271/343] Fix output format flag in benchmark workflow for consistency --- .github/workflows/benchmark.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 562f2223f3..f1051497a8 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -65,7 +65,7 @@ jobs: sudo apt update sudo apt install oha - name: Benchmark PR - run: 'oha -z 180s http://localhost/v1/health/version --output_format json > benchmark.json' + run: 'oha -z 180s http://localhost/v1/health/version --output-format json > benchmark.json' - name: Cleaning run: docker compose down -v - name: Installing latest version @@ -78,7 +78,7 @@ jobs: docker compose up -d sleep 10 - name: Benchmark Latest - run: oha -z 180s http://localhost/v1/health/version --output_format json > benchmark-latest.json + run: oha -z 180s http://localhost/v1/health/version --output-format json > benchmark-latest.json - name: Prepare comment run: | echo '## :sparkles: Benchmark results' > benchmark.txt From 5761320bfb953d92cd2601a0fc553dfd9650f07e Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Thu, 26 Jun 2025 15:05:55 +0400 Subject: [PATCH 272/343] Update src/Appwrite/Platform/Action.php Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/Appwrite/Platform/Action.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Action.php b/src/Appwrite/Platform/Action.php index 96444f9144..fda6209d5f 100644 --- a/src/Appwrite/Platform/Action.php +++ b/src/Appwrite/Platform/Action.php @@ -114,7 +114,20 @@ class Action extends UtopiaAction } } - public function dump(string $method, string $log, string $type = 'info', ?Document $project = null, string $collectionId = '') + /** + * Dump Log Message + * + * Logs messages to console with timestamp, method context, and project details. + * Supports multiple log types: success, error, log, warning, and info (default). + * + * @param string $method The calling method name + * @param string $log The log message + * @param string $type The log type (success, error, log, warning, info) + * @param Document|null $project The project document for context + * @param string $collectionId The collection identifier + * @return void + */ + public function dump(string $method, string $log, string $type = 'info', ?Document $project = null, string $collectionId = ''): void { if (empty($project)) { $project = new Document([]); From 204b00850d6e6311221adbbd7a5b84cded2ce289 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Thu, 26 Jun 2025 15:09:57 +0400 Subject: [PATCH 273/343] Refactor log message documentation in Action class to improve clarity and formatting --- src/Appwrite/Platform/Action.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Action.php b/src/Appwrite/Platform/Action.php index fda6209d5f..e5a7cf7984 100644 --- a/src/Appwrite/Platform/Action.php +++ b/src/Appwrite/Platform/Action.php @@ -116,10 +116,10 @@ class Action extends UtopiaAction /** * Dump Log Message - * + * * Logs messages to console with timestamp, method context, and project details. * Supports multiple log types: success, error, log, warning, and info (default). - * + * * @param string $method The calling method name * @param string $log The log message * @param string $type The log type (success, error, log, warning, info) From 9861f60666abe184ebfa3c72c260de04eb876b75 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 26 Jun 2025 18:55:51 +0530 Subject: [PATCH 274/343] chore: add logging --- app/controllers/general.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/general.php b/app/controllers/general.php index edb4295a0d..f0a90dddd7 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1067,6 +1067,8 @@ App::init() $origin = $request->getOrigin($request->getReferer('')); $originValidator = new Origin($platforms); + Console::info('Platforms: ' . json_encode($platforms, JSON_PRETTY_PRINT)); + if ( !empty($origin) && !$originValidator->isValid($origin) From e13089b1ce5e2618728f96690bb7a79260aeaf3d Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 26 Jun 2025 19:09:14 +0530 Subject: [PATCH 275/343] chore: more logging --- app/controllers/general.php | 4 ++-- src/Appwrite/Network/Validator/Origin.php | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index f0a90dddd7..cd1d8ac655 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1070,9 +1070,9 @@ App::init() Console::info('Platforms: ' . json_encode($platforms, JSON_PRETTY_PRINT)); if ( - !empty($origin) + $devKey->isEmpty() + && !empty($origin) && !$originValidator->isValid($origin) - && $devKey->isEmpty() && \in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE]) && $route->getLabel('origin', false) !== '*' && empty($request->getHeader('x-appwrite-key', '')) diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index b0aa4bd49b..33426b7d56 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -3,6 +3,7 @@ namespace Appwrite\Network\Validator; use Appwrite\Network\Platform; +use Utopia\CLI\Console; use Utopia\Validator; use Utopia\Validator\Hostname; @@ -42,6 +43,12 @@ class Origin extends Validator $this->scheme = $this->parseScheme($origin); $this->host = parse_url($origin, PHP_URL_HOST); + Console::info('Origin: ' . $origin); + Console::info('Hostnames: ' . json_encode($this->hostnames, JSON_PRETTY_PRINT)); + Console::info('Host: ' . $this->host); + Console::info('Schemes: ' . json_encode($this->schemes, JSON_PRETTY_PRINT)); + Console::info('Scheme: ' . $this->scheme); + if (!empty($this->scheme) && in_array($this->scheme, $this->schemes, true)) { return true; } From 7e378a3a1ee3cd2e7b0ce7f9902d0048576481a4 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 26 Jun 2025 19:10:35 +0530 Subject: [PATCH 276/343] chore: more logging --- src/Appwrite/Network/Validator/Origin.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 33426b7d56..8fd2120042 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -46,6 +46,8 @@ class Origin extends Validator Console::info('Origin: ' . $origin); Console::info('Hostnames: ' . json_encode($this->hostnames, JSON_PRETTY_PRINT)); Console::info('Host: ' . $this->host); + $validator = new Hostname($this->hostnames); + Console::info('Valid Hostname? ' . $validator->isValid($this->host) ? 'Yes' : 'No'); Console::info('Schemes: ' . json_encode($this->schemes, JSON_PRETTY_PRINT)); Console::info('Scheme: ' . $this->scheme); @@ -57,7 +59,6 @@ class Origin extends Validator return false; } - $validator = new Hostname($this->hostnames); return $validator->isValid($this->host); } From 043cead66ba01007add576189227971f9cd97b74 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 26 Jun 2025 19:32:15 +0530 Subject: [PATCH 277/343] chore: fix logging --- app/controllers/api/account.php | 1 - src/Appwrite/Network/Validator/Origin.php | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 978c0bd2b5..915335f1c2 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1282,7 +1282,6 @@ App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId') ->inject('request') ->inject('response') ->action(function (string $projectId, string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response) { - $domain = $request->getHostname(); $protocol = $request->getProtocol(); diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 8fd2120042..e7c4069569 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -46,8 +46,6 @@ class Origin extends Validator Console::info('Origin: ' . $origin); Console::info('Hostnames: ' . json_encode($this->hostnames, JSON_PRETTY_PRINT)); Console::info('Host: ' . $this->host); - $validator = new Hostname($this->hostnames); - Console::info('Valid Hostname? ' . $validator->isValid($this->host) ? 'Yes' : 'No'); Console::info('Schemes: ' . json_encode($this->schemes, JSON_PRETTY_PRINT)); Console::info('Scheme: ' . $this->scheme); @@ -55,10 +53,16 @@ class Origin extends Validator return true; } + Console::info('we got here (1)'); + if (!in_array($this->scheme, ['http', 'https'])) { return false; } + Console::info('we got here (2)'); + + $validator = new Hostname($this->hostnames); + Console::info('Valid Hostname? ' . ($validator->isValid($this->host) ? 'Yes' : 'No')); return $validator->isValid($this->host); } From be40f1cbe3519da6bab6720aba46796c246ae8af Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 26 Jun 2025 19:44:41 +0530 Subject: [PATCH 278/343] chore: remove check for scheme --- src/Appwrite/Network/Validator/Origin.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index e7c4069569..92fa776f40 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -55,9 +55,9 @@ class Origin extends Validator Console::info('we got here (1)'); - if (!in_array($this->scheme, ['http', 'https'])) { - return false; - } + // if (!in_array($this->scheme, ['http', 'https'])) { + // return false; + // } Console::info('we got here (2)'); From f8e74d073a51b1166d9847f482eccb0edd1d8768 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 26 Jun 2025 19:48:57 +0530 Subject: [PATCH 279/343] chore: fix scheme check, remove logging --- app/controllers/general.php | 2 -- src/Appwrite/Network/Validator/Origin.php | 20 ++------------------ 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index cd1d8ac655..e9b9cab632 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1067,8 +1067,6 @@ App::init() $origin = $request->getOrigin($request->getReferer('')); $originValidator = new Origin($platforms); - Console::info('Platforms: ' . json_encode($platforms, JSON_PRETTY_PRINT)); - if ( $devKey->isEmpty() && !empty($origin) diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 92fa776f40..66441dab2e 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -3,7 +3,6 @@ namespace Appwrite\Network\Validator; use Appwrite\Network\Platform; -use Utopia\CLI\Console; use Utopia\Validator; use Utopia\Validator\Hostname; @@ -43,26 +42,11 @@ class Origin extends Validator $this->scheme = $this->parseScheme($origin); $this->host = parse_url($origin, PHP_URL_HOST); - Console::info('Origin: ' . $origin); - Console::info('Hostnames: ' . json_encode($this->hostnames, JSON_PRETTY_PRINT)); - Console::info('Host: ' . $this->host); - Console::info('Schemes: ' . json_encode($this->schemes, JSON_PRETTY_PRINT)); - Console::info('Scheme: ' . $this->scheme); - - if (!empty($this->scheme) && in_array($this->scheme, $this->schemes, true)) { - return true; + if (!empty($this->scheme) && !in_array($this->scheme, $this->schemes, true)) { + return false; } - Console::info('we got here (1)'); - - // if (!in_array($this->scheme, ['http', 'https'])) { - // return false; - // } - - Console::info('we got here (2)'); - $validator = new Hostname($this->hostnames); - Console::info('Valid Hostname? ' . ($validator->isValid($this->host) ? 'Yes' : 'No')); return $validator->isValid($this->host); } From 1555abcbd6d6533a63b4ccc0e802bddbf7b4b733 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 26 Jun 2025 19:59:58 +0530 Subject: [PATCH 280/343] chore: use lowercase for check --- src/Appwrite/Network/Validator/Origin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 66441dab2e..3ea11bb764 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -40,7 +40,7 @@ class Origin extends Validator } $this->scheme = $this->parseScheme($origin); - $this->host = parse_url($origin, PHP_URL_HOST); + $this->host = strtolower(parse_url($origin, PHP_URL_HOST)); if (!empty($this->scheme) && !in_array($this->scheme, $this->schemes, true)) { return false; From c76fa53f55f885e0dd2617d23575b389b2ab8ac4 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Thu, 26 Jun 2025 21:13:12 +0530 Subject: [PATCH 281/343] updated the db version --- composer.lock | 109 ++++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/composer.lock b/composer.lock index ff6884de7d..b63be420dc 100644 --- a/composer.lock +++ b/composer.lock @@ -1113,16 +1113,16 @@ }, { "name": "open-telemetry/api", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/api.git", - "reference": "4e3bb38e069876fb73c2ce85c89583bf2b28cd86" + "reference": "b3a9286f9c1c8247c83493c5b1fa475cd0cec7f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/4e3bb38e069876fb73c2ce85c89583bf2b28cd86", - "reference": "4e3bb38e069876fb73c2ce85c89583bf2b28cd86", + "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/b3a9286f9c1c8247c83493c5b1fa475cd0cec7f7", + "reference": "b3a9286f9c1c8247c83493c5b1fa475cd0cec7f7", "shasum": "" }, "require": { @@ -1142,7 +1142,7 @@ ] }, "branch-alias": { - "dev-main": "1.1.x-dev" + "dev-main": "1.4.x-dev" } }, "autoload": { @@ -1179,7 +1179,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-07T12:32:21+00:00" + "time": "2025-06-19T23:36:51+00:00" }, { "name": "open-telemetry/context", @@ -1242,16 +1242,16 @@ }, { "name": "open-telemetry/exporter-otlp", - "version": "1.3.1", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/exporter-otlp.git", - "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e" + "reference": "196f3a1dbce3b2c0f8110d164232c11ac00ddbb2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/8b3ca1f86d01429c73b407bf1a2075d9c187001e", - "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e", + "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/196f3a1dbce3b2c0f8110d164232c11ac00ddbb2", + "reference": "196f3a1dbce3b2c0f8110d164232c11ac00ddbb2", "shasum": "" }, "require": { @@ -1302,7 +1302,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-21T12:02:20+00:00" + "time": "2025-06-16T00:24:51+00:00" }, { "name": "open-telemetry/gen-otlp-protobuf", @@ -1369,22 +1369,22 @@ }, { "name": "open-telemetry/sdk", - "version": "1.5.0", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sdk.git", - "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657" + "reference": "1c0371794e4c0700afd4a9d4d8511cb5e3f78e6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/cd0d7367599717fc29e04eb8838ec061e6c2c657", - "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/1c0371794e4c0700afd4a9d4d8511cb5e3f78e6a", + "reference": "1c0371794e4c0700afd4a9d4d8511cb5e3f78e6a", "shasum": "" }, "require": { "ext-json": "*", "nyholm/psr7-server": "^1.1", - "open-telemetry/api": "~1.0 || ~1.1", + "open-telemetry/api": "~1.4.0", "open-telemetry/context": "^1.0", "open-telemetry/sem-conv": "^1.0", "php": "^8.1", @@ -1407,6 +1407,10 @@ "type": "library", "extra": { "spi": { + "OpenTelemetry\\API\\Configuration\\ConfigEnv\\EnvComponentLoader": [ + "OpenTelemetry\\API\\Instrumentation\\Configuration\\General\\ConfigEnv\\EnvComponentLoaderHttpConfig", + "OpenTelemetry\\API\\Instrumentation\\Configuration\\General\\ConfigEnv\\EnvComponentLoaderPeerConfig" + ], "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" ] @@ -1455,20 +1459,20 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-22T02:33:34+00:00" + "time": "2025-06-19T23:36:51+00:00" }, { "name": "open-telemetry/sem-conv", - "version": "1.32.0", + "version": "1.32.1", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sem-conv.git", - "reference": "16585cc0dbc3032a318e274043454679430d2ebf" + "reference": "94daa85ea61a8e2b7e1b0af6be0e875bedda7c22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/16585cc0dbc3032a318e274043454679430d2ebf", - "reference": "16585cc0dbc3032a318e274043454679430d2ebf", + "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/94daa85ea61a8e2b7e1b0af6be0e875bedda7c22", + "reference": "94daa85ea61a8e2b7e1b0af6be0e875bedda7c22", "shasum": "" }, "require": { @@ -1512,7 +1516,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-05T03:58:53+00:00" + "time": "2025-06-24T02:32:27+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -1874,16 +1878,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.44", + "version": "3.0.45", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "1d0b5e7e1434678411787c5a0535e68907cf82d9" + "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/1d0b5e7e1434678411787c5a0535e68907cf82d9", - "reference": "1d0b5e7e1434678411787c5a0535e68907cf82d9", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/bd81b90d5963c6b9d87de50357585375223f4dd8", + "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8", "shasum": "" }, "require": { @@ -1964,7 +1968,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.44" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.45" }, "funding": [ { @@ -1980,7 +1984,7 @@ "type": "tidelift" } ], - "time": "2025-06-15T09:59:26+00:00" + "time": "2025-06-22T22:54:43+00:00" }, { "name": "psr/container", @@ -2323,21 +2327,20 @@ }, { "name": "ramsey/uuid", - "version": "4.8.1", + "version": "4.9.0", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28" + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", - "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0", + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0", "shasum": "" }, "require": { "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", - "ext-json": "*", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" }, @@ -2396,9 +2399,9 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.8.1" + "source": "https://github.com/ramsey/uuid/tree/4.9.0" }, - "time": "2025-06-01T06:28:46+00:00" + "time": "2025-06-25T14:20:11+00:00" }, { "name": "spomky-labs/otphp", @@ -3490,16 +3493,16 @@ }, { "name": "utopia-php/database", - "version": "0.71.6", + "version": "0.71.8", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "2bd87acc40af087fc0fdcccc47c43141dff0be5c" + "reference": "7dff6b67a54f1a7f9d3f210db4c6e40d7052b79e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/2bd87acc40af087fc0fdcccc47c43141dff0be5c", - "reference": "2bd87acc40af087fc0fdcccc47c43141dff0be5c", + "url": "https://api.github.com/repos/utopia-php/database/zipball/7dff6b67a54f1a7f9d3f210db4c6e40d7052b79e", + "reference": "7dff6b67a54f1a7f9d3f210db4c6e40d7052b79e", "shasum": "" }, "require": { @@ -3540,9 +3543,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.71.6" + "source": "https://github.com/utopia-php/database/tree/0.71.8" }, - "time": "2025-06-16T16:48:37+00:00" + "time": "2025-06-26T14:48:17+00:00" }, { "name": "utopia-php/detector", @@ -4807,16 +4810,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.41.7", + "version": "0.41.8", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "d8c7bb26ea32ab378faf4e0dfa62fd15fe37c57b" + "reference": "93ffb24b25b376ca4423e3a5caf6f916673af4b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/d8c7bb26ea32ab378faf4e0dfa62fd15fe37c57b", - "reference": "d8c7bb26ea32ab378faf4e0dfa62fd15fe37c57b", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/93ffb24b25b376ca4423e3a5caf6f916673af4b2", + "reference": "93ffb24b25b376ca4423e3a5caf6f916673af4b2", "shasum": "" }, "require": { @@ -4852,9 +4855,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.41.7" + "source": "https://github.com/appwrite/sdk-generator/tree/0.41.8" }, - "time": "2025-06-13T17:05:57+00:00" + "time": "2025-06-18T13:20:45+00:00" }, { "name": "doctrine/annotations", @@ -5147,16 +5150,16 @@ }, { "name": "matthiasmullie/minify", - "version": "1.3.74", + "version": "1.3.75", "source": { "type": "git", "url": "https://github.com/matthiasmullie/minify.git", - "reference": "a2593286a4135d03c6a6a9e9aeded5d41e931ce4" + "reference": "76ba4a5f555fd7bf4aa408af608e991569076671" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/a2593286a4135d03c6a6a9e9aeded5d41e931ce4", - "reference": "a2593286a4135d03c6a6a9e9aeded5d41e931ce4", + "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/76ba4a5f555fd7bf4aa408af608e991569076671", + "reference": "76ba4a5f555fd7bf4aa408af608e991569076671", "shasum": "" }, "require": { @@ -5205,7 +5208,7 @@ ], "support": { "issues": "https://github.com/matthiasmullie/minify/issues", - "source": "https://github.com/matthiasmullie/minify/tree/1.3.74" + "source": "https://github.com/matthiasmullie/minify/tree/1.3.75" }, "funding": [ { @@ -5213,7 +5216,7 @@ "type": "github" } ], - "time": "2025-06-12T08:06:04+00:00" + "time": "2025-06-25T09:56:19+00:00" }, { "name": "matthiasmullie/path-converter", From b36431d45ca5019039bbc8ecdfed6ac3eea5bc77 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Thu, 26 Jun 2025 21:26:25 +0530 Subject: [PATCH 282/343] empty commit From 918ad8979d2770bcc9b8662d1cdfd6a47c83ddaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 26 Jun 2025 18:07:59 +0200 Subject: [PATCH 283/343] Fix flakyness of account tests --- app/init/registers.php | 3 ++- docker-compose.yml | 16 +++++++++++--- tests/e2e/Scopes/ProjectCustom.php | 2 +- tests/e2e/Scopes/Scope.php | 22 +++++++++++++++---- .../Account/AccountCustomClientTest.php | 5 ++--- 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/app/init/registers.php b/app/init/registers.php index 415730f936..3dc0e22dba 100644 --- a/app/init/registers.php +++ b/app/init/registers.php @@ -36,7 +36,8 @@ App::setMode(System::getEnv('_APP_ENV', App::MODE_TYPE_PRODUCTION)); if (!App::isProduction()) { // Allow specific domains to skip public domain validation in dev environment // Useful for existing tests involving webhooks - PublicDomain::allow(['request-catcher']); + PublicDomain::allow(['request-catcher-sms']); + PublicDomain::allow(['request-catcher-webhook']); } $register->set('logger', function () { // Register error logger diff --git a/docker-compose.yml b/docker-compose.yml index ecb46de057..f5ac47a832 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -323,7 +323,8 @@ services: depends_on: - redis - mariadb - - request-catcher + - request-catcher-sms + - request-catcher-webhook environment: - _APP_ENV - _APP_WORKER_PER_CORE @@ -1075,15 +1076,24 @@ services: networks: - appwrite - request-catcher: # used mainly for dev tests + request-catcher-webhook: # used mainly for dev tests (mock HTTP webhook) image: appwrite/requestcatcher:1.0.0 - container_name: appwrite-requestcatcher + container_name: appwrite-requestcatcher-webhook <<: *x-logging ports: - "9504:5000" networks: - appwrite + request-catcher-sms: # used mainly for dev tests (mock SMS auth secret) + image: appwrite/requestcatcher:1.0.0 + container_name: appwrite-requestcatcher-sms + <<: *x-logging + ports: + - "9507:5000" + networks: + - appwrite + adminer: image: adminer container_name: appwrite-adminer diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index a354696f53..c5152adbcc 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -140,7 +140,7 @@ trait ProjectCustom 'teams.*', 'users.*' ], - 'url' => 'http://request-catcher:5000/webhook', + 'url' => 'http://request-catcher-webhook:5000/', 'security' => false, ]); diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index dddc97e3a0..b9792202e5 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -13,6 +13,9 @@ abstract class Scope extends TestCase use Retryable; use Async; + public const REQUEST_TYPE_WEBHOOK = 'webhook'; + public const REQUEST_TYPE_SMS = 'sms'; + protected ?Client $client = null; protected string $endpoint = 'http://localhost/v1'; @@ -76,10 +79,16 @@ abstract class Scope extends TestCase return []; } - protected function assertLastRequest(callable $probe, $timeoutMs = 20_000, $waitMs = 500): array + protected function assertLastRequest(callable $probe, string $type, $timeoutMs = 20_000, $waitMs = 500): array { - $this->assertEventually(function () use (&$request, $probe) { - $request = json_decode(file_get_contents('http://request-catcher:5000/__last_request__'), true); + $hostname = match ($type) { + 'webhook' => 'request-catcher-webhook', + 'api' => 'request-catcher-api', + default => throw new \Exception('Invalid request catcher type.'), + }; + + $this->assertEventually(function () use (&$request, $probe, $hostname) { + $request = json_decode(file_get_contents('http://' . $hostname . ':5000/__last_request__'), true); $request['data'] = json_decode($request['data'], true); call_user_func($probe, $request); @@ -88,11 +97,16 @@ abstract class Scope extends TestCase return $request; } + /** + * @deprecated Use assertLastRequest instead. Used only historically in webhook tests + */ protected function getLastRequest(): array { + $hostname = 'request-catcher-webhook'; + sleep(2); - $request = json_decode(file_get_contents('http://request-catcher:5000/__last_request__'), true); + $request = json_decode(file_get_contents('http://' . $hostname . ':5000/__last_request__'), true); $request['data'] = json_decode($request['data'], true); return $request; diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 86c78d5d81..7072b122f4 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -2065,14 +2065,13 @@ class AccountCustomClientTest extends Scope $userId = $response['body']['userId']; $smsRequest = $this->assertLastRequest(function (array $request) use ($number) { - $this->assertEquals('http://request-catcher:5000/mock-sms', $request['url']); $this->assertEquals('Appwrite Mock Message Sender', $request['headers']['User-Agent']); $this->assertEquals('username', $request['headers']['X-Username']); $this->assertEquals('password', $request['headers']['X-Key']); $this->assertEquals('POST', $request['method']); $this->assertEquals('+123456789', $request['data']['from']); $this->assertEquals($number, $request['data']['to']); - }); + }, Scope::REQUEST_TYPE_SMS); $data['token'] = $smsRequest['data']['message']; $data['id'] = $userId; @@ -2422,7 +2421,7 @@ class AccountCustomClientTest extends Scope $smsRequest = $this->assertLastRequest(function ($request) { $this->assertArrayHasKey('data', $request); $this->assertArrayHasKey('message', $request['data'], "Last request missing message: " . \json_encode($request)); - }); + }, Scope::REQUEST_TYPE_SMS); /** * Test for FAILURE From 87c100db28608f0eac29032166baf52f15c7e247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 26 Jun 2025 18:09:07 +0200 Subject: [PATCH 284/343] Improve General tests logging --- tests/e2e/General/HTTPTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/General/HTTPTest.php b/tests/e2e/General/HTTPTest.php index 620409bb39..bce6e7206f 100644 --- a/tests/e2e/General/HTTPTest.php +++ b/tests/e2e/General/HTTPTest.php @@ -60,7 +60,7 @@ class HTTPTest extends Scope 'origin' => 'http://localhost', ])); - $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(200, $response['headers']['status-code'], "Simple GET /robots.txt HTTP request failed: " . \json_encode($response)); $this->assertStringContainsString('# robotstxt.org/', $response['body']); } From 572ff06f533c3a8651c3a7b861206aa7523d2680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 26 Jun 2025 18:32:03 +0200 Subject: [PATCH 285/343] Fix robots.txt 5xx error --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 44a9cff45b..c18f729c44 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1408,7 +1408,7 @@ App::get('/robots.txt') ->inject('isResourceBlocked') ->inject('previewHostname') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Log $log, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); From d4b53175dc0ca3e919170a2c0223371de80612a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 26 Jun 2025 18:33:22 +0200 Subject: [PATCH 286/343] Update tests/e2e/Scopes/Scope.php --- tests/e2e/Scopes/Scope.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index b9792202e5..2ee0d0198e 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -83,7 +83,7 @@ abstract class Scope extends TestCase { $hostname = match ($type) { 'webhook' => 'request-catcher-webhook', - 'api' => 'request-catcher-api', + 'sms' => 'request-catcher-sms', default => throw new \Exception('Invalid request catcher type.'), }; From ee2796f870d877054ea55a8d611798cdf01733f3 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Thu, 26 Jun 2025 20:49:52 +0400 Subject: [PATCH 287/343] fix: correct parameter order in action function for robots.txt route --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 44a9cff45b..c18f729c44 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1408,7 +1408,7 @@ App::get('/robots.txt') ->inject('isResourceBlocked') ->inject('previewHostname') ->inject('apiKey') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Log $log, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); From bda9adc52eb9e04437fee564d44aac5a4f0105a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 26 Jun 2025 20:04:56 +0200 Subject: [PATCH 288/343] Fix sms mock endpoint --- composer.json | 2 +- composer.lock | 64 ++++++++++++--------- src/Appwrite/Platform/Workers/Messaging.php | 2 +- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/composer.json b/composer.json index 4c36ab125d..0dd37d3747 100644 --- a/composer.json +++ b/composer.json @@ -61,7 +61,7 @@ "utopia-php/image": "0.8.*", "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", - "utopia-php/messaging": "0.18.*", + "utopia-php/messaging": "dev-feat-customizable-mock as 0.18.99", "utopia-php/migration": "0.10.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", diff --git a/composer.lock b/composer.lock index fd6a322076..63a03422c8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "55bc52686a08d64930e6af7411ac0654", + "content-hash": "8c1c38af4f7d733255bfdb8390fe6d65", "packages": [ { "name": "adhocore/jwt", @@ -1463,16 +1463,16 @@ }, { "name": "open-telemetry/sem-conv", - "version": "1.32.0", + "version": "1.32.1", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sem-conv.git", - "reference": "16585cc0dbc3032a318e274043454679430d2ebf" + "reference": "94daa85ea61a8e2b7e1b0af6be0e875bedda7c22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/16585cc0dbc3032a318e274043454679430d2ebf", - "reference": "16585cc0dbc3032a318e274043454679430d2ebf", + "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/94daa85ea61a8e2b7e1b0af6be0e875bedda7c22", + "reference": "94daa85ea61a8e2b7e1b0af6be0e875bedda7c22", "shasum": "" }, "require": { @@ -1516,7 +1516,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-05T03:58:53+00:00" + "time": "2025-06-24T02:32:27+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -2327,21 +2327,20 @@ }, { "name": "ramsey/uuid", - "version": "4.8.1", + "version": "4.9.0", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28" + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", - "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0", + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0", "shasum": "" }, "require": { "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", - "ext-json": "*", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" }, @@ -2400,9 +2399,9 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.8.1" + "source": "https://github.com/ramsey/uuid/tree/4.9.0" }, - "time": "2025-06-01T06:28:46+00:00" + "time": "2025-06-25T14:20:11+00:00" }, { "name": "spomky-labs/otphp", @@ -3494,16 +3493,16 @@ }, { "name": "utopia-php/database", - "version": "0.71.7", + "version": "0.71.8", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "aa0116b2380125907fc18c82662be8e74c54091f" + "reference": "7dff6b67a54f1a7f9d3f210db4c6e40d7052b79e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/aa0116b2380125907fc18c82662be8e74c54091f", - "reference": "aa0116b2380125907fc18c82662be8e74c54091f", + "url": "https://api.github.com/repos/utopia-php/database/zipball/7dff6b67a54f1a7f9d3f210db4c6e40d7052b79e", + "reference": "7dff6b67a54f1a7f9d3f210db4c6e40d7052b79e", "shasum": "" }, "require": { @@ -3544,9 +3543,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.71.7" + "source": "https://github.com/utopia-php/database/tree/0.71.8" }, - "time": "2025-06-17T23:59:10+00:00" + "time": "2025-06-26T14:48:17+00:00" }, { "name": "utopia-php/detector", @@ -3943,16 +3942,16 @@ }, { "name": "utopia-php/messaging", - "version": "0.18.0", + "version": "dev-feat-customizable-mock", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "c151aa5d4d475c788ca15c210b5b2017e21c41d6" + "reference": "1f761b5f4103f372da3cb3f1141024cb1d0735da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/c151aa5d4d475c788ca15c210b5b2017e21c41d6", - "reference": "c151aa5d4d475c788ca15c210b5b2017e21c41d6", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/1f761b5f4103f372da3cb3f1141024cb1d0735da", + "reference": "1f761b5f4103f372da3cb3f1141024cb1d0735da", "shasum": "" }, "require": { @@ -3988,9 +3987,9 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/0.18.0" + "source": "https://github.com/utopia-php/messaging/tree/feat-customizable-mock" }, - "time": "2025-05-15T05:00:03+00:00" + "time": "2025-06-26T18:01:16+00:00" }, { "name": "utopia-php/migration", @@ -8235,9 +8234,18 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/messaging", + "version": "dev-feat-customizable-mock", + "alias": "0.18.99", + "alias_normalized": "0.18.99.0" + } + ], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/messaging": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8261,5 +8269,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 35733200c7..668993fdae 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -426,7 +426,7 @@ class Messaging extends Action $credentials = $provider->getAttribute('credentials'); return match ($provider->getAttribute('provider')) { - 'mock' => new Mock('username', 'password'), + 'mock' => (new Mock('username', 'password'))->setEndpoint('http://request-catcher-sms:5000/'), 'twilio' => new Twilio( $credentials['accountSid'] ?? '', $credentials['authToken'] ?? '', From a356e86ced5cd1c52a258cf5a12845b59c5ccee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 26 Jun 2025 20:17:26 +0200 Subject: [PATCH 289/343] Add previe wendpoint logging --- app/controllers/api/storage.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 26c789ce27..98a5b105a3 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -18,6 +18,7 @@ use Appwrite\Utopia\Database\Validator\Queries\Buckets; use Appwrite\Utopia\Database\Validator\Queries\Files; use Appwrite\Utopia\Response; use Utopia\App; +use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; @@ -953,12 +954,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->param('output', '', new WhiteList(\array_keys(Config::getParam('storage-outputs')), true), 'Output format type (jpeg, jpg, png, gif and webp).', true) // NOTE: this is only for the sdk generator and is not used in the action below and is utilised in `resources.php` for `resourceToken`. ->param('token', '', new Text(512), 'File token for accessing this file.', true) + ->inject('request') ->inject('response') ->inject('dbForProject') ->inject('resourceToken') ->inject('deviceForFiles') ->inject('deviceForLocal') - ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, ?string $token, Response $response, Database $dbForProject, Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal) { + ->inject('project') + ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, ?string $token, Request $request, Response $response, Database $dbForProject, Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal, Document $project) { if (!\extension_loaded('imagick')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); @@ -1035,8 +1038,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $output = empty($type) ? (array_search($mime, $outputs) ?? 'jpg') : $type; } + $startTime = \microtime(true); + $source = $deviceForFiles->read($path); + $downloadTime = \microtime(true) - $startTime; + if (!empty($cipher)) { // Decrypt $source = OpenSSL::decrypt( $source, @@ -1048,6 +1055,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ); } + $decryptionTime = \microtime(true) - $startTime - $downloadTime; + switch ($algorithm) { case Compression::ZSTD: $compressor = new Zstd(); @@ -1059,6 +1068,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') break; } + $decompressionTime = \microtime(true) - $startTime - $downloadTime - $decryptionTime; + try { $image = new Image($source); } catch (ImagickException $e) { @@ -1089,6 +1100,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $data = $image->output($output, $quality); + $renderingTime = \microtime(true) - $startTime - $downloadTime - $decryptionTime - $decompressionTime; + + $totalTime = \microtime(true) - $startTime; + + Console::info("File preview rendered,project=" . $project->getId() . ",bucket=" . $bucketId . ",file=" . $file->getId() . ",uri=" . $request->getURI() . ",total=" . $totalTime . ",rendering=" . $renderingTime . ",decryption=" . $decryptionTime . ",decompression=" . $decompressionTime . ",download=" . $downloadTime); + $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; //Do not update transformedAt if it's a console user From df902d2624c2d1f7f9f880c421521f6159dd6692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 26 Jun 2025 20:47:59 +0200 Subject: [PATCH 290/343] Fix account tests using old token --- composer.json | 2 +- composer.lock | 27 +++++++------------ src/Executor/Executor.php | 4 +-- .../Account/AccountCustomClientTest.php | 10 ++++++- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/composer.json b/composer.json index 0dd37d3747..4c36ab125d 100644 --- a/composer.json +++ b/composer.json @@ -61,7 +61,7 @@ "utopia-php/image": "0.8.*", "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", - "utopia-php/messaging": "dev-feat-customizable-mock as 0.18.99", + "utopia-php/messaging": "0.18.*", "utopia-php/migration": "0.10.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", diff --git a/composer.lock b/composer.lock index 63a03422c8..bd6b0e959e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8c1c38af4f7d733255bfdb8390fe6d65", + "content-hash": "55bc52686a08d64930e6af7411ac0654", "packages": [ { "name": "adhocore/jwt", @@ -3942,16 +3942,16 @@ }, { "name": "utopia-php/messaging", - "version": "dev-feat-customizable-mock", + "version": "0.18.1", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "1f761b5f4103f372da3cb3f1141024cb1d0735da" + "reference": "5d1245207a61d7ca065daddad7ac5f1d5640152f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/1f761b5f4103f372da3cb3f1141024cb1d0735da", - "reference": "1f761b5f4103f372da3cb3f1141024cb1d0735da", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/5d1245207a61d7ca065daddad7ac5f1d5640152f", + "reference": "5d1245207a61d7ca065daddad7ac5f1d5640152f", "shasum": "" }, "require": { @@ -3987,9 +3987,9 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/feat-customizable-mock" + "source": "https://github.com/utopia-php/messaging/tree/0.18.1" }, - "time": "2025-06-26T18:01:16+00:00" + "time": "2025-06-26T18:26:07+00:00" }, { "name": "utopia-php/migration", @@ -8234,18 +8234,9 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [ - { - "package": "utopia-php/messaging", - "version": "dev-feat-customizable-mock", - "alias": "0.18.99", - "alias_normalized": "0.18.99.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/messaging": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index e0e40f0169..fd1a8b494f 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -188,9 +188,9 @@ class Executor array $headers, float $cpus, int $memory, - string $runtimeEntrypoint = '', bool $logging, - int $requestTimeout = null + string $runtimeEntrypoint = '', + ?int $requestTimeout ) { if (empty($headers['host'])) { $headers['host'] = System::getEnv('_APP_DOMAIN', ''); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 7072b122f4..1b84ce7083 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -2415,12 +2415,20 @@ class AccountCustomClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); + $this->assertNotEmpty($response['body']['$createdAt']); $this->assertEmpty($response['body']['secret']); $this->assertTrue((new DatetimeValidator())->isValid($response['body']['expire'])); - $smsRequest = $this->assertLastRequest(function ($request) { + $tokenCreatedAt = $response['body']['$createdAt']; + + $smsRequest = $this->assertLastRequest(function ($request) use ($tokenCreatedAt) { $this->assertArrayHasKey('data', $request); + $this->assertArrayHasKey('time', $request); $this->assertArrayHasKey('message', $request['data'], "Last request missing message: " . \json_encode($request)); + + // Ensure we are not using token from last sms login + $tokenRecievedAt = $request['time']; + $this->assertGreaterThan($tokenCreatedAt, $tokenRecievedAt); }, Scope::REQUEST_TYPE_SMS); /** From b12ea0b3b149c67cd83ba137487f4b0d5964996a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 26 Jun 2025 21:22:38 +0200 Subject: [PATCH 291/343] Fix merge conflict bug --- src/Appwrite/Platform/Modules/Compute/Base.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 71b932590d..e58f2b8664 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -235,15 +235,15 @@ class Base extends Action fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $site->getId(), - 'deploymentResourceInternalId' => $site->getInternalId(), + 'deploymentResourceInternalId' => $site->getSequence(), 'deploymentVcsProviderBranch' => $providerBranch, 'status' => 'verified', 'certificateId' => '', @@ -272,15 +272,15 @@ class Base extends Action fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $site->getId(), - 'deploymentResourceInternalId' => $site->getInternalId(), + 'deploymentResourceInternalId' => $site->getSequence(), 'deploymentVcsProviderBranch' => $providerBranch, 'status' => 'verified', 'certificateId' => '', From ee225834d92e2b42761154bb0d5fa6614c2e3f06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 26 Jun 2025 21:39:00 +0200 Subject: [PATCH 292/343] Fix default param syntax --- src/Executor/Executor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index fd1a8b494f..df4c5fd8f5 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -190,7 +190,7 @@ class Executor int $memory, bool $logging, string $runtimeEntrypoint = '', - ?int $requestTimeout + ?int $requestTimeout = null ) { if (empty($headers['host'])) { $headers['host'] = System::getEnv('_APP_DOMAIN', ''); From fffdab23f9de57116b017c25c44d6665c1dcea6c Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Fri, 27 Jun 2025 08:29:13 +0530 Subject: [PATCH 293/343] chore: update scheme check --- src/Appwrite/Network/Validator/Origin.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 3ea11bb764..21563a9a15 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -40,14 +40,16 @@ class Origin extends Validator } $this->scheme = $this->parseScheme($origin); - $this->host = strtolower(parse_url($origin, PHP_URL_HOST)); - - if (!empty($this->scheme) && !in_array($this->scheme, $this->schemes, true)) { - return false; - } + $this->host = strtolower(parse_url($origin, PHP_URL_HOST) ?? ''); $validator = new Hostname($this->hostnames); - return $validator->isValid($this->host); + if (in_array($this->scheme, ['http', 'https']) && $validator->isValid($this->host)) { // Valid HTTP/HTTPS origin + return true; + } if (!empty($this->scheme) && in_array($this->scheme, $this->schemes, true)) { // Valid scheme-based origin + return true; + } + + return false; } /** From 5a48fd6300c02940fa1dfb5ecf6d1b2a30e30562 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Fri, 27 Jun 2025 11:43:56 +0530 Subject: [PATCH 294/343] chore: update cli to 8.1.0 and add changelog --- app/config/platforms.php | 2 +- composer.json | 2 +- composer.lock | 65 +++++++++++++++++++------------------- docs/sdks/cli/CHANGELOG.md | 62 +++++++++++++++++++++++++++++++++++- 4 files changed, 96 insertions(+), 35 deletions(-) diff --git a/app/config/platforms.php b/app/config/platforms.php index 63ad307ea2..96d5426515 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -217,7 +217,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '8.0.2', + 'version' => '8.1.0', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, diff --git a/composer.json b/composer.json index 4c36ab125d..22ca53ee78 100644 --- a/composer.json +++ b/composer.json @@ -86,7 +86,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "0.41.*", + "appwrite/sdk-generator": "dev-fix-attribute-creation-errors", "phpunit/phpunit": "9.*", "swoole/ide-helper": "5.1.2", "phpstan/phpstan": "1.8.*", diff --git a/composer.lock b/composer.lock index fd6a322076..45467bd4e5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "55bc52686a08d64930e6af7411ac0654", + "content-hash": "71a256558261b19e11189c5967e5bd07", "packages": [ { "name": "adhocore/jwt", @@ -1463,16 +1463,16 @@ }, { "name": "open-telemetry/sem-conv", - "version": "1.32.0", + "version": "1.32.1", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sem-conv.git", - "reference": "16585cc0dbc3032a318e274043454679430d2ebf" + "reference": "94daa85ea61a8e2b7e1b0af6be0e875bedda7c22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/16585cc0dbc3032a318e274043454679430d2ebf", - "reference": "16585cc0dbc3032a318e274043454679430d2ebf", + "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/94daa85ea61a8e2b7e1b0af6be0e875bedda7c22", + "reference": "94daa85ea61a8e2b7e1b0af6be0e875bedda7c22", "shasum": "" }, "require": { @@ -1516,7 +1516,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-05T03:58:53+00:00" + "time": "2025-06-24T02:32:27+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -2327,21 +2327,20 @@ }, { "name": "ramsey/uuid", - "version": "4.8.1", + "version": "4.9.0", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28" + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", - "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0", + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0", "shasum": "" }, "require": { "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", - "ext-json": "*", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" }, @@ -2400,9 +2399,9 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.8.1" + "source": "https://github.com/ramsey/uuid/tree/4.9.0" }, - "time": "2025-06-01T06:28:46+00:00" + "time": "2025-06-25T14:20:11+00:00" }, { "name": "spomky-labs/otphp", @@ -3494,16 +3493,16 @@ }, { "name": "utopia-php/database", - "version": "0.71.7", + "version": "0.71.8", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "aa0116b2380125907fc18c82662be8e74c54091f" + "reference": "7dff6b67a54f1a7f9d3f210db4c6e40d7052b79e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/aa0116b2380125907fc18c82662be8e74c54091f", - "reference": "aa0116b2380125907fc18c82662be8e74c54091f", + "url": "https://api.github.com/repos/utopia-php/database/zipball/7dff6b67a54f1a7f9d3f210db4c6e40d7052b79e", + "reference": "7dff6b67a54f1a7f9d3f210db4c6e40d7052b79e", "shasum": "" }, "require": { @@ -3544,9 +3543,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.71.7" + "source": "https://github.com/utopia-php/database/tree/0.71.8" }, - "time": "2025-06-17T23:59:10+00:00" + "time": "2025-06-26T14:48:17+00:00" }, { "name": "utopia-php/detector", @@ -3943,16 +3942,16 @@ }, { "name": "utopia-php/messaging", - "version": "0.18.0", + "version": "0.18.1", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "c151aa5d4d475c788ca15c210b5b2017e21c41d6" + "reference": "5d1245207a61d7ca065daddad7ac5f1d5640152f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/c151aa5d4d475c788ca15c210b5b2017e21c41d6", - "reference": "c151aa5d4d475c788ca15c210b5b2017e21c41d6", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/5d1245207a61d7ca065daddad7ac5f1d5640152f", + "reference": "5d1245207a61d7ca065daddad7ac5f1d5640152f", "shasum": "" }, "require": { @@ -3988,9 +3987,9 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/0.18.0" + "source": "https://github.com/utopia-php/messaging/tree/0.18.1" }, - "time": "2025-05-15T05:00:03+00:00" + "time": "2025-06-26T18:26:07+00:00" }, { "name": "utopia-php/migration", @@ -4811,16 +4810,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.41.8", + "version": "dev-fix-attribute-creation-errors", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "93ffb24b25b376ca4423e3a5caf6f916673af4b2" + "reference": "a94668e92f9d8dd23770e1075076b2b9534f2886" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/93ffb24b25b376ca4423e3a5caf6f916673af4b2", - "reference": "93ffb24b25b376ca4423e3a5caf6f916673af4b2", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/a94668e92f9d8dd23770e1075076b2b9534f2886", + "reference": "a94668e92f9d8dd23770e1075076b2b9534f2886", "shasum": "" }, "require": { @@ -4856,9 +4855,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.41.8" + "source": "https://github.com/appwrite/sdk-generator/tree/fix-attribute-creation-errors" }, - "time": "2025-06-18T13:20:45+00:00" + "time": "2025-06-27T06:11:13+00:00" }, { "name": "doctrine/annotations", @@ -8237,7 +8236,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "appwrite/sdk-generator": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/docs/sdks/cli/CHANGELOG.md b/docs/sdks/cli/CHANGELOG.md index fa4d35e687..c2c93b0c09 100644 --- a/docs/sdks/cli/CHANGELOG.md +++ b/docs/sdks/cli/CHANGELOG.md @@ -1 +1,61 @@ -# Change Log \ No newline at end of file +# Change Log + +## 8.1.0 + +* Add multi-region support to `init` command +* Update `init` command to clear previous configuration in `appwrite.json` +* Update localConfig to store multi-region endpoint +* Fix throw error when creating unknown attribute instead of timing out +* Fix equal comparison of large numbers and BigNumber instances using proper equality checks +* Fix duplication of reasons when comparing localConfig with remoteConfig +* Fix `firstOrNull()` to `firstOrNull` in types generation for dart +* Refactor to use `isCloud()` method consistently + +## 8.0.2 + +* Add Type generation fixes: + * Properly handle enum attributes in dart, java and kotlin + * Fix initialisation of null attributes in dart's fromMap method + * Fix relationships and enums in swift + +## 8.0.1 + +* Add `resourceId` and `resourceType` attributes to `createRedirectRule` +* Add `providerReference` to vcs command for getting repository contents +* Add warning comment to `bulk updateDocuments` method +* Fix type generation for enums in Typescript and PHP language + +## 8.0.0 + +* Add `types` command to generate language specific typings for collections. Currently supports - `php`, `swift`, `dart`, `js`, `ts`, `kotlin` and `java` +* Update bulk operation docs to include experiment feature warnings +* Remove assistant service and commands + +## 7.0.0 + +* Add `sites` command +* Add `tokens` command +* Add `devKeys` support to `projects` command +* Add `init site`, `pull site` and `push site` commands +* Add bulk operation methods like `createDocuments`, `deleteDocuments` etc. +* Add new upsert methods: `upsertDocument` and `upsertDocuments` +* Update GET requests to not include content-type header + +## 6.2.3 + +* Fix hot swapping error in `python-ml` function + +## 6.2.2 + +* Fix GitHub builds by adding `qemu-system` package +* Fix attribute creation timed out + +## 6.2.1 + +* Add `listOrganizations` method to `organizations` service and fix init project command + +## 6.2.0 + +* Add specifications support to CLI +* Update package version +* Fix: Missed specifications param when updating a function \ No newline at end of file From f056a8ba2f18338957f2228aa4b9daf17de2c2de Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Fri, 27 Jun 2025 15:49:08 +0530 Subject: [PATCH 295/343] fix: composer --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 255f82224b..4c36ab125d 100644 --- a/composer.json +++ b/composer.json @@ -86,7 +86,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "0.41.x", + "appwrite/sdk-generator": "0.41.*", "phpunit/phpunit": "9.*", "swoole/ide-helper": "5.1.2", "phpstan/phpstan": "1.8.*", From 156daca044167def9f73a57e31fb86312897cda0 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Fri, 27 Jun 2025 15:50:32 +0530 Subject: [PATCH 296/343] fix: composer --- composer.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.lock b/composer.lock index 60d039c562..05c8a49512 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "081385d2d7081b323429e45ffd3b3b33", + "content-hash": "55bc52686a08d64930e6af7411ac0654", "packages": [ { "name": "adhocore/jwt", From 63a02e11ac30f9a6d3063837531798ebc0d73737 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 27 Jun 2025 18:42:02 +0400 Subject: [PATCH 297/343] Fix default value assignment in Mapper class to handle null cases --- src/Appwrite/GraphQL/Types/Mapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index 3c7915bc96..db330034b3 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -226,7 +226,7 @@ class Mapper ]; if (!$rule['required']) { - $fields[$escapedKey]['defaultValue'] = $rule['default']; + $fields[$escapedKey]['defaultValue'] = $rule['default'] ?? ''; } } From 332c82e61eb5ea6e3fe3f1ff1cb44657966bb160 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 30 Jun 2025 19:00:54 +0530 Subject: [PATCH 298/343] fix: lint --- app/controllers/general.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index d509c9bb18..ae5b17cee6 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -11,7 +11,6 @@ use Appwrite\Event\Event; use Appwrite\Event\Func; use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception as AppwriteException; -use Appwrite\Network\Platform; use Appwrite\Network\Validator\Origin; use Appwrite\Platform\Appwrite; use Appwrite\SDK\Method; From 9242ef85ebcb5b2f1fbcd631f39762aae3e6f2f5 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 30 Jun 2025 19:03:12 +0530 Subject: [PATCH 299/343] fix: order --- app/controllers/general.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index ae5b17cee6..4483700d2b 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1034,9 +1034,9 @@ App::init() $originValidator = new Origin($platforms); if ( - $devKey->isEmpty() + !$originValidator->isValid($origin) + && $devKey->isEmpty() && !empty($origin) - && !$originValidator->isValid($origin) && \in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE]) && $route->getLabel('origin', false) !== '*' && empty($request->getHeader('x-appwrite-key', '')) From 39db3a3066e9d53df5717b0f670ee2ccab55ab57 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 30 Jun 2025 19:07:49 +0530 Subject: [PATCH 300/343] fix: order --- app/controllers/general.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 4483700d2b..76fd3117e0 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1034,9 +1034,8 @@ App::init() $originValidator = new Origin($platforms); if ( - !$originValidator->isValid($origin) - && $devKey->isEmpty() - && !empty($origin) + $devKey->isEmpty() + && !$originValidator->isValid($origin) && \in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE]) && $route->getLabel('origin', false) !== '*' && empty($request->getHeader('x-appwrite-key', '')) From 8a2ccd32b4307ac110d89e798112ed82097ad75a Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 30 Jun 2025 19:09:15 +0530 Subject: [PATCH 301/343] fix: remove redundant check --- app/realtime.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/realtime.php b/app/realtime.php index bb0d4da78c..02b71c1780 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -559,7 +559,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $origin = $request->getOrigin(); $originValidator = new Origin($platforms); - if (!empty($origin) && !$originValidator->isValid($origin) && $project->getId() !== 'console') { + if (!$originValidator->isValid($origin) && $project->getId() !== 'console') { throw new Exception(Exception::REALTIME_POLICY_VIOLATION, $originValidator->getDescription()); } From 843d4d9ea0a631395fec90e38f05f37ff8dd03ac Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 30 Jun 2025 19:29:42 +0530 Subject: [PATCH 302/343] chore: use origin validator --- app/init/resources.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/init/resources.php b/app/init/resources.php index 5881fcef07..84473bb0d6 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -20,6 +20,7 @@ use Appwrite\Event\Webhook; use Appwrite\Extend\Exception; use Appwrite\GraphQL\Schema; use Appwrite\Network\Platform; +use Appwrite\Network\Validator\Origin; use Appwrite\Utopia\Request; use Executor\Executor; use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; @@ -943,7 +944,7 @@ App::setResource('httpReferrer', function (Request $request): string { return $referrer; }, ['request']); -App::setResource('httpReferrerSafe', function (Request $request, string $httpReferrer, array $clients, Database $dbForPlatform, Document $project, App $utopia): string { +App::setResource('httpReferrerSafe', function (Request $request, string $httpReferrer, array $platforms, Database $dbForPlatform, Document $project, App $utopia): string { $origin = \parse_url($request->getOrigin($httpReferrer), PHP_URL_HOST); $protocol = \parse_url($request->getOrigin($httpReferrer), PHP_URL_SCHEME); $port = \parse_url($request->getOrigin($httpReferrer), PHP_URL_PORT); @@ -956,8 +957,8 @@ App::setResource('httpReferrerSafe', function (Request $request, string $httpRef } // Safe if added as web platform - $validator = new Hostname($clients); - if ($validator->isValid($origin)) { + $originValidator = new Origin($platforms); + if ($originValidator->isValid($origin)) { return $referrer; } @@ -985,4 +986,4 @@ App::setResource('httpReferrerSafe', function (Request $request, string $httpRef $port = \parse_url($request->getOrigin($httpReferrer), PHP_URL_PORT); $referrer = (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $origin . (!empty($port) ? ':' . $port : ''); return $referrer; -}, ['request', 'httpReferrer', 'clients', 'dbForPlatform', 'project', 'utopia']); +}, ['request', 'httpReferrer', 'platforms', 'dbForPlatform', 'project', 'utopia']); From db56361ad987f78bd82b153c284e043315385a8b Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 30 Jun 2025 19:48:05 +0530 Subject: [PATCH 303/343] fix: add back empty checks --- app/controllers/general.php | 1 + app/realtime.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 76fd3117e0..ae5b17cee6 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1035,6 +1035,7 @@ App::init() if ( $devKey->isEmpty() + && !empty($origin) && !$originValidator->isValid($origin) && \in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE]) && $route->getLabel('origin', false) !== '*' diff --git a/app/realtime.php b/app/realtime.php index 02b71c1780..bb0d4da78c 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -559,7 +559,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $origin = $request->getOrigin(); $originValidator = new Origin($platforms); - if (!$originValidator->isValid($origin) && $project->getId() !== 'console') { + if (!empty($origin) && !$originValidator->isValid($origin) && $project->getId() !== 'console') { throw new Exception(Exception::REALTIME_POLICY_VIOLATION, $originValidator->getDescription()); } From 2d00052db64cd613f431119a4fbd5dc0859c6de3 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 30 Jun 2025 20:50:29 +0530 Subject: [PATCH 304/343] fix: general test --- app/init/resources.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/init/resources.php b/app/init/resources.php index 84473bb0d6..eb922268ec 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -958,7 +958,7 @@ App::setResource('httpReferrerSafe', function (Request $request, string $httpRef // Safe if added as web platform $originValidator = new Origin($platforms); - if ($originValidator->isValid($origin)) { + if ($originValidator->isValid($request->getOrigin($httpReferrer))) { return $referrer; } From d6326758a8cabca9ab96e6b5b4ffe5c61c58ec51 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Mon, 30 Jun 2025 20:58:00 +0400 Subject: [PATCH 305/343] patch: increase cache ttl to ensure hits --- app/controllers/shared/api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 735487339f..58b0f9a8a9 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -564,7 +564,7 @@ App::init() $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); - $timestamp = 60 * 60 * 24 * 30; + $timestamp = 60 * 60 * 24 * 180; // Temporarily increase the TTL to 180 day to ensure files in the cache are still fetched. $data = $cache->load($key, $timestamp); if (!empty($data) && !$cacheLog->isEmpty()) { From fd7628efe84308b6c04b17cb6fa2f48854f32149 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Mon, 30 Jun 2025 21:03:30 +0400 Subject: [PATCH 306/343] refactor: streamline cache handling in App::shutdown() and ensure file modification time updates --- app/controllers/shared/api.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 58b0f9a8a9..76fe177b0b 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -564,7 +564,7 @@ App::init() $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); - $timestamp = 60 * 60 * 24 * 180; // Temporarily increase the TTL to 180 day to ensure files in the cache are still fetched. + $timestamp = 60 * 60 * 24 * 180; // Temporarily increase the TTL to 180 day to ensure files in the cache are still fetched. $data = $cache->load($key, $timestamp); if (!empty($data) && !$cacheLog->isEmpty()) { @@ -831,6 +831,10 @@ App::shutdown() $resourceType = $parseLabel($pattern, $responsePayload, $requestParams, $user); } + $cache = new Cache( + new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) + ); + $key = $request->cacheIdentifier(); $signature = md5($data['payload']); $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); @@ -848,12 +852,11 @@ App::shutdown() } elseif (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_CACHE_UPDATE)) > $accessedAt) { $cacheLog->setAttribute('accessedAt', $now); Authorization::skip(fn () => $dbForProject->updateDocument('cache', $cacheLog->getId(), $cacheLog)); + // Overwrite the file every APP_CACHE_UPDATE seconds to update the file modified time that is used in the TTL checks in cache->load() + $cache->save($key, $data['payload']); } if ($signature !== $cacheLog->getAttribute('signature')) { - $cache = new Cache( - new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) - ); $cache->save($key, $data['payload']); } } From 609e1adcf02a7facc35b40539c8a100ca1afba11 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 30 Jun 2025 22:27:18 -0400 Subject: [PATCH 307/343] Catch --- app/controllers/api/users.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index d7def69464..b3ae17dc91 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -649,6 +649,8 @@ App::get('/v1/users') $total = $dbForProject->count('users', $filterQueries, APP_LIMIT_COUNT); } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } $response->dynamic(new Document([ 'users' => $users, From 98dccf6d15ae8f20a182429d922ffce6b7b10cce Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 30 Jun 2025 22:27:29 -0400 Subject: [PATCH 308/343] Map null on missing default --- src/Appwrite/GraphQL/Types/Mapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index db330034b3..347642e5a1 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -226,7 +226,7 @@ class Mapper ]; if (!$rule['required']) { - $fields[$escapedKey]['defaultValue'] = $rule['default'] ?? ''; + $fields[$escapedKey]['defaultValue'] = $rule['default'] ?? null; } } From a1af742c4b2b812c56c25a57e42403436d397d60 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 30 Jun 2025 22:28:09 -0400 Subject: [PATCH 309/343] Update lock --- composer.json | 2 +- composer.lock | 54 +++++++++++++++++++++++++-------------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/composer.json b/composer.json index 76b7146b96..073e667cdb 100644 --- a/composer.json +++ b/composer.json @@ -67,7 +67,7 @@ "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", "utopia-php/preloader": "0.2.*", - "utopia-php/queue": "^0.12.0", + "utopia-php/queue": "0.12.*", "utopia-php/registry": "0.5.*", "utopia-php/storage": "0.18.*", "utopia-php/swoole": "0.8.*", diff --git a/composer.lock b/composer.lock index 2ac0062d6d..985f2187b8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "dbd3be6cce9f2a5e551be564cdabcbe5", + "content-hash": "beacba1fc087db3ab9f9d718b28c5876", "packages": [ { "name": "adhocore/jwt", @@ -1890,16 +1890,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.45", + "version": "3.0.46", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8" + "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/bd81b90d5963c6b9d87de50357585375223f4dd8", - "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", + "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", "shasum": "" }, "require": { @@ -1980,7 +1980,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.45" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.46" }, "funding": [ { @@ -1996,7 +1996,7 @@ "type": "tidelift" } ], - "time": "2025-06-22T22:54:43+00:00" + "time": "2025-06-26T16:29:55+00:00" }, { "name": "psr/container", @@ -2559,16 +2559,16 @@ }, { "name": "symfony/http-client", - "version": "v7.3.0", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9" + "reference": "4403d87a2c16f33345dca93407a8714ee8c05a64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/57e4fb86314015a695a750ace358d07a7e37b8a9", - "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9", + "url": "https://api.github.com/repos/symfony/http-client/zipball/4403d87a2c16f33345dca93407a8714ee8c05a64", + "reference": "4403d87a2c16f33345dca93407a8714ee8c05a64", "shasum": "" }, "require": { @@ -2580,6 +2580,7 @@ }, "conflict": { "amphp/amp": "<2.5", + "amphp/socket": "<1.1", "php-http/discovery": "<1.15", "symfony/http-foundation": "<6.4" }, @@ -2592,7 +2593,6 @@ "require-dev": { "amphp/http-client": "^4.2.1|^5.0", "amphp/http-tunnel": "^1.0|^2.0", - "amphp/socket": "^1.1", "guzzlehttp/promises": "^1.4|^2.0", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", @@ -2634,7 +2634,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.3.0" + "source": "https://github.com/symfony/http-client/tree/v7.3.1" }, "funding": [ { @@ -2650,7 +2650,7 @@ "type": "tidelift" } ], - "time": "2025-05-02T08:23:16+00:00" + "time": "2025-06-28T07:58:39+00:00" }, { "name": "symfony/http-client-contracts", @@ -2972,16 +2972,16 @@ }, { "name": "tbachert/spi", - "version": "v1.0.3", + "version": "v1.0.5", "source": { "type": "git", "url": "https://github.com/Nevay/spi.git", - "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a" + "reference": "e7078767866d0a9e0f91d3f9d42a832df5e39002" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Nevay/spi/zipball/506a79c98e1a51522e76ee921ccb6c62d52faf3a", - "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a", + "url": "https://api.github.com/repos/Nevay/spi/zipball/e7078767866d0a9e0f91d3f9d42a832df5e39002", + "reference": "e7078767866d0a9e0f91d3f9d42a832df5e39002", "shasum": "" }, "require": { @@ -2999,7 +2999,7 @@ "extra": { "class": "Nevay\\SPI\\Composer\\Plugin", "branch-alias": { - "dev-main": "0.2.x-dev" + "dev-main": "1.0.x-dev" }, "plugin-optional": true }, @@ -3018,9 +3018,9 @@ ], "support": { "issues": "https://github.com/Nevay/spi/issues", - "source": "https://github.com/Nevay/spi/tree/v1.0.3" + "source": "https://github.com/Nevay/spi/tree/v1.0.5" }, - "time": "2025-04-02T19:38:14+00:00" + "time": "2025-06-29T15:42:06+00:00" }, { "name": "thecodingmachine/safe", @@ -7267,16 +7267,16 @@ }, { "name": "symfony/console", - "version": "v7.3.0", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" + "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", - "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", + "url": "https://api.github.com/repos/symfony/console/zipball/9e27aecde8f506ba0fd1d9989620c04a87697101", + "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101", "shasum": "" }, "require": { @@ -7341,7 +7341,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.0" + "source": "https://github.com/symfony/console/tree/v7.3.1" }, "funding": [ { @@ -7357,7 +7357,7 @@ "type": "tidelift" } ], - "time": "2025-05-24T10:34:04+00:00" + "time": "2025-06-27T19:55:54+00:00" }, { "name": "symfony/filesystem", From 385e4e14b881d4755e7aa9bf5fd69a2f931b68ac Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 1 Jul 2025 17:33:11 +0530 Subject: [PATCH 310/343] add: delay, retries. --- .../Databases/DatabasesCustomServerTest.php | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index e84c760c86..b38b1202c6 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -1470,9 +1470,24 @@ class DatabasesCustomServerTest extends Scope $this->assertCount(64, $collection['body']['attributes']); $this->assertCount(0, $collection['body']['indexes']); - foreach ($collection['body']['attributes'] as $attribute) { - $this->assertEquals('available', $attribute['status'], 'attribute: ' . $attribute['key']); - } + $this->assertEventually(function () use ($databaseId, $collectionId) { + $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + foreach ($collection['body']['attributes'] ?? [] as $attribute) { + $this->assertEquals( + 'available', + $attribute['status'], + 'attribute: ' . $attribute['key'] + ); + } + + return true; + }, 60000, 500); + // Test indexLimit = 64 // MariaDB, MySQL, and MongoDB create 6 indexes per new collection From 4d0bd1d74fb0d572b3838aca9526123f0a101e61 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 1 Jul 2025 18:10:19 +0530 Subject: [PATCH 311/343] add: delay, retries. --- tests/e2e/Services/Databases/DatabasesBase.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index e34691839d..a9a6c6e1db 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -1414,9 +1414,20 @@ trait DatabasesBase $this->assertEquals($releaseYearIndex['body']['key'], $movies['body']['indexes'][1]['key']); $this->assertEquals($releaseWithDate1['body']['key'], $movies['body']['indexes'][2]['key']); $this->assertEquals($releaseWithDate2['body']['key'], $movies['body']['indexes'][3]['key']); - foreach ($movies['body']['indexes'] as $index) { - $this->assertEquals('available', $index['status']); - } + + $this->assertEventually(function () use ($databaseId, $data) { + $movies = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + foreach ($movies['body']['indexes'] as $index) { + $this->assertEquals('available', $index['status']); + } + + return true; + }, 60000, 500); return $data; } From 99ccd64b4c9418c51e172857974b441b47cb4982 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 1 Jul 2025 18:24:05 -0400 Subject: [PATCH 312/343] =?UTF-8?q?Revert=20"chore:=20update=20composer.js?= =?UTF-8?q?on=20and=20composer.lock=20to=20include=20appwrite-lab=E2=80=A6?= =?UTF-8?q?"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/api/users.php | 2 - composer.json | 2 +- composer.lock | 256 ++++++++++++-------------- src/Appwrite/GraphQL/Types/Mapper.php | 2 +- 4 files changed, 124 insertions(+), 138 deletions(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index b3ae17dc91..d7def69464 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -649,8 +649,6 @@ App::get('/v1/users') $total = $dbForProject->count('users', $filterQueries, APP_LIMIT_COUNT); } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } $response->dynamic(new Document([ 'users' => $users, diff --git a/composer.json b/composer.json index 073e667cdb..4c36ab125d 100644 --- a/composer.json +++ b/composer.json @@ -67,7 +67,7 @@ "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", "utopia-php/preloader": "0.2.*", - "utopia-php/queue": "0.12.*", + "utopia-php/queue": "0.11.0", "utopia-php/registry": "0.5.*", "utopia-php/storage": "0.18.*", "utopia-php/swoole": "0.8.*", diff --git a/composer.lock b/composer.lock index 985f2187b8..05c8a49512 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "beacba1fc087db3ab9f9d718b28c5876", + "content-hash": "55bc52686a08d64930e6af7411ac0654", "packages": [ { "name": "adhocore/jwt", @@ -67,99 +67,6 @@ ], "time": "2025-02-18T01:00:50+00:00" }, - { - "name": "appwrite-labs/php-amqplib", - "version": "0.1.1", - "source": { - "type": "git", - "url": "https://github.com/appwrite-labs/php-amqplib.git", - "reference": "bd380cbd63c8c0f063a3893b7a0b889d40876861" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/appwrite-labs/php-amqplib/zipball/bd380cbd63c8c0f063a3893b7a0b889d40876861", - "reference": "bd380cbd63c8c0f063a3893b7a0b889d40876861", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "ext-sockets": "*", - "php": "^7.2||^8.0", - "phpseclib/phpseclib": "^2.0|^3.0" - }, - "conflict": { - "php": "7.4.0 - 7.4.1" - }, - "replace": { - "php-amqplib/php-amqplib": "self.version", - "videlalvaro/php-amqplib": "self.version" - }, - "require-dev": { - "ext-curl": "*", - "nategood/httpful": "^0.2.20", - "phpunit/phpunit": "^7.5|^9.5", - "squizlabs/php_codesniffer": "^3.6", - "swoole/ide-helper": "^5.0" - }, - "suggest": { - "ext-swoole": "For Swoole coroutine support" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "psr-4": { - "PhpAmqpLib\\": "PhpAmqpLib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-2.1-or-later" - ], - "authors": [ - { - "name": "Appwrite Labs", - "email": "team@appwrite.io", - "role": "Fork Maintainer" - }, - { - "name": "Alvaro Videla", - "role": "Original Maintainer" - }, - { - "name": "Raúl Araya", - "email": "nubeiro@gmail.com", - "role": "Maintainer" - }, - { - "name": "Luke Bakken", - "email": "luke@bakken.io", - "role": "Maintainer" - }, - { - "name": "Ramūnas Dronga", - "email": "github@ramuno.lt", - "role": "Maintainer" - } - ], - "description": "Fork of php-amqplib with Swoole coroutine support. A pure PHP implementation of the AMQP protocol tested against RabbitMQ.", - "homepage": "https://github.com/appwrite-labs/php-amqplib/", - "keywords": [ - "async", - "coroutine", - "message", - "queue", - "rabbitmq", - "swoole" - ], - "support": { - "source": "https://github.com/appwrite-labs/php-amqplib/tree/0.1.1" - }, - "time": "2025-06-24T18:12:57+00:00" - }, { "name": "appwrite/appwrite", "version": "11.1.0", @@ -1728,6 +1635,87 @@ }, "time": "2020-10-15T08:29:30+00:00" }, + { + "name": "php-amqplib/php-amqplib", + "version": "v3.7.3", + "source": { + "type": "git", + "url": "https://github.com/php-amqplib/php-amqplib.git", + "reference": "9f50fe69a9f1a19e2cb25596a354d705de36fe59" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/9f50fe69a9f1a19e2cb25596a354d705de36fe59", + "reference": "9f50fe69a9f1a19e2cb25596a354d705de36fe59", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-sockets": "*", + "php": "^7.2||^8.0", + "phpseclib/phpseclib": "^2.0|^3.0" + }, + "conflict": { + "php": "7.4.0 - 7.4.1" + }, + "replace": { + "videlalvaro/php-amqplib": "self.version" + }, + "require-dev": { + "ext-curl": "*", + "nategood/httpful": "^0.2.20", + "phpunit/phpunit": "^7.5|^9.5", + "squizlabs/php_codesniffer": "^3.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpAmqpLib\\": "PhpAmqpLib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Alvaro Videla", + "role": "Original Maintainer" + }, + { + "name": "Raúl Araya", + "email": "nubeiro@gmail.com", + "role": "Maintainer" + }, + { + "name": "Luke Bakken", + "email": "luke@bakken.io", + "role": "Maintainer" + }, + { + "name": "Ramūnas Dronga", + "email": "github@ramuno.lt", + "role": "Maintainer" + } + ], + "description": "Formerly videlalvaro/php-amqplib. This library is a pure PHP implementation of the AMQP protocol. It's been tested against RabbitMQ.", + "homepage": "https://github.com/php-amqplib/php-amqplib/", + "keywords": [ + "message", + "queue", + "rabbitmq" + ], + "support": { + "issues": "https://github.com/php-amqplib/php-amqplib/issues", + "source": "https://github.com/php-amqplib/php-amqplib/tree/v3.7.3" + }, + "time": "2025-02-18T20:11:13+00:00" + }, { "name": "php-http/discovery", "version": "1.20.0", @@ -1890,16 +1878,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.46", + "version": "3.0.45", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6" + "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", - "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/bd81b90d5963c6b9d87de50357585375223f4dd8", + "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8", "shasum": "" }, "require": { @@ -1980,7 +1968,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.46" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.45" }, "funding": [ { @@ -1996,7 +1984,7 @@ "type": "tidelift" } ], - "time": "2025-06-26T16:29:55+00:00" + "time": "2025-06-22T22:54:43+00:00" }, { "name": "psr/container", @@ -2559,16 +2547,16 @@ }, { "name": "symfony/http-client", - "version": "v7.3.1", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "4403d87a2c16f33345dca93407a8714ee8c05a64" + "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/4403d87a2c16f33345dca93407a8714ee8c05a64", - "reference": "4403d87a2c16f33345dca93407a8714ee8c05a64", + "url": "https://api.github.com/repos/symfony/http-client/zipball/57e4fb86314015a695a750ace358d07a7e37b8a9", + "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9", "shasum": "" }, "require": { @@ -2580,7 +2568,6 @@ }, "conflict": { "amphp/amp": "<2.5", - "amphp/socket": "<1.1", "php-http/discovery": "<1.15", "symfony/http-foundation": "<6.4" }, @@ -2593,6 +2580,7 @@ "require-dev": { "amphp/http-client": "^4.2.1|^5.0", "amphp/http-tunnel": "^1.0|^2.0", + "amphp/socket": "^1.1", "guzzlehttp/promises": "^1.4|^2.0", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", @@ -2634,7 +2622,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.3.1" + "source": "https://github.com/symfony/http-client/tree/v7.3.0" }, "funding": [ { @@ -2650,7 +2638,7 @@ "type": "tidelift" } ], - "time": "2025-06-28T07:58:39+00:00" + "time": "2025-05-02T08:23:16+00:00" }, { "name": "symfony/http-client-contracts", @@ -2972,16 +2960,16 @@ }, { "name": "tbachert/spi", - "version": "v1.0.5", + "version": "v1.0.3", "source": { "type": "git", "url": "https://github.com/Nevay/spi.git", - "reference": "e7078767866d0a9e0f91d3f9d42a832df5e39002" + "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Nevay/spi/zipball/e7078767866d0a9e0f91d3f9d42a832df5e39002", - "reference": "e7078767866d0a9e0f91d3f9d42a832df5e39002", + "url": "https://api.github.com/repos/Nevay/spi/zipball/506a79c98e1a51522e76ee921ccb6c62d52faf3a", + "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a", "shasum": "" }, "require": { @@ -2999,7 +2987,7 @@ "extra": { "class": "Nevay\\SPI\\Composer\\Plugin", "branch-alias": { - "dev-main": "1.0.x-dev" + "dev-main": "0.2.x-dev" }, "plugin-optional": true }, @@ -3018,9 +3006,9 @@ ], "support": { "issues": "https://github.com/Nevay/spi/issues", - "source": "https://github.com/Nevay/spi/tree/v1.0.5" + "source": "https://github.com/Nevay/spi/tree/v1.0.3" }, - "time": "2025-06-29T15:42:06+00:00" + "time": "2025-04-02T19:38:14+00:00" }, { "name": "thecodingmachine/safe", @@ -4111,16 +4099,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.9", + "version": "0.7.8", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "b061f523513b071ef7168e6dc1441364eb73f308" + "reference": "e3a4536c46f10988b1a446ec6b8dd8a9914be854" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/b061f523513b071ef7168e6dc1441364eb73f308", - "reference": "b061f523513b071ef7168e6dc1441364eb73f308", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/e3a4536c46f10988b1a446ec6b8dd8a9914be854", + "reference": "e3a4536c46f10988b1a446ec6b8dd8a9914be854", "shasum": "" }, "require": { @@ -4129,7 +4117,7 @@ "php": ">=8.0", "utopia-php/cli": "0.15.*", "utopia-php/framework": "0.33.*", - "utopia-php/queue": "^0.12.0" + "utopia-php/queue": "0.11.*" }, "require-dev": { "laravel/pint": "1.*", @@ -4155,9 +4143,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.9" + "source": "https://github.com/utopia-php/platform/tree/0.7.8" }, - "time": "2025-06-24T20:21:05+00:00" + "time": "2025-05-30T10:05:43+00:00" }, { "name": "utopia-php/pools", @@ -4266,21 +4254,21 @@ }, { "name": "utopia-php/queue", - "version": "0.12.0", + "version": "0.11.0", "source": { "type": "git", "url": "https://github.com/utopia-php/queue.git", - "reference": "3a7603ee712c592bfc54af4a76f0426c428b5574" + "reference": "06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/queue/zipball/3a7603ee712c592bfc54af4a76f0426c428b5574", - "reference": "3a7603ee712c592bfc54af4a76f0426c428b5574", + "url": "https://api.github.com/repos/utopia-php/queue/zipball/06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5", + "reference": "06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5", "shasum": "" }, "require": { - "appwrite-labs/php-amqplib": "^0.1", "php": ">=8.3", + "php-amqplib/php-amqplib": "^3.7", "utopia-php/cli": "0.15.*", "utopia-php/fetch": "0.4.*", "utopia-php/framework": "0.33.*", @@ -4326,9 +4314,9 @@ ], "support": { "issues": "https://github.com/utopia-php/queue/issues", - "source": "https://github.com/utopia-php/queue/tree/0.12.0" + "source": "https://github.com/utopia-php/queue/tree/0.11.0" }, - "time": "2025-06-24T18:58:38+00:00" + "time": "2025-05-30T09:52:38+00:00" }, { "name": "utopia-php/registry", @@ -7267,16 +7255,16 @@ }, { "name": "symfony/console", - "version": "v7.3.1", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101" + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/9e27aecde8f506ba0fd1d9989620c04a87697101", - "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101", + "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", "shasum": "" }, "require": { @@ -7341,7 +7329,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.1" + "source": "https://github.com/symfony/console/tree/v7.3.0" }, "funding": [ { @@ -7357,7 +7345,7 @@ "type": "tidelift" } ], - "time": "2025-06-27T19:55:54+00:00" + "time": "2025-05-24T10:34:04+00:00" }, { "name": "symfony/filesystem", diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index 347642e5a1..3c7915bc96 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -226,7 +226,7 @@ class Mapper ]; if (!$rule['required']) { - $fields[$escapedKey]['defaultValue'] = $rule['default'] ?? null; + $fields[$escapedKey]['defaultValue'] = $rule['default']; } } From 1cd69e26f884bbf532fc32a329880e90a18cc143 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 1 Jul 2025 18:24:52 -0400 Subject: [PATCH 313/343] =?UTF-8?q?Reapply=20"chore:=20update=20composer.j?= =?UTF-8?q?son=20and=20composer.lock=20to=20include=20appwrite-lab?= =?UTF-8?q?=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 99ccd64b4c9418c51e172857974b441b47cb4982. --- app/controllers/api/users.php | 2 ++ src/Appwrite/GraphQL/Types/Mapper.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index d7def69464..b3ae17dc91 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -649,6 +649,8 @@ App::get('/v1/users') $total = $dbForProject->count('users', $filterQueries, APP_LIMIT_COUNT); } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } $response->dynamic(new Document([ 'users' => $users, diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index 3c7915bc96..347642e5a1 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -226,7 +226,7 @@ class Mapper ]; if (!$rule['required']) { - $fields[$escapedKey]['defaultValue'] = $rule['default']; + $fields[$escapedKey]['defaultValue'] = $rule['default'] ?? null; } } From aa9a82d8ce3b5c2c9509f620069879d0bc7416b3 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 2 Jul 2025 14:32:16 +0530 Subject: [PATCH 314/343] fix: document attribute type. --- app/controllers/api/migrations.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 92fca88744..6fae5204b2 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -410,8 +410,8 @@ App::post('/v1/migrations/csv') 'resources' => $resources, 'resourceId' => $resourceId, 'resourceType' => Resource::TYPE_DATABASE, - 'statusCounters' => [], - 'resourceData' => [], + 'statusCounters' => '{}', + 'resourceData' => '{}', 'errors' => [], 'options' => [ 'path' => $newPath, From eb1d4c68ea5f10b582fb84e7669796cb507c9994 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 2 Jul 2025 14:54:25 +0530 Subject: [PATCH 315/343] add: logging. --- src/Appwrite/Platform/Workers/Migrations.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 573772835e..9c5f9b6f79 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -154,6 +154,8 @@ class Migrations extends Action $this->sourceReport = $migrationSource->report(); + Console::log(json_encode(['stage' => 'processSource', 'source' => $source], JSON_PRETTY_PRINT)); + return $migrationSource; } @@ -164,6 +166,8 @@ class Migrations extends Action { $destination = $migration->getAttribute('destination'); + Console::log(json_encode(['stage' => 'processDestination', 'destination' => $destination], JSON_PRETTY_PRINT)); + return match ($destination) { DestinationAppwrite::getName() => new DestinationAppwrite( $this->project->getId(), @@ -214,6 +218,12 @@ class Migrations extends Action ->setPayload($clonedMigrationDocument->getArrayCopy(), ['options', 'credentials']) ->trigger(); + Console::log(json_encode([ + 'stage' => 'updateMigrationDocument', + 'migration' => $migration, + 'clonedMigration' => $clonedMigrationDocument + ], JSON_PRETTY_PRINT)); + return $this->dbForProject->updateDocument('migrations', $migration->getId(), $migration); } @@ -306,6 +316,15 @@ class Migrations extends Action $transfer->run( $migration->getAttribute('resources'), function () use ($migration, $transfer, $projectDocument, $queueForRealtime) { + Console::log(json_encode([ + 'stage' => 'transfer#run', + 'migration' => $migration, + 'details' => [ + 'resourceData' => $transfer->getCache(), + 'statusCounters' => $transfer->getStatusCounters() + ] + ], JSON_PRETTY_PRINT)); + $migration->setAttribute('resourceData', json_encode($transfer->getCache())); $migration->setAttribute('statusCounters', json_encode($transfer->getStatusCounters())); $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); From d34635becb6054b804c3e9617c9e30e5460716ce Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 2 Jul 2025 15:13:42 +0530 Subject: [PATCH 316/343] add: logging for errors. --- src/Appwrite/Platform/Workers/Migrations.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 9c5f9b6f79..3cf43b5c1b 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -332,7 +332,13 @@ class Migrations extends Action $migration->getAttribute('resourceId'), $migration->getAttribute('resourceType') ); + } else { + Console::log(json_encode([ + 'stage' => 'source#errors', + 'errors' => $source->getErrors(), + ], JSON_PRETTY_PRINT)); } + $destination->shutDown(); $source->shutDown(); From 0e50fb7ec5ddc112c40075d69230c79ad7508094 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 2 Jul 2025 17:04:26 +0530 Subject: [PATCH 317/343] add: migrations lib logging for errors. --- composer.json | 2 +- composer.lock | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 4c36ab125d..58cc03457b 100644 --- a/composer.json +++ b/composer.json @@ -62,7 +62,7 @@ "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.18.*", - "utopia-php/migration": "0.10.*", + "utopia-php/migration": "logging-dev", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", diff --git a/composer.lock b/composer.lock index 05c8a49512..b78635d9af 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "55bc52686a08d64930e6af7411ac0654", + "content-hash": "63bb9b3d7f61273cd71bf98e44ecf83c", "packages": [ { "name": "adhocore/jwt", @@ -3993,16 +3993,16 @@ }, { "name": "utopia-php/migration", - "version": "0.10.1", + "version": "dev-logging", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "ea1c585df7ec5f346f061a11581fc9a91679966f" + "reference": "c6eb35992bc09ccb7210a95519bc12f313c05d28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/ea1c585df7ec5f346f061a11581fc9a91679966f", - "reference": "ea1c585df7ec5f346f061a11581fc9a91679966f", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/c6eb35992bc09ccb7210a95519bc12f313c05d28", + "reference": "c6eb35992bc09ccb7210a95519bc12f313c05d28", "shasum": "" }, "require": { @@ -4043,9 +4043,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.10.1" + "source": "https://github.com/utopia-php/migration/tree/logging" }, - "time": "2025-05-26T15:29:19+00:00" + "time": "2025-07-02T11:33:13+00:00" }, { "name": "utopia-php/orchestration", @@ -8236,7 +8236,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/migration": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { From fc1a9a4e16dba695a430f989692fdeff34a174f4 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 2 Jul 2025 19:13:13 +0530 Subject: [PATCH 318/343] fix: path and revert deps. --- app/controllers/api/migrations.php | 2 +- composer.json | 2 +- composer.lock | 70 ++++++++++---------- src/Appwrite/Platform/Workers/Migrations.php | 24 ------- 4 files changed, 36 insertions(+), 62 deletions(-) diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 6fae5204b2..85751811ba 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -361,7 +361,7 @@ App::post('/v1/migrations/csv') $hasCompression = $compression !== Compression::NONE; $migrationId = ID::unique(); - $newPath = $deviceForImports->getPath('/' . $migrationId . '_' . $fileId . '.csv'); + $newPath = $deviceForImports->getPath($migrationId . '_' . $fileId . '.csv'); if ($hasEncryption || $hasCompression) { $source = $deviceForFiles->read($path); diff --git a/composer.json b/composer.json index 58cc03457b..4c36ab125d 100644 --- a/composer.json +++ b/composer.json @@ -62,7 +62,7 @@ "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.18.*", - "utopia-php/migration": "logging-dev", + "utopia-php/migration": "0.10.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", diff --git a/composer.lock b/composer.lock index b78635d9af..b809b01124 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "63bb9b3d7f61273cd71bf98e44ecf83c", + "content-hash": "55bc52686a08d64930e6af7411ac0654", "packages": [ { "name": "adhocore/jwt", @@ -1878,16 +1878,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.45", + "version": "3.0.46", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8" + "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/bd81b90d5963c6b9d87de50357585375223f4dd8", - "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", + "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", "shasum": "" }, "require": { @@ -1968,7 +1968,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.45" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.46" }, "funding": [ { @@ -1984,7 +1984,7 @@ "type": "tidelift" } ], - "time": "2025-06-22T22:54:43+00:00" + "time": "2025-06-26T16:29:55+00:00" }, { "name": "psr/container", @@ -2547,16 +2547,16 @@ }, { "name": "symfony/http-client", - "version": "v7.3.0", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9" + "reference": "4403d87a2c16f33345dca93407a8714ee8c05a64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/57e4fb86314015a695a750ace358d07a7e37b8a9", - "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9", + "url": "https://api.github.com/repos/symfony/http-client/zipball/4403d87a2c16f33345dca93407a8714ee8c05a64", + "reference": "4403d87a2c16f33345dca93407a8714ee8c05a64", "shasum": "" }, "require": { @@ -2568,6 +2568,7 @@ }, "conflict": { "amphp/amp": "<2.5", + "amphp/socket": "<1.1", "php-http/discovery": "<1.15", "symfony/http-foundation": "<6.4" }, @@ -2580,7 +2581,6 @@ "require-dev": { "amphp/http-client": "^4.2.1|^5.0", "amphp/http-tunnel": "^1.0|^2.0", - "amphp/socket": "^1.1", "guzzlehttp/promises": "^1.4|^2.0", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", @@ -2622,7 +2622,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.3.0" + "source": "https://github.com/symfony/http-client/tree/v7.3.1" }, "funding": [ { @@ -2638,7 +2638,7 @@ "type": "tidelift" } ], - "time": "2025-05-02T08:23:16+00:00" + "time": "2025-06-28T07:58:39+00:00" }, { "name": "symfony/http-client-contracts", @@ -2960,16 +2960,16 @@ }, { "name": "tbachert/spi", - "version": "v1.0.3", + "version": "v1.0.5", "source": { "type": "git", "url": "https://github.com/Nevay/spi.git", - "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a" + "reference": "e7078767866d0a9e0f91d3f9d42a832df5e39002" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Nevay/spi/zipball/506a79c98e1a51522e76ee921ccb6c62d52faf3a", - "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a", + "url": "https://api.github.com/repos/Nevay/spi/zipball/e7078767866d0a9e0f91d3f9d42a832df5e39002", + "reference": "e7078767866d0a9e0f91d3f9d42a832df5e39002", "shasum": "" }, "require": { @@ -2987,7 +2987,7 @@ "extra": { "class": "Nevay\\SPI\\Composer\\Plugin", "branch-alias": { - "dev-main": "0.2.x-dev" + "dev-main": "1.0.x-dev" }, "plugin-optional": true }, @@ -3006,9 +3006,9 @@ ], "support": { "issues": "https://github.com/Nevay/spi/issues", - "source": "https://github.com/Nevay/spi/tree/v1.0.3" + "source": "https://github.com/Nevay/spi/tree/v1.0.5" }, - "time": "2025-04-02T19:38:14+00:00" + "time": "2025-06-29T15:42:06+00:00" }, { "name": "thecodingmachine/safe", @@ -3993,16 +3993,16 @@ }, { "name": "utopia-php/migration", - "version": "dev-logging", + "version": "0.10.1", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "c6eb35992bc09ccb7210a95519bc12f313c05d28" + "reference": "ea1c585df7ec5f346f061a11581fc9a91679966f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/c6eb35992bc09ccb7210a95519bc12f313c05d28", - "reference": "c6eb35992bc09ccb7210a95519bc12f313c05d28", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/ea1c585df7ec5f346f061a11581fc9a91679966f", + "reference": "ea1c585df7ec5f346f061a11581fc9a91679966f", "shasum": "" }, "require": { @@ -4043,9 +4043,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/logging" + "source": "https://github.com/utopia-php/migration/tree/0.10.1" }, - "time": "2025-07-02T11:33:13+00:00" + "time": "2025-05-26T15:29:19+00:00" }, { "name": "utopia-php/orchestration", @@ -7255,16 +7255,16 @@ }, { "name": "symfony/console", - "version": "v7.3.0", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" + "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", - "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", + "url": "https://api.github.com/repos/symfony/console/zipball/9e27aecde8f506ba0fd1d9989620c04a87697101", + "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101", "shasum": "" }, "require": { @@ -7329,7 +7329,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.0" + "source": "https://github.com/symfony/console/tree/v7.3.1" }, "funding": [ { @@ -7345,7 +7345,7 @@ "type": "tidelift" } ], - "time": "2025-05-24T10:34:04+00:00" + "time": "2025-06-27T19:55:54+00:00" }, { "name": "symfony/filesystem", @@ -8236,9 +8236,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/migration": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 3cf43b5c1b..807cf5ec9d 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -154,8 +154,6 @@ class Migrations extends Action $this->sourceReport = $migrationSource->report(); - Console::log(json_encode(['stage' => 'processSource', 'source' => $source], JSON_PRETTY_PRINT)); - return $migrationSource; } @@ -166,8 +164,6 @@ class Migrations extends Action { $destination = $migration->getAttribute('destination'); - Console::log(json_encode(['stage' => 'processDestination', 'destination' => $destination], JSON_PRETTY_PRINT)); - return match ($destination) { DestinationAppwrite::getName() => new DestinationAppwrite( $this->project->getId(), @@ -218,12 +214,6 @@ class Migrations extends Action ->setPayload($clonedMigrationDocument->getArrayCopy(), ['options', 'credentials']) ->trigger(); - Console::log(json_encode([ - 'stage' => 'updateMigrationDocument', - 'migration' => $migration, - 'clonedMigration' => $clonedMigrationDocument - ], JSON_PRETTY_PRINT)); - return $this->dbForProject->updateDocument('migrations', $migration->getId(), $migration); } @@ -316,15 +306,6 @@ class Migrations extends Action $transfer->run( $migration->getAttribute('resources'), function () use ($migration, $transfer, $projectDocument, $queueForRealtime) { - Console::log(json_encode([ - 'stage' => 'transfer#run', - 'migration' => $migration, - 'details' => [ - 'resourceData' => $transfer->getCache(), - 'statusCounters' => $transfer->getStatusCounters() - ] - ], JSON_PRETTY_PRINT)); - $migration->setAttribute('resourceData', json_encode($transfer->getCache())); $migration->setAttribute('statusCounters', json_encode($transfer->getStatusCounters())); $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); @@ -332,11 +313,6 @@ class Migrations extends Action $migration->getAttribute('resourceId'), $migration->getAttribute('resourceType') ); - } else { - Console::log(json_encode([ - 'stage' => 'source#errors', - 'errors' => $source->getErrors(), - ], JSON_PRETTY_PRINT)); } $destination->shutDown(); From 6d792fcb6ce28acbd3be2105355272c32e5e087b Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 2 Jul 2025 19:20:30 +0530 Subject: [PATCH 319/343] revert: lock. --- composer.lock | 52 +++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/composer.lock b/composer.lock index b809b01124..05c8a49512 100644 --- a/composer.lock +++ b/composer.lock @@ -1878,16 +1878,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.46", + "version": "3.0.45", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6" + "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", - "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/bd81b90d5963c6b9d87de50357585375223f4dd8", + "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8", "shasum": "" }, "require": { @@ -1968,7 +1968,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.46" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.45" }, "funding": [ { @@ -1984,7 +1984,7 @@ "type": "tidelift" } ], - "time": "2025-06-26T16:29:55+00:00" + "time": "2025-06-22T22:54:43+00:00" }, { "name": "psr/container", @@ -2547,16 +2547,16 @@ }, { "name": "symfony/http-client", - "version": "v7.3.1", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "4403d87a2c16f33345dca93407a8714ee8c05a64" + "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/4403d87a2c16f33345dca93407a8714ee8c05a64", - "reference": "4403d87a2c16f33345dca93407a8714ee8c05a64", + "url": "https://api.github.com/repos/symfony/http-client/zipball/57e4fb86314015a695a750ace358d07a7e37b8a9", + "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9", "shasum": "" }, "require": { @@ -2568,7 +2568,6 @@ }, "conflict": { "amphp/amp": "<2.5", - "amphp/socket": "<1.1", "php-http/discovery": "<1.15", "symfony/http-foundation": "<6.4" }, @@ -2581,6 +2580,7 @@ "require-dev": { "amphp/http-client": "^4.2.1|^5.0", "amphp/http-tunnel": "^1.0|^2.0", + "amphp/socket": "^1.1", "guzzlehttp/promises": "^1.4|^2.0", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", @@ -2622,7 +2622,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.3.1" + "source": "https://github.com/symfony/http-client/tree/v7.3.0" }, "funding": [ { @@ -2638,7 +2638,7 @@ "type": "tidelift" } ], - "time": "2025-06-28T07:58:39+00:00" + "time": "2025-05-02T08:23:16+00:00" }, { "name": "symfony/http-client-contracts", @@ -2960,16 +2960,16 @@ }, { "name": "tbachert/spi", - "version": "v1.0.5", + "version": "v1.0.3", "source": { "type": "git", "url": "https://github.com/Nevay/spi.git", - "reference": "e7078767866d0a9e0f91d3f9d42a832df5e39002" + "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Nevay/spi/zipball/e7078767866d0a9e0f91d3f9d42a832df5e39002", - "reference": "e7078767866d0a9e0f91d3f9d42a832df5e39002", + "url": "https://api.github.com/repos/Nevay/spi/zipball/506a79c98e1a51522e76ee921ccb6c62d52faf3a", + "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a", "shasum": "" }, "require": { @@ -2987,7 +2987,7 @@ "extra": { "class": "Nevay\\SPI\\Composer\\Plugin", "branch-alias": { - "dev-main": "1.0.x-dev" + "dev-main": "0.2.x-dev" }, "plugin-optional": true }, @@ -3006,9 +3006,9 @@ ], "support": { "issues": "https://github.com/Nevay/spi/issues", - "source": "https://github.com/Nevay/spi/tree/v1.0.5" + "source": "https://github.com/Nevay/spi/tree/v1.0.3" }, - "time": "2025-06-29T15:42:06+00:00" + "time": "2025-04-02T19:38:14+00:00" }, { "name": "thecodingmachine/safe", @@ -7255,16 +7255,16 @@ }, { "name": "symfony/console", - "version": "v7.3.1", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101" + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/9e27aecde8f506ba0fd1d9989620c04a87697101", - "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101", + "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", "shasum": "" }, "require": { @@ -7329,7 +7329,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.1" + "source": "https://github.com/symfony/console/tree/v7.3.0" }, "funding": [ { @@ -7345,7 +7345,7 @@ "type": "tidelift" } ], - "time": "2025-06-27T19:55:54+00:00" + "time": "2025-05-24T10:34:04+00:00" }, { "name": "symfony/filesystem", From 6f5d3d53c081f730fa651fc56b54d1ee37730438 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 2 Jul 2025 19:51:36 +0530 Subject: [PATCH 320/343] bump: for tests. --- composer.json | 2 +- composer.lock | 70 ++++++++++++++++++++++++++------------------------- 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/composer.json b/composer.json index 4c36ab125d..9598bc3ebe 100644 --- a/composer.json +++ b/composer.json @@ -62,7 +62,7 @@ "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.18.*", - "utopia-php/migration": "0.10.*", + "utopia-php/migration": "fix-path-dev", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", diff --git a/composer.lock b/composer.lock index 05c8a49512..b5128bff85 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "55bc52686a08d64930e6af7411ac0654", + "content-hash": "0adf677d7a79dd195419f512265b9905", "packages": [ { "name": "adhocore/jwt", @@ -1878,16 +1878,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.45", + "version": "3.0.46", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8" + "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/bd81b90d5963c6b9d87de50357585375223f4dd8", - "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", + "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", "shasum": "" }, "require": { @@ -1968,7 +1968,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.45" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.46" }, "funding": [ { @@ -1984,7 +1984,7 @@ "type": "tidelift" } ], - "time": "2025-06-22T22:54:43+00:00" + "time": "2025-06-26T16:29:55+00:00" }, { "name": "psr/container", @@ -2547,16 +2547,16 @@ }, { "name": "symfony/http-client", - "version": "v7.3.0", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9" + "reference": "4403d87a2c16f33345dca93407a8714ee8c05a64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/57e4fb86314015a695a750ace358d07a7e37b8a9", - "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9", + "url": "https://api.github.com/repos/symfony/http-client/zipball/4403d87a2c16f33345dca93407a8714ee8c05a64", + "reference": "4403d87a2c16f33345dca93407a8714ee8c05a64", "shasum": "" }, "require": { @@ -2568,6 +2568,7 @@ }, "conflict": { "amphp/amp": "<2.5", + "amphp/socket": "<1.1", "php-http/discovery": "<1.15", "symfony/http-foundation": "<6.4" }, @@ -2580,7 +2581,6 @@ "require-dev": { "amphp/http-client": "^4.2.1|^5.0", "amphp/http-tunnel": "^1.0|^2.0", - "amphp/socket": "^1.1", "guzzlehttp/promises": "^1.4|^2.0", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", @@ -2622,7 +2622,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.3.0" + "source": "https://github.com/symfony/http-client/tree/v7.3.1" }, "funding": [ { @@ -2638,7 +2638,7 @@ "type": "tidelift" } ], - "time": "2025-05-02T08:23:16+00:00" + "time": "2025-06-28T07:58:39+00:00" }, { "name": "symfony/http-client-contracts", @@ -2960,16 +2960,16 @@ }, { "name": "tbachert/spi", - "version": "v1.0.3", + "version": "v1.0.5", "source": { "type": "git", "url": "https://github.com/Nevay/spi.git", - "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a" + "reference": "e7078767866d0a9e0f91d3f9d42a832df5e39002" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Nevay/spi/zipball/506a79c98e1a51522e76ee921ccb6c62d52faf3a", - "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a", + "url": "https://api.github.com/repos/Nevay/spi/zipball/e7078767866d0a9e0f91d3f9d42a832df5e39002", + "reference": "e7078767866d0a9e0f91d3f9d42a832df5e39002", "shasum": "" }, "require": { @@ -2987,7 +2987,7 @@ "extra": { "class": "Nevay\\SPI\\Composer\\Plugin", "branch-alias": { - "dev-main": "0.2.x-dev" + "dev-main": "1.0.x-dev" }, "plugin-optional": true }, @@ -3006,9 +3006,9 @@ ], "support": { "issues": "https://github.com/Nevay/spi/issues", - "source": "https://github.com/Nevay/spi/tree/v1.0.3" + "source": "https://github.com/Nevay/spi/tree/v1.0.5" }, - "time": "2025-04-02T19:38:14+00:00" + "time": "2025-06-29T15:42:06+00:00" }, { "name": "thecodingmachine/safe", @@ -3993,16 +3993,16 @@ }, { "name": "utopia-php/migration", - "version": "0.10.1", + "version": "dev-fix-path", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "ea1c585df7ec5f346f061a11581fc9a91679966f" + "reference": "1f2271ec2be7daba00ce025dbbb25a988caf4796" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/ea1c585df7ec5f346f061a11581fc9a91679966f", - "reference": "ea1c585df7ec5f346f061a11581fc9a91679966f", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/1f2271ec2be7daba00ce025dbbb25a988caf4796", + "reference": "1f2271ec2be7daba00ce025dbbb25a988caf4796", "shasum": "" }, "require": { @@ -4043,9 +4043,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.10.1" + "source": "https://github.com/utopia-php/migration/tree/fix-path" }, - "time": "2025-05-26T15:29:19+00:00" + "time": "2025-07-02T14:18:24+00:00" }, { "name": "utopia-php/orchestration", @@ -7255,16 +7255,16 @@ }, { "name": "symfony/console", - "version": "v7.3.0", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" + "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", - "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", + "url": "https://api.github.com/repos/symfony/console/zipball/9e27aecde8f506ba0fd1d9989620c04a87697101", + "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101", "shasum": "" }, "require": { @@ -7329,7 +7329,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.0" + "source": "https://github.com/symfony/console/tree/v7.3.1" }, "funding": [ { @@ -7345,7 +7345,7 @@ "type": "tidelift" } ], - "time": "2025-05-24T10:34:04+00:00" + "time": "2025-06-27T19:55:54+00:00" }, { "name": "symfony/filesystem", @@ -8236,7 +8236,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/migration": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { From ed2d12f8966309b3dfa29e4a5b7874abcf04dafb Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 2 Jul 2025 19:55:42 +0530 Subject: [PATCH 321/343] update: full path on appwrite. --- app/controllers/api/migrations.php | 7 +++++++ composer.json | 2 +- composer.lock | 18 ++++++++---------- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 85751811ba..f292a90a77 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -401,6 +401,13 @@ App::post('/v1/migrations/csv') $fileSize = $deviceForImports->getFileSize($newPath); $resources = Transfer::extractServices([Transfer::GROUP_DATABASES]); + // full path + $newPath = str_ireplace( + $deviceForImports->getRoot(), + $deviceForImports->getRoot() . DIRECTORY_SEPARATOR, + $newPath + ); + $migration = $dbForProject->createDocument('migrations', new Document([ '$id' => $migrationId, 'status' => 'pending', diff --git a/composer.json b/composer.json index 9598bc3ebe..4c36ab125d 100644 --- a/composer.json +++ b/composer.json @@ -62,7 +62,7 @@ "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.18.*", - "utopia-php/migration": "fix-path-dev", + "utopia-php/migration": "0.10.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", diff --git a/composer.lock b/composer.lock index b5128bff85..b809b01124 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0adf677d7a79dd195419f512265b9905", + "content-hash": "55bc52686a08d64930e6af7411ac0654", "packages": [ { "name": "adhocore/jwt", @@ -3993,16 +3993,16 @@ }, { "name": "utopia-php/migration", - "version": "dev-fix-path", + "version": "0.10.1", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "1f2271ec2be7daba00ce025dbbb25a988caf4796" + "reference": "ea1c585df7ec5f346f061a11581fc9a91679966f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/1f2271ec2be7daba00ce025dbbb25a988caf4796", - "reference": "1f2271ec2be7daba00ce025dbbb25a988caf4796", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/ea1c585df7ec5f346f061a11581fc9a91679966f", + "reference": "ea1c585df7ec5f346f061a11581fc9a91679966f", "shasum": "" }, "require": { @@ -4043,9 +4043,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/fix-path" + "source": "https://github.com/utopia-php/migration/tree/0.10.1" }, - "time": "2025-07-02T14:18:24+00:00" + "time": "2025-05-26T15:29:19+00:00" }, { "name": "utopia-php/orchestration", @@ -8236,9 +8236,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/migration": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From b1724e9c9ddac72c666a548039acc267d0aea164 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 2 Jul 2025 10:40:35 -0400 Subject: [PATCH 322/343] Update lock --- composer.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index b809b01124..0e61f2cd4b 100644 --- a/composer.lock +++ b/composer.lock @@ -3993,16 +3993,16 @@ }, { "name": "utopia-php/migration", - "version": "0.10.1", + "version": "0.10.2", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "ea1c585df7ec5f346f061a11581fc9a91679966f" + "reference": "42da0d3f00bb8a3eb480294ca94b5402e6a5a35c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/ea1c585df7ec5f346f061a11581fc9a91679966f", - "reference": "ea1c585df7ec5f346f061a11581fc9a91679966f", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/42da0d3f00bb8a3eb480294ca94b5402e6a5a35c", + "reference": "42da0d3f00bb8a3eb480294ca94b5402e6a5a35c", "shasum": "" }, "require": { @@ -4043,9 +4043,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.10.1" + "source": "https://github.com/utopia-php/migration/tree/0.10.2" }, - "time": "2025-05-26T15:29:19+00:00" + "time": "2025-07-02T14:37:14+00:00" }, { "name": "utopia-php/orchestration", From ce8ae2294a0ef6ccd9a4aea9cdf633b8560094cf Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 2 Jul 2025 12:58:37 -0400 Subject: [PATCH 323/343] Update lock --- composer.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index 0e61f2cd4b..abea16be08 100644 --- a/composer.lock +++ b/composer.lock @@ -3493,16 +3493,16 @@ }, { "name": "utopia-php/database", - "version": "0.71.8", + "version": "0.71.9", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "7dff6b67a54f1a7f9d3f210db4c6e40d7052b79e" + "reference": "eb2f759020bba617e99dd67973a9bd949b47f54e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/7dff6b67a54f1a7f9d3f210db4c6e40d7052b79e", - "reference": "7dff6b67a54f1a7f9d3f210db4c6e40d7052b79e", + "url": "https://api.github.com/repos/utopia-php/database/zipball/eb2f759020bba617e99dd67973a9bd949b47f54e", + "reference": "eb2f759020bba617e99dd67973a9bd949b47f54e", "shasum": "" }, "require": { @@ -3543,9 +3543,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.71.8" + "source": "https://github.com/utopia-php/database/tree/0.71.9" }, - "time": "2025-06-26T14:48:17+00:00" + "time": "2025-07-02T16:37:41+00:00" }, { "name": "utopia-php/detector", @@ -3993,16 +3993,16 @@ }, { "name": "utopia-php/migration", - "version": "0.10.2", + "version": "0.10.3", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "42da0d3f00bb8a3eb480294ca94b5402e6a5a35c" + "reference": "c8509727d0c5ecef31c1063b5901ed1a7541c71e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/42da0d3f00bb8a3eb480294ca94b5402e6a5a35c", - "reference": "42da0d3f00bb8a3eb480294ca94b5402e6a5a35c", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/c8509727d0c5ecef31c1063b5901ed1a7541c71e", + "reference": "c8509727d0c5ecef31c1063b5901ed1a7541c71e", "shasum": "" }, "require": { @@ -4043,9 +4043,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.10.2" + "source": "https://github.com/utopia-php/migration/tree/0.10.3" }, - "time": "2025-07-02T14:37:14+00:00" + "time": "2025-07-02T16:57:46+00:00" }, { "name": "utopia-php/orchestration", From 2ce3118ba96bd54df4be354f89eadcbb93b5d397 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 2 Jul 2025 13:36:46 -0400 Subject: [PATCH 324/343] Remove path update --- app/controllers/api/migrations.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index f292a90a77..85751811ba 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -401,13 +401,6 @@ App::post('/v1/migrations/csv') $fileSize = $deviceForImports->getFileSize($newPath); $resources = Transfer::extractServices([Transfer::GROUP_DATABASES]); - // full path - $newPath = str_ireplace( - $deviceForImports->getRoot(), - $deviceForImports->getRoot() . DIRECTORY_SEPARATOR, - $newPath - ); - $migration = $dbForProject->createDocument('migrations', new Document([ '$id' => $migrationId, 'status' => 'pending', From 55dc965dd6e1a55e925b4a698fb8fe285805b7b3 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 2 Jul 2025 14:32:05 -0400 Subject: [PATCH 325/343] Update lib --- composer.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index abea16be08..01a3ce7401 100644 --- a/composer.lock +++ b/composer.lock @@ -3993,16 +3993,16 @@ }, { "name": "utopia-php/migration", - "version": "0.10.3", + "version": "0.10.4", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "c8509727d0c5ecef31c1063b5901ed1a7541c71e" + "reference": "0c85917482db172b3ccdc0704e42af3c1cc89361" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/c8509727d0c5ecef31c1063b5901ed1a7541c71e", - "reference": "c8509727d0c5ecef31c1063b5901ed1a7541c71e", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/0c85917482db172b3ccdc0704e42af3c1cc89361", + "reference": "0c85917482db172b3ccdc0704e42af3c1cc89361", "shasum": "" }, "require": { @@ -4043,9 +4043,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.10.3" + "source": "https://github.com/utopia-php/migration/tree/0.10.4" }, - "time": "2025-07-02T16:57:46+00:00" + "time": "2025-07-02T18:31:09+00:00" }, { "name": "utopia-php/orchestration", From 0f37a0e0efb292fece58b60957e2f1a8265eb3fa Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Thu, 3 Jul 2025 00:08:29 +0530 Subject: [PATCH 326/343] Fix tests --- src/Appwrite/Platform/Modules/Functions/Workers/Builds.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 3221383d70..25b3473829 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -594,7 +594,7 @@ class Builds extends Action ]); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); + $hostname = System::getEnv('_APP_DOMAIN'); $endpoint = $protocol . '://' . $hostname . "/v1"; // Appwrite vars From f62c3135df230c57c5604df7b020218e1c1b777b Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 3 Jul 2025 16:26:56 +0530 Subject: [PATCH 327/343] add null check for platform --- src/Appwrite/Network/Platform.php | 6 +++--- src/Appwrite/Network/Validator/Redirect.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Network/Platform.php b/src/Appwrite/Network/Platform.php index cc59bd4508..6b18b35bef 100644 --- a/src/Appwrite/Network/Platform.php +++ b/src/Appwrite/Network/Platform.php @@ -50,10 +50,10 @@ class Platform /** * Get user-friendly platform name from a scheme. * - * @param string $scheme + * @param string|null $scheme * @return string Empty string if scheme is not found. */ - public static function getNameByScheme(string $scheme): string + public static function getNameByScheme(?string $scheme): string { return self::$names[$scheme] ?? ''; } @@ -62,7 +62,7 @@ class Platform { $hostnames = []; foreach ($platforms as $platform) { - $type = $platform['type'] ?? self::TYPE_UNKNOWN; + $type = strtolower($platform['type'] ?? self::TYPE_UNKNOWN); $hostname = strtolower($platform['hostname'] ?? ''); $key = strtolower($platform['key'] ?? ''); diff --git a/src/Appwrite/Network/Validator/Redirect.php b/src/Appwrite/Network/Validator/Redirect.php index 43750f4cbd..162f4c7eb9 100644 --- a/src/Appwrite/Network/Validator/Redirect.php +++ b/src/Appwrite/Network/Validator/Redirect.php @@ -12,7 +12,7 @@ class Redirect extends Origin */ public function getDescription(): string { - $platform = $this->scheme ? Platform::getNameByScheme($this->scheme) : null; + $platform = Platform::getNameByScheme($this->scheme); $host = $this->host ? '(' . $this->host . ')' : ''; if (empty($this->host) && empty($this->scheme)) { From bb9a271fa85045af287283c107b1ba922ba0069e Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 3 Jul 2025 16:38:22 +0530 Subject: [PATCH 328/343] chore: add scheme validation --- src/Appwrite/Network/Platform.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Network/Platform.php b/src/Appwrite/Network/Platform.php index 6b18b35bef..b7acafc96d 100644 --- a/src/Appwrite/Network/Platform.php +++ b/src/Appwrite/Network/Platform.php @@ -101,12 +101,14 @@ class Platform { $schemes = []; foreach ($platforms as $platform) { - $type = $platform['type'] ?? self::TYPE_UNKNOWN; - $scheme = $platform['key'] ?? ''; + $type = strtolower($platform['type'] ?? self::TYPE_UNKNOWN); + $scheme = strtolower($platform['key'] ?? ''); switch ($type) { case self::TYPE_SCHEME: - $schemes[] = $scheme; + if (!empty($scheme) && preg_match('/^[a-z][a-z0-9+.-]*$/', $scheme)) { + $schemes[] = $scheme; + } break; default: break; From 4747700eaed9ef970477923e2b71015727430d22 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 3 Jul 2025 21:17:43 +0530 Subject: [PATCH 329/343] chore: add logging --- app/controllers/general.php | 1 - src/Appwrite/Network/Validator/Origin.php | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index ae5b17cee6..7d23c515e3 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -49,7 +49,6 @@ use Utopia\Logger\Log\User; use Utopia\Logger\Logger; use Utopia\Platform\Service; use Utopia\System\System; -use Utopia\Validator\Hostname; use Utopia\Validator\Text; Config::setParam('domainVerification', false); diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 21563a9a15..7aa1bf278d 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -3,6 +3,7 @@ namespace Appwrite\Network\Validator; use Appwrite\Network\Platform; +use Utopia\CLI\Console; use Utopia\Validator; use Utopia\Validator\Hostname; @@ -42,6 +43,11 @@ class Origin extends Validator $this->scheme = $this->parseScheme($origin); $this->host = strtolower(parse_url($origin, PHP_URL_HOST) ?? ''); + Console::log("Scheme: " . $this->scheme); + Console::log("Host: " . $this->host); + Console::log("Hostnames: " . json_encode($this->hostnames, JSON_PRETTY_PRINT)); + Console::log("Schemes: " . json_encode($this->schemes, JSON_PRETTY_PRINT)); + $validator = new Hostname($this->hostnames); if (in_array($this->scheme, ['http', 'https']) && $validator->isValid($this->host)) { // Valid HTTP/HTTPS origin return true; From d9486f38c4a4644005aeb4f9e9cf794485adfb1a Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Thu, 3 Jul 2025 10:54:51 -0500 Subject: [PATCH 330/343] fix: jwt auth database selection for admin mode Use dbForPlatform for JWT user lookup in admin mode --- app/init/resources.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/init/resources.php b/app/init/resources.php index aa04b46e1f..474c802bb2 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -264,7 +264,11 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons $jwtUserId = $payload['userId'] ?? ''; if (!empty($jwtUserId)) { - $user = $dbForProject->getDocument('users', $jwtUserId); + if (APP_MODE_ADMIN !== $mode) { + $user = $dbForProject->getDocument('users', $jwtUserId); + } else { + $user = $dbForPlatform->getDocument('users', $jwtUserId); + } } $jwtSessionId = $payload['sessionId'] ?? ''; From 199b9f7e6d7f79f7ce2d9f09022670f8f7cd66ec Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Thu, 3 Jul 2025 11:06:36 -0500 Subject: [PATCH 331/343] fix nitpick --- app/init/resources.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/init/resources.php b/app/init/resources.php index 474c802bb2..ac9159d2f2 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -222,7 +222,9 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons Auth::$unique = $session['id'] ?? ''; Auth::$secret = $session['secret'] ?? ''; - if (APP_MODE_ADMIN !== $mode) { + if ($mode === APP_MODE_ADMIN) { + $user = $dbForPlatform->getDocument('users', Auth::$unique); + } else { if ($project->isEmpty()) { $user = new Document([]); } else { @@ -232,8 +234,6 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons $user = $dbForProject->getDocument('users', Auth::$unique); } } - } else { - $user = $dbForPlatform->getDocument('users', Auth::$unique); } if ( @@ -264,10 +264,10 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons $jwtUserId = $payload['userId'] ?? ''; if (!empty($jwtUserId)) { - if (APP_MODE_ADMIN !== $mode) { - $user = $dbForProject->getDocument('users', $jwtUserId); - } else { + if ($mode === APP_MODE_ADMIN) { $user = $dbForPlatform->getDocument('users', $jwtUserId); + } else { + $user = $dbForProject->getDocument('users', $jwtUserId); } } From b6f11144b8ebdf7e0cb3f27a67419e6d1e7f4cd7 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 3 Jul 2025 21:39:23 +0530 Subject: [PATCH 332/343] chore: popular schemes --- src/Appwrite/Network/Platform.php | 31 +++++++++++++++++++++++ src/Appwrite/Network/Validator/Origin.php | 4 ++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Network/Platform.php b/src/Appwrite/Network/Platform.php index b7acafc96d..71b4587824 100644 --- a/src/Appwrite/Network/Platform.php +++ b/src/Appwrite/Network/Platform.php @@ -110,6 +110,37 @@ class Platform $schemes[] = $scheme; } break; + case self::TYPE_WEB: + case self::TYPE_FLUTTER_WEB: + $schemes[] = self::SCHEME_HTTP; + break; + case self::TYPE_FLUTTER_IOS: + case self::TYPE_APPLE_IOS: + case self::TYPE_REACT_NATIVE_IOS: + $schemes[] = self::SCHEME_IOS; + break; + case self::TYPE_FLUTTER_ANDROID: + case self::TYPE_ANDROID: + case self::TYPE_REACT_NATIVE_ANDROID: + $schemes[] = self::SCHEME_ANDROID; + break; + case self::TYPE_FLUTTER_MACOS: + case self::TYPE_APPLE_MACOS: + $schemes[] = self::SCHEME_MACOS; + break; + case self::TYPE_FLUTTER_WINDOWS: + case self::TYPE_UNITY: + $schemes[] = self::SCHEME_WINDOWS; + break; + case self::TYPE_FLUTTER_LINUX: + $schemes[] = self::SCHEME_LINUX; + break; + case self::TYPE_APPLE_WATCHOS: + $schemes[] = self::SCHEME_WATCHOS; + break; + case self::TYPE_APPLE_TVOS: + $schemes[] = self::SCHEME_TVOS; + break; default: break; } diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 7aa1bf278d..f793ea6c4e 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -51,7 +51,9 @@ class Origin extends Validator $validator = new Hostname($this->hostnames); if (in_array($this->scheme, ['http', 'https']) && $validator->isValid($this->host)) { // Valid HTTP/HTTPS origin return true; - } if (!empty($this->scheme) && in_array($this->scheme, $this->schemes, true)) { // Valid scheme-based origin + } + + if (!empty($this->scheme) && in_array($this->scheme, $this->schemes, true)) { // Valid scheme-based origin return true; } From 172ba84ec8c682e6be4fc02620935f4c56f6bf73 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 3 Jul 2025 22:25:46 +0530 Subject: [PATCH 333/343] chore: add logging --- src/Appwrite/Network/Platform.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Appwrite/Network/Platform.php b/src/Appwrite/Network/Platform.php index 71b4587824..1bf68c4483 100644 --- a/src/Appwrite/Network/Platform.php +++ b/src/Appwrite/Network/Platform.php @@ -2,6 +2,8 @@ namespace Appwrite\Network; +use Utopia\CLI\Console; + class Platform { public const TYPE_UNKNOWN = 'unknown'; @@ -100,6 +102,7 @@ class Platform public static function getSchemes(array $platforms): array { $schemes = []; + Console::log("Platforms: " . json_encode($platforms, JSON_PRETTY_PRINT)); foreach ($platforms as $platform) { $type = strtolower($platform['type'] ?? self::TYPE_UNKNOWN); $scheme = strtolower($platform['key'] ?? ''); From 431a26e1512c49a48b9491cfa0b5eeec32ec37c9 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 3 Jul 2025 22:37:31 +0530 Subject: [PATCH 334/343] chore: removing loggin --- src/Appwrite/Network/Platform.php | 3 --- src/Appwrite/Network/Validator/Origin.php | 6 ------ 2 files changed, 9 deletions(-) diff --git a/src/Appwrite/Network/Platform.php b/src/Appwrite/Network/Platform.php index 1bf68c4483..71b4587824 100644 --- a/src/Appwrite/Network/Platform.php +++ b/src/Appwrite/Network/Platform.php @@ -2,8 +2,6 @@ namespace Appwrite\Network; -use Utopia\CLI\Console; - class Platform { public const TYPE_UNKNOWN = 'unknown'; @@ -102,7 +100,6 @@ class Platform public static function getSchemes(array $platforms): array { $schemes = []; - Console::log("Platforms: " . json_encode($platforms, JSON_PRETTY_PRINT)); foreach ($platforms as $platform) { $type = strtolower($platform['type'] ?? self::TYPE_UNKNOWN); $scheme = strtolower($platform['key'] ?? ''); diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index f793ea6c4e..59e06a8ea4 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -3,7 +3,6 @@ namespace Appwrite\Network\Validator; use Appwrite\Network\Platform; -use Utopia\CLI\Console; use Utopia\Validator; use Utopia\Validator\Hostname; @@ -43,11 +42,6 @@ class Origin extends Validator $this->scheme = $this->parseScheme($origin); $this->host = strtolower(parse_url($origin, PHP_URL_HOST) ?? ''); - Console::log("Scheme: " . $this->scheme); - Console::log("Host: " . $this->host); - Console::log("Hostnames: " . json_encode($this->hostnames, JSON_PRETTY_PRINT)); - Console::log("Schemes: " . json_encode($this->schemes, JSON_PRETTY_PRINT)); - $validator = new Hostname($this->hostnames); if (in_array($this->scheme, ['http', 'https']) && $validator->isValid($this->host)) { // Valid HTTP/HTTPS origin return true; From 72f08e281bc8878936889a1352b803c0bce781c5 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 3 Jul 2025 22:39:12 +0530 Subject: [PATCH 335/343] chore: make check consistent --- src/Appwrite/Network/Platform.php | 1 + src/Appwrite/Network/Validator/Origin.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Network/Platform.php b/src/Appwrite/Network/Platform.php index 71b4587824..d584ec074f 100644 --- a/src/Appwrite/Network/Platform.php +++ b/src/Appwrite/Network/Platform.php @@ -113,6 +113,7 @@ class Platform case self::TYPE_WEB: case self::TYPE_FLUTTER_WEB: $schemes[] = self::SCHEME_HTTP; + $schemes[] = self::SCHEME_HTTPS; break; case self::TYPE_FLUTTER_IOS: case self::TYPE_APPLE_IOS: diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 59e06a8ea4..6cd212af2f 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -43,7 +43,7 @@ class Origin extends Validator $this->host = strtolower(parse_url($origin, PHP_URL_HOST) ?? ''); $validator = new Hostname($this->hostnames); - if (in_array($this->scheme, ['http', 'https']) && $validator->isValid($this->host)) { // Valid HTTP/HTTPS origin + if (in_array($this->scheme, [Platform::SCHEME_HTTP, Platform::SCHEME_HTTPS]) && $validator->isValid($this->host)) { // Valid HTTP/HTTPS origin return true; } From 6725b31b65497b93d1e02b0c6514be09b63fb95f Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 3 Jul 2025 13:55:13 -0400 Subject: [PATCH 336/343] Add redis publisher to schedule base if available --- src/Appwrite/Platform/Tasks/ScheduleBase.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index b2134707e7..7686815868 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -26,6 +26,7 @@ abstract class ScheduleBase extends Action protected array $schedules = []; protected BrokerPool $publisher; + protected ?BrokerPool $publisherRedis = null; private ?Histogram $collectSchedulesTelemetryDuration = null; private ?Gauge $collectSchedulesTelemetryCount = null; @@ -72,6 +73,13 @@ abstract class ScheduleBase extends Action Console::success(APP_NAME . ' ' . \ucfirst(static::getSupportedResource()) . ' scheduler v1 has started'); $this->publisher = new BrokerPool($pools->get('publisher')); + + try { + $this->publisherRedis = new BrokerPool($pools->get('publisherRedis')); + } catch (\Throwable) { + $this->publisherRedis = null; + } + $this->scheduleTelemetryCount = $telemetry->createGauge('task.schedule.count'); $this->collectSchedulesTelemetryDuration = $telemetry->createHistogram('task.schedule.collect_schedules.duration', 's'); $this->collectSchedulesTelemetryCount = $telemetry->createGauge('task.schedule.collect_schedules.count'); From f224c09c10eebf36905d1d4a01164a4440c75bec Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 3 Jul 2025 14:08:54 -0400 Subject: [PATCH 337/343] Use correct publisher in schedule tasks --- src/Appwrite/Platform/Tasks/ScheduleExecutions.php | 9 ++++++++- src/Appwrite/Platform/Tasks/ScheduleFunctions.php | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php index 27a7c1dbf1..c9b795f684 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php @@ -6,6 +6,7 @@ use Appwrite\Event\Func; use Swoole\Coroutine as Co; use Utopia\Database\Database; use Utopia\Pools\Group; +use Utopia\System\System; class ScheduleExecutions extends ScheduleBase { @@ -29,9 +30,15 @@ class ScheduleExecutions extends ScheduleBase protected function enqueueResources(Group $pools, Database $dbForPlatform, callable $getProjectDB): void { - $queueForFunctions = new Func($this->publisher); $intervalEnd = (new \DateTime())->modify('+' . self::ENQUEUE_TIMER . ' seconds'); + $isRedisFallback = \str_contains(System::getEnv('_APP_WORKER_REDIS_FALLBACK', ''), 'functions'); + + $queueForFunctions = new Func($isRedisFallback + ? $this->publisherRedis + : $this->publisher + ); + foreach ($this->schedules as $schedule) { if (!$schedule['active']) { $dbForPlatform->deleteDocument( diff --git a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php index 7812b27832..80d5b32d03 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php @@ -8,6 +8,8 @@ use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Pools\Group; +use Utopia\Queue\Queue; +use Utopia\System\System; class ScheduleFunctions extends ScheduleBase { @@ -90,7 +92,12 @@ class ScheduleFunctions extends ScheduleBase $this->updateProjectAccess($schedule['project'], $dbForPlatform); - $queueForFunctions = new Func($this->publisher); + $isRedisFallback = \str_contains(System::getEnv('_APP_WORKER_REDIS_FALLBACK', ''), 'functions'); + + $queueForFunctions = new Func($isRedisFallback + ? $this->publisherRedis + : $this->publisher + ); $queueForFunctions ->setType('schedule') From 2a73dddbdbfbe30988d6e854bb8e6fc3604c0f5c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 3 Jul 2025 14:09:08 -0400 Subject: [PATCH 338/343] Fix health --- app/controllers/api/health.php | 18 ++++++++++++++---- app/worker.php | 8 ++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 2bdaea3c2c..43368b8d3f 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -523,11 +523,16 @@ App::get('/v1/health/queue/databases') ->param('name', 'database_db_main', new Text(256), 'Queue name for which to check the queue size', true) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('publisher') + ->inject('publisherRedis') ->inject('response') - ->action(function (string $name, int|string $threshold, Publisher $publisher, Response $response) { + ->action(function (string $name, int|string $threshold, Publisher $publisher, ?Publisher $publisherRedis, Response $response) { $threshold = \intval($threshold); - $size = $publisher->getQueueSize(new Queue($name)); + $isRedisFallback = \str_contains(System::getEnv('_APP_WORKER_REDIS_FALLBACK', ''), 'databases'); + + $size = $isRedisFallback + ? $publisherRedis->getQueueSize(new Queue($name)) + : $publisher->getQueueSize(new Queue($name)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); @@ -655,11 +660,16 @@ App::get('/v1/health/queue/migrations') )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->inject('publisher') + ->inject('publisherRedis') ->inject('response') - ->action(function (int|string $threshold, Publisher $publisher, Response $response) { + ->action(function (int|string $threshold, Publisher $publisher, ?Publisher $publisherRedis, Response $response) { $threshold = \intval($threshold); - $size = $publisher->getQueueSize(new Queue(Event::MIGRATIONS_QUEUE_NAME)); + $isRedisFallback = \str_contains(System::getEnv('_APP_WORKER_REDIS_FALLBACK', ''), 'migrations'); + + $size = $isRedisFallback + ? $publisherRedis->getQueueSize(new Queue(Event::MIGRATIONS_QUEUE_NAME)) + : $publisher->getQueueSize(new Queue(Event::MIGRATIONS_QUEUE_NAME)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); diff --git a/app/worker.php b/app/worker.php index 845914c923..c1fdd93f2c 100644 --- a/app/worker.php +++ b/app/worker.php @@ -247,10 +247,18 @@ Server::setResource('publisher', function (Group $pools) { return new BrokerPool(publisher: $pools->get('publisher')); }, ['pools']); +Server::setResource('publisherRedis', function () { + return null; +}); + Server::setResource('consumer', function (Group $pools) { return new BrokerPool(consumer: $pools->get('consumer')); }, ['pools']); +Server::setResource('consumerRedis', function () { + return null; +}); + Server::setResource('queueForStatsUsage', function (Publisher $publisher) { return new StatsUsage($publisher); }, ['publisher']); From 7d37f5b066792d509bf50aa9446729407ae81689 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 3 Jul 2025 14:18:19 -0400 Subject: [PATCH 339/343] Lint --- app/worker.php | 4 ++-- src/Appwrite/Platform/Tasks/ScheduleExecutions.php | 3 ++- src/Appwrite/Platform/Tasks/ScheduleFunctions.php | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/worker.php b/app/worker.php index c1fdd93f2c..71d99eadf8 100644 --- a/app/worker.php +++ b/app/worker.php @@ -248,7 +248,7 @@ Server::setResource('publisher', function (Group $pools) { }, ['pools']); Server::setResource('publisherRedis', function () { - return null; + return; }); Server::setResource('consumer', function (Group $pools) { @@ -256,7 +256,7 @@ Server::setResource('consumer', function (Group $pools) { }, ['pools']); Server::setResource('consumerRedis', function () { - return null; + return; }); Server::setResource('queueForStatsUsage', function (Publisher $publisher) { diff --git a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php index c9b795f684..acb2dd3070 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php @@ -34,7 +34,8 @@ class ScheduleExecutions extends ScheduleBase $isRedisFallback = \str_contains(System::getEnv('_APP_WORKER_REDIS_FALLBACK', ''), 'functions'); - $queueForFunctions = new Func($isRedisFallback + $queueForFunctions = new Func( + $isRedisFallback ? $this->publisherRedis : $this->publisher ); diff --git a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php index 80d5b32d03..7a3363d74d 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php @@ -8,7 +8,6 @@ use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Pools\Group; -use Utopia\Queue\Queue; use Utopia\System\System; class ScheduleFunctions extends ScheduleBase @@ -94,7 +93,8 @@ class ScheduleFunctions extends ScheduleBase $isRedisFallback = \str_contains(System::getEnv('_APP_WORKER_REDIS_FALLBACK', ''), 'functions'); - $queueForFunctions = new Func($isRedisFallback + $queueForFunctions = new Func( + $isRedisFallback ? $this->publisherRedis : $this->publisher ); From 5bb998b02da7159b99c74883c04758e919e4663e Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 3 Jul 2025 14:24:40 -0400 Subject: [PATCH 340/343] Add API + CLI stubs --- app/cli.php | 10 ++++++---- app/init/resources.php | 6 ++++++ app/worker.php | 4 ++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/app/cli.php b/app/cli.php index c829546011..86ec241c93 100644 --- a/app/cli.php +++ b/app/cli.php @@ -188,16 +188,18 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { return $database; }; }, ['pools', 'cache']); - +CLI::setResource('publisher', function (Group $pools) { + return new BrokerPool(publisher: $pools->get('publisher')); +}, ['pools']); +CLI::setResource('publisherRedis', function () { + // Stub +}); CLI::setResource('queueForStatsUsage', function (Publisher $publisher) { return new StatsUsage($publisher); }, ['publisher']); CLI::setResource('queueForStatsResources', function (Publisher $publisher) { return new StatsResources($publisher); }, ['publisher']); -CLI::setResource('publisher', function (Group $pools) { - return new BrokerPool(publisher: $pools->get('publisher')); -}, ['pools']); CLI::setResource('queueForFunctions', function (Publisher $publisher) { return new Func($publisher); }, ['publisher']); diff --git a/app/init/resources.php b/app/init/resources.php index ac9159d2f2..339106291b 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -79,9 +79,15 @@ App::setResource('localeCodes', function () { App::setResource('publisher', function (Group $pools) { return new BrokerPool(publisher: $pools->get('publisher')); }, ['pools']); +App::setResource('publisherRedis', function () { + // Stub +}); App::setResource('consumer', function (Group $pools) { return new BrokerPool(consumer: $pools->get('consumer')); }, ['pools']); +App::setResource('consumerRedis', function () { + // Stub +}); App::setResource('queueForMessaging', function (Publisher $publisher) { return new Messaging($publisher); }, ['publisher']); diff --git a/app/worker.php b/app/worker.php index 71d99eadf8..4f0f569a9e 100644 --- a/app/worker.php +++ b/app/worker.php @@ -248,7 +248,7 @@ Server::setResource('publisher', function (Group $pools) { }, ['pools']); Server::setResource('publisherRedis', function () { - return; + // Stub }); Server::setResource('consumer', function (Group $pools) { @@ -256,7 +256,7 @@ Server::setResource('consumer', function (Group $pools) { }, ['pools']); Server::setResource('consumerRedis', function () { - return; + // Stub }); Server::setResource('queueForStatsUsage', function (Publisher $publisher) { From bc8b10a69e0478872a289375d9b9b11bcc5f7bd1 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Fri, 4 Jul 2025 16:46:14 +0530 Subject: [PATCH 341/343] fix: origin tests --- src/Appwrite/Network/Validator/Origin.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 6cd212af2f..c8d9ee626d 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -42,12 +42,12 @@ class Origin extends Validator $this->scheme = $this->parseScheme($origin); $this->host = strtolower(parse_url($origin, PHP_URL_HOST) ?? ''); - $validator = new Hostname($this->hostnames); - if (in_array($this->scheme, [Platform::SCHEME_HTTP, Platform::SCHEME_HTTPS]) && $validator->isValid($this->host)) { // Valid HTTP/HTTPS origin - return true; + if (in_array($this->scheme, [Platform::SCHEME_HTTP, Platform::SCHEME_HTTPS], true)) { + $validator = new Hostname($this->hostnames); + return $validator->isValid($this->host); } - if (!empty($this->scheme) && in_array($this->scheme, $this->schemes, true)) { // Valid scheme-based origin + if (!empty($this->scheme) && in_array($this->scheme, $this->schemes, true)) { return true; } From 37c741140516203b5fed7c1e0ab3fef20c908e49 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Fri, 4 Jul 2025 16:51:30 +0530 Subject: [PATCH 342/343] Trigger Build From 2545977d4778d7d33187d1d12829854bce3903c1 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Fri, 4 Jul 2025 17:46:21 +0530 Subject: [PATCH 343/343] Fix site template test --- app/config/templates/site.php | 2 +- tests/e2e/Services/Sites/SitesCustomClientTest.php | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/config/templates/site.php b/app/config/templates/site.php index c6f0119ed9..4ae6f61607 100644 --- a/app/config/templates/site.php +++ b/app/config/templates/site.php @@ -7,7 +7,7 @@ use Utopia\System\System; */ $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; -$hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN', '')); +$hostname = System::getEnv('_APP_DOMAIN', ''); $url = $protocol . '://' . $hostname; diff --git a/tests/e2e/Services/Sites/SitesCustomClientTest.php b/tests/e2e/Services/Sites/SitesCustomClientTest.php index 9bf389ea62..42fe26d216 100644 --- a/tests/e2e/Services/Sites/SitesCustomClientTest.php +++ b/tests/e2e/Services/Sites/SitesCustomClientTest.php @@ -6,6 +6,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; +use Utopia\System\System; class SitesCustomClientTest extends Scope { @@ -121,6 +122,7 @@ class SitesCustomClientTest extends Scope * Test for SUCCESS */ $template = $this->getTemplate('starter-for-react'); + $hostname = System::getEnv('_APP_DOMAIN') ?: ''; $this->assertEquals(200, $template['headers']['status-code']); $this->assertIsArray($template['body']); $this->assertEquals('starter-for-react', $template['body']['key']); @@ -129,8 +131,8 @@ class SitesCustomClientTest extends Scope $this->assertEquals('github', $template['body']['vcsProvider']); $this->assertEquals('Simple React application integrated with Appwrite SDK.', $template['body']['tagline']); $this->assertIsArray($template['body']['frameworks']); - $this->assertEquals('http://localhost/images/sites/templates/starter-for-react-dark.png', $template['body']['screenshotDark']); - $this->assertEquals('http://localhost/images/sites/templates/starter-for-react-light.png', $template['body']['screenshotLight']); + $this->assertEquals('http://'. $hostname . '/images/sites/templates/starter-for-react-dark.png', $template['body']['screenshotDark']); + $this->assertEquals('http://' . $hostname . '/images/sites/templates/starter-for-react-light.png', $template['body']['screenshotLight']); /** * Test for FAILURE

    {{buttonText}}

  • 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%0AF45mIQ%KM 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

  • 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%0AF45mIQ%KM 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