diff --git a/docs/changelog/index.mdx b/docs/changelog/index.mdx index 3f438ff43..2a5ef50d5 100644 --- a/docs/changelog/index.mdx +++ b/docs/changelog/index.mdx @@ -15,6 +15,7 @@ rss: true ## Fixes & Security - Thank you to [@shaxbozaka](https://github.com/shaxbozaka) for running a security audit on Reactive Resume and helping make the app more secure. - Hardened auth, OAuth, AI URL validation, printer/export endpoints, resume access controls, Browserless configuration, and public route exposure. [a42dbcd4](https://github.com/amruthpillai/reactive-resume/commit/a42dbcd4) +- Removed the public RPC surface for the printer-only resume fetch endpoint by moving it behind a server function, further shrinking the attack surface for `getByIdForPrinter`, thanks to [@shaxbozaka](https://github.com/shaxbozaka). - Corrected Computer Modern Sans italic font file mappings, thanks to [@russellbrenner](https://github.com/russellbrenner). [#2881](https://github.com/amruthpillai/reactive-resume/pull/2881) - Improved email handling and user lookup in OAuth configuration, thanks to [@VedantBhawsar](https://github.com/VedantBhawsar). [#2874](https://github.com/amruthpillai/reactive-resume/pull/2874) - Aligned role period text in experience items, thanks to [@JamesGoslings](https://github.com/JamesGoslings). [#2908](https://github.com/amruthpillai/reactive-resume/pull/2908) diff --git a/locales/af-ZA.po b/locales/af-ZA.po index 79d2c4bfe..5c9f37d7a 100644 --- a/locales/af-ZA.po +++ b/locales/af-ZA.po @@ -2772,12 +2772,6 @@ msgstr "Besig om jou wagwoord te herstel..." msgid "Resources" msgstr "Hulpbronne" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "CV" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "CV-ontleding" @@ -3951,4 +3945,3 @@ msgstr "Zoem uit" #: src/utils/locale.ts msgid "Zulu" msgstr "Zoeloe" - diff --git a/locales/am-ET.po b/locales/am-ET.po index 6cdfb7509..04601367c 100644 --- a/locales/am-ET.po +++ b/locales/am-ET.po @@ -2772,12 +2772,6 @@ msgstr "የይለፍ ቃልዎን በመዳግም ላይ…" msgid "Resources" msgstr "ሀብቶች" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "" @@ -3951,4 +3945,3 @@ msgstr "አጉር" #: src/utils/locale.ts msgid "Zulu" msgstr "ዙሉ" - diff --git a/locales/ar-SA.po b/locales/ar-SA.po index 71cbd80bf..ff3bf5ff0 100644 --- a/locales/ar-SA.po +++ b/locales/ar-SA.po @@ -2772,12 +2772,6 @@ msgstr "جاري إعادة تعيين كلمة المرور..." msgid "Resources" msgstr "الموارد" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "السيرة الذاتية" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "تحليل السيرة الذاتية" @@ -3951,4 +3945,3 @@ msgstr "تصغير" #: src/utils/locale.ts msgid "Zulu" msgstr "الزولو" - diff --git a/locales/az-AZ.po b/locales/az-AZ.po index ca1f29422..b2eba90e5 100644 --- a/locales/az-AZ.po +++ b/locales/az-AZ.po @@ -2772,12 +2772,6 @@ msgstr "Parolunuz sıfırlanır..." msgid "Resources" msgstr "Resurslar" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Təcrübə" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Təcrübə Təhlili" @@ -3951,4 +3945,3 @@ msgstr "Uzaqlaşdır" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/bg-BG.po b/locales/bg-BG.po index 82fb1660b..775361c84 100644 --- a/locales/bg-BG.po +++ b/locales/bg-BG.po @@ -2772,12 +2772,6 @@ msgstr "Нулиране на паролата ви..." msgid "Resources" msgstr "Ресурси" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Резюме" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Анализ на автобиографията" @@ -3951,4 +3945,3 @@ msgstr "Намаляване" #: src/utils/locale.ts msgid "Zulu" msgstr "Зулуски" - diff --git a/locales/bn-BD.po b/locales/bn-BD.po index fe41c8857..817843e3d 100644 --- a/locales/bn-BD.po +++ b/locales/bn-BD.po @@ -2772,12 +2772,6 @@ msgstr "আপনার পাসওয়ার্ড রিসেট করা msgid "Resources" msgstr "রিসোর্সসমূহ" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "জীবনবৃত্তান্ত" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "রিজিউমে বিশ্লেষণ" @@ -3951,4 +3945,3 @@ msgstr "জুম আউট" #: src/utils/locale.ts msgid "Zulu" msgstr "জুলু" - diff --git a/locales/ca-ES.po b/locales/ca-ES.po index b27a43a21..9c733f0b3 100644 --- a/locales/ca-ES.po +++ b/locales/ca-ES.po @@ -2772,12 +2772,6 @@ msgstr "S’està restablint la contrasenya..." msgid "Resources" msgstr "Recursos" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Resum" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Anàlisi de currículum" @@ -3951,4 +3945,3 @@ msgstr "Allunya" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulú" - diff --git a/locales/cs-CZ.po b/locales/cs-CZ.po index 39d9a78a2..34531fe90 100644 --- a/locales/cs-CZ.po +++ b/locales/cs-CZ.po @@ -2772,12 +2772,6 @@ msgstr "Obnovování hesla…" msgid "Resources" msgstr "Zdroje" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Životopis" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Analýza životopisu" @@ -3951,4 +3945,3 @@ msgstr "Oddálit" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/da-DK.po b/locales/da-DK.po index 11496d90e..1e3252f17 100644 --- a/locales/da-DK.po +++ b/locales/da-DK.po @@ -2772,12 +2772,6 @@ msgstr "Nulstiller din adgangskode..." msgid "Resources" msgstr "Ressourcer" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "CV" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "CV-analyse" @@ -3951,4 +3945,3 @@ msgstr "Zoom ud" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/de-DE.po b/locales/de-DE.po index 5a49a90cd..0e172ffd4 100644 --- a/locales/de-DE.po +++ b/locales/de-DE.po @@ -2772,12 +2772,6 @@ msgstr "Ihr Passwort wird zurückgesetzt..." msgid "Resources" msgstr "Ressourcen" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Lebenslauf" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Lebenslauf Analyse" @@ -3951,4 +3945,3 @@ msgstr "Herauszoomen" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/el-GR.po b/locales/el-GR.po index eaa2d8a5c..fd3edf3ca 100644 --- a/locales/el-GR.po +++ b/locales/el-GR.po @@ -2772,12 +2772,6 @@ msgstr "Επαναφορά κωδικού πρόσβασης..." msgid "Resources" msgstr "Πόροι" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Βιογραφικό σημείωμα" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Ανάλυση βιογραφικού σημειώματος" @@ -3951,4 +3945,3 @@ msgstr "Σμίκρυνση" #: src/utils/locale.ts msgid "Zulu" msgstr "Ζουλού" - diff --git a/locales/en-GB.po b/locales/en-GB.po index 9ebbc2a91..3308a966e 100644 --- a/locales/en-GB.po +++ b/locales/en-GB.po @@ -2772,12 +2772,6 @@ msgstr "Resetting your password..." msgid "Resources" msgstr "Resources" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Resume" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Resume Analysis" @@ -3951,4 +3945,3 @@ msgstr "Zoom out" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/en-US.po b/locales/en-US.po index 4d45fa2e7..b0bf241e3 100644 --- a/locales/en-US.po +++ b/locales/en-US.po @@ -2767,12 +2767,6 @@ msgstr "Resetting your password..." msgid "Resources" msgstr "Resources" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Resume" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Resume Analysis" diff --git a/locales/es-ES.po b/locales/es-ES.po index afc101bd0..1a36c8c43 100644 --- a/locales/es-ES.po +++ b/locales/es-ES.po @@ -2772,12 +2772,6 @@ msgstr "Restableciendo tu contraseña..." msgid "Resources" msgstr "Recursos" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Currículum" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Análisis del currículum" @@ -3951,4 +3945,3 @@ msgstr "Alejar" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulú" - diff --git a/locales/fa-IR.po b/locales/fa-IR.po index bba79ad5f..7c20088ee 100644 --- a/locales/fa-IR.po +++ b/locales/fa-IR.po @@ -2772,12 +2772,6 @@ msgstr "در حال تنظیم مجدد گذرواژه شما..." msgid "Resources" msgstr "منابع" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "رزومه" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "تحلیل رزومه" @@ -3951,4 +3945,3 @@ msgstr "کوچک‌نمایی" #: src/utils/locale.ts msgid "Zulu" msgstr "زولو" - diff --git a/locales/fi-FI.po b/locales/fi-FI.po index 5ac2ed39b..da027078c 100644 --- a/locales/fi-FI.po +++ b/locales/fi-FI.po @@ -2772,12 +2772,6 @@ msgstr "Palautetaan salasanaasi..." msgid "Resources" msgstr "Resurssit" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Yhteenveto" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Yhteenveto Analyysi" @@ -3951,4 +3945,3 @@ msgstr "Loitonna" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/fr-FR.po b/locales/fr-FR.po index 940f00ef1..dd385f662 100644 --- a/locales/fr-FR.po +++ b/locales/fr-FR.po @@ -2772,12 +2772,6 @@ msgstr "Réinitialisation de votre mot de passe..." msgid "Resources" msgstr "Ressources" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Curriculum vitae" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Analyse de CV" @@ -3951,4 +3945,3 @@ msgstr "Zoom arrière" #: src/utils/locale.ts msgid "Zulu" msgstr "Zoulou" - diff --git a/locales/he-IL.po b/locales/he-IL.po index 2bd104a9a..c421683cb 100644 --- a/locales/he-IL.po +++ b/locales/he-IL.po @@ -2772,12 +2772,6 @@ msgstr "איפוס הסיסמה שלך..." msgid "Resources" msgstr "משאבים" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "קורות חיים" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "ניתוח קורות חיים" @@ -3951,4 +3945,3 @@ msgstr "התרחקות" #: src/utils/locale.ts msgid "Zulu" msgstr "זולו" - diff --git a/locales/hi-IN.po b/locales/hi-IN.po index 189168f5c..76e7ce42c 100644 --- a/locales/hi-IN.po +++ b/locales/hi-IN.po @@ -2772,12 +2772,6 @@ msgstr "आपका पासवर्ड रीसेट किया जा msgid "Resources" msgstr "संसाधन" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "जीवन-परिचय" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "रिज़्यूमे विश्लेषण" @@ -3951,4 +3945,3 @@ msgstr "ज़ूम आउट" #: src/utils/locale.ts msgid "Zulu" msgstr "ज़ुलु" - diff --git a/locales/hu-HU.po b/locales/hu-HU.po index de2214562..4af9dc99a 100644 --- a/locales/hu-HU.po +++ b/locales/hu-HU.po @@ -2772,12 +2772,6 @@ msgstr "Jelszó visszaállítása..." msgid "Resources" msgstr "Erőforrások" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Önéletrajz" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Összefoglaló elemzés" @@ -3951,4 +3945,3 @@ msgstr "Kicsinyítés" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/id-ID.po b/locales/id-ID.po index 14fcb4526..18c6d9fde 100644 --- a/locales/id-ID.po +++ b/locales/id-ID.po @@ -2772,12 +2772,6 @@ msgstr "Mengatur ulang kata sandi Anda..." msgid "Resources" msgstr "Sumber Daya" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Melanjutkan" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Melanjutkan Analisis" @@ -3951,4 +3945,3 @@ msgstr "Perkecil" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/it-IT.po b/locales/it-IT.po index 1724fae1b..d644bca8e 100644 --- a/locales/it-IT.po +++ b/locales/it-IT.po @@ -2772,12 +2772,6 @@ msgstr "Reimpostazione della tua password in corso..." msgid "Resources" msgstr "Risorse" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Il curriculum" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Analisi del curriculum" @@ -3951,4 +3945,3 @@ msgstr "Rimpicciolisci" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/ja-JP.po b/locales/ja-JP.po index 3756eb5f3..33750679c 100644 --- a/locales/ja-JP.po +++ b/locales/ja-JP.po @@ -2772,12 +2772,6 @@ msgstr "パスワードをリセットしています..." msgid "Resources" msgstr "リソース" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "履歴書" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "履歴書分析" @@ -3951,4 +3945,3 @@ msgstr "ズームアウト" #: src/utils/locale.ts msgid "Zulu" msgstr "ズールー語" - diff --git a/locales/km-KH.po b/locales/km-KH.po index aa08b426c..7839159db 100644 --- a/locales/km-KH.po +++ b/locales/km-KH.po @@ -2772,12 +2772,6 @@ msgstr "កំពុង​កំណត់​ពាក្យសម្ងាត់ msgid "Resources" msgstr "ធនធាន" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "" @@ -3951,4 +3945,3 @@ msgstr "បង្រួម" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/kn-IN.po b/locales/kn-IN.po index 81876403e..d1afcb821 100644 --- a/locales/kn-IN.po +++ b/locales/kn-IN.po @@ -2772,12 +2772,6 @@ msgstr "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಮರು msgid "Resources" msgstr "ಸಂಪನ್ಮೂಲಗಳು" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "" @@ -3951,4 +3945,3 @@ msgstr "ಗಾತ್ರ ಕುಗ್ಗಿಸಿ" #: src/utils/locale.ts msgid "Zulu" msgstr "ಜೂಲೂ" - diff --git a/locales/ko-KR.po b/locales/ko-KR.po index e40ff04c9..9cde6d8af 100644 --- a/locales/ko-KR.po +++ b/locales/ko-KR.po @@ -2772,12 +2772,6 @@ msgstr "비밀번호를 재설정하는 중입니다..." msgid "Resources" msgstr "리소스" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "이력서" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "이력서 분석" @@ -3951,4 +3945,3 @@ msgstr "축소" #: src/utils/locale.ts msgid "Zulu" msgstr "줄루어" - diff --git a/locales/lt-LT.po b/locales/lt-LT.po index d9193cd86..c9739a3c1 100644 --- a/locales/lt-LT.po +++ b/locales/lt-LT.po @@ -2772,12 +2772,6 @@ msgstr "Atstatomas slaptažodis..." msgid "Resources" msgstr "Ištekliai" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "CV" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Gyvenimo aprašymo analizė" @@ -3951,4 +3945,3 @@ msgstr "Tolinti" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulų" - diff --git a/locales/lv-LV.po b/locales/lv-LV.po index dc46e79cf..dbbeb196a 100644 --- a/locales/lv-LV.po +++ b/locales/lv-LV.po @@ -2772,12 +2772,6 @@ msgstr "Tiek atiestatīta jūsu parole..." msgid "Resources" msgstr "Resursi" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "CV" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "CV analīze" @@ -3951,4 +3945,3 @@ msgstr "Tālināt" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/ml-IN.po b/locales/ml-IN.po index 8765e34ed..7bbbf701b 100644 --- a/locales/ml-IN.po +++ b/locales/ml-IN.po @@ -2772,12 +2772,6 @@ msgstr "നിങ്ങളുടെ പാസ്‌വേഡ് റീസെറ msgid "Resources" msgstr "റിസോഴ്സുകൾ" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "പുനരാരംഭിക്കുക" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "റെസ്യൂമെ വിശകലനം" @@ -3951,4 +3945,3 @@ msgstr "സൂം ഔട്ട് ചെയ്യുക" #: src/utils/locale.ts msgid "Zulu" msgstr "സൂളു" - diff --git a/locales/mr-IN.po b/locales/mr-IN.po index 3aed3180e..9a3098e48 100644 --- a/locales/mr-IN.po +++ b/locales/mr-IN.po @@ -2772,12 +2772,6 @@ msgstr "तुमचा पासवर्ड रीसेट केला ज msgid "Resources" msgstr "साधने" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "पुनरावलोकन" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "रेझ्युमे विश्लेषण" @@ -3951,4 +3945,3 @@ msgstr "बाहेर झूम करा" #: src/utils/locale.ts msgid "Zulu" msgstr "झुलू" - diff --git a/locales/ms-MY.po b/locales/ms-MY.po index 3d662d9c5..8110f8b7e 100644 --- a/locales/ms-MY.po +++ b/locales/ms-MY.po @@ -2772,12 +2772,6 @@ msgstr "Menetapkan semula kata laluan anda..." msgid "Resources" msgstr "Sumber" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Ringkasan" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Analisis Resume" @@ -3951,4 +3945,3 @@ msgstr "Zum keluar" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/ne-NP.po b/locales/ne-NP.po index 9fb8de438..158b134b8 100644 --- a/locales/ne-NP.po +++ b/locales/ne-NP.po @@ -2772,12 +2772,6 @@ msgstr "तपाईंको पासवर्ड रिसेट हुँद msgid "Resources" msgstr "स्रोतहरू" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "जीवन बृत्तान्त" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "बायोडाटा विश्लेषण" @@ -3951,4 +3945,3 @@ msgstr "जूम आउट" #: src/utils/locale.ts msgid "Zulu" msgstr "जुलु" - diff --git a/locales/nl-NL.po b/locales/nl-NL.po index 20ce45dac..dd98d8cbe 100644 --- a/locales/nl-NL.po +++ b/locales/nl-NL.po @@ -2772,12 +2772,6 @@ msgstr "Uw wachtwoord wordt gereset..." msgid "Resources" msgstr "Bronnen" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "CV" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "C.V. Analyse" @@ -3951,4 +3945,3 @@ msgstr "Uitzoomen" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/no-NO.po b/locales/no-NO.po index c8e68fa96..17d69998f 100644 --- a/locales/no-NO.po +++ b/locales/no-NO.po @@ -2772,12 +2772,6 @@ msgstr "Tilbakestiller passordet ditt..." msgid "Resources" msgstr "Ressurser" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "" @@ -3951,4 +3945,3 @@ msgstr "Zoom ut" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/or-IN.po b/locales/or-IN.po index af0073662..550031891 100644 --- a/locales/or-IN.po +++ b/locales/or-IN.po @@ -2772,12 +2772,6 @@ msgstr "ଆପଣଙ୍କ ପାସୱାର୍ଡ ରିସେଟ୍ ହେଉ msgid "Resources" msgstr "ସମ୍ପଦ" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "" @@ -3951,4 +3945,3 @@ msgstr "ଜୁମ୍ ଆଉଟ୍ କରନ୍ତୁ" #: src/utils/locale.ts msgid "Zulu" msgstr "ଜୁଲୁ" - diff --git a/locales/pl-PL.po b/locales/pl-PL.po index 56894c735..e198f4c90 100644 --- a/locales/pl-PL.po +++ b/locales/pl-PL.po @@ -2772,12 +2772,6 @@ msgstr "Resetowanie hasła..." msgid "Resources" msgstr "Zasoby" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Proszę wznowić" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Analiza CV" @@ -3951,4 +3945,3 @@ msgstr "Pomniejsz" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/pt-BR.po b/locales/pt-BR.po index c03001ce3..243ff37c4 100644 --- a/locales/pt-BR.po +++ b/locales/pt-BR.po @@ -2772,12 +2772,6 @@ msgstr "Redefinindo a sua senha..." msgid "Resources" msgstr "Recursos" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Currículo" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Análise de currículo" @@ -3951,4 +3945,3 @@ msgstr "Diminuir zoom" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/pt-PT.po b/locales/pt-PT.po index a72ba5e2d..9f5d23c69 100644 --- a/locales/pt-PT.po +++ b/locales/pt-PT.po @@ -2772,12 +2772,6 @@ msgstr "A repor a sua senha..." msgid "Resources" msgstr "Recursos" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Currículo" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Análise de currículos" @@ -3951,4 +3945,3 @@ msgstr "Afastar" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/ro-RO.po b/locales/ro-RO.po index 2bfdb9454..4b72a55e5 100644 --- a/locales/ro-RO.po +++ b/locales/ro-RO.po @@ -2772,12 +2772,6 @@ msgstr "Se resetează parola..." msgid "Resources" msgstr "Resurse" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "CV" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Analiza CV-ului" @@ -3951,4 +3945,3 @@ msgstr "Micșorează" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/ru-RU.po b/locales/ru-RU.po index 5dac421bb..364412596 100644 --- a/locales/ru-RU.po +++ b/locales/ru-RU.po @@ -2772,12 +2772,6 @@ msgstr "Сброс пароля..." msgid "Resources" msgstr "Ресурсы" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Резюме" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Анализ резюме" @@ -3951,4 +3945,3 @@ msgstr "Уменьшить" #: src/utils/locale.ts msgid "Zulu" msgstr "Зулу" - diff --git a/locales/sk-SK.po b/locales/sk-SK.po index 4244ded85..4fca42ad0 100644 --- a/locales/sk-SK.po +++ b/locales/sk-SK.po @@ -2772,12 +2772,6 @@ msgstr "Obnovujem tvoje heslo..." msgid "Resources" msgstr "Zdroje" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Životopis" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Analýza životopisu" @@ -3951,4 +3945,3 @@ msgstr "Oddialiť" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/sl-SI.po b/locales/sl-SI.po index cd621bbda..97cdc4d29 100644 --- a/locales/sl-SI.po +++ b/locales/sl-SI.po @@ -2772,12 +2772,6 @@ msgstr "Ponastavljanje gesla..." msgid "Resources" msgstr "Viri" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Življenjepis" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Analiza življenjepisa" @@ -3951,4 +3945,3 @@ msgstr "Oddalji" #: src/utils/locale.ts msgid "Zulu" msgstr "Zuluščina" - diff --git a/locales/sq-AL.po b/locales/sq-AL.po index 14ccd9aa1..5e200e2bf 100644 --- a/locales/sq-AL.po +++ b/locales/sq-AL.po @@ -2772,12 +2772,6 @@ msgstr "Po rivendoset fjalëkalimi juaj..." msgid "Resources" msgstr "Burime" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Përmbledhje" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Analiza e CV-së" @@ -3951,4 +3945,3 @@ msgstr "Zvogëlo" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/sr-SP.po b/locales/sr-SP.po index 4171d7ee1..ff3b68646 100644 --- a/locales/sr-SP.po +++ b/locales/sr-SP.po @@ -2772,12 +2772,6 @@ msgstr "Ресетовање ваше лозинке..." msgid "Resources" msgstr "Ресурси" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Резиме" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Анализа резимеа" @@ -3951,4 +3945,3 @@ msgstr "Умањи" #: src/utils/locale.ts msgid "Zulu" msgstr "Зулу" - diff --git a/locales/sv-SE.po b/locales/sv-SE.po index 9532ec2cb..0434678cc 100644 --- a/locales/sv-SE.po +++ b/locales/sv-SE.po @@ -2772,12 +2772,6 @@ msgstr "Återställer ditt lösenord..." msgid "Resources" msgstr "Resurser" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Meritförteckning" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Analys av CV" @@ -3951,4 +3945,3 @@ msgstr "Zooma ut" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/ta-IN.po b/locales/ta-IN.po index d797a3ae7..e8f5e2f41 100644 --- a/locales/ta-IN.po +++ b/locales/ta-IN.po @@ -2772,12 +2772,6 @@ msgstr "உங்கள் கடவுச்சொல்லை மீட்ட msgid "Resources" msgstr "வளங்கள்" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "தொடர்" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "விண்ணப்பப் பகுப்பாய்வு" @@ -3951,4 +3945,3 @@ msgstr "சிறிதாக்கு" #: src/utils/locale.ts msgid "Zulu" msgstr "ஜூலு" - diff --git a/locales/te-IN.po b/locales/te-IN.po index 21df74dbc..9614706e0 100644 --- a/locales/te-IN.po +++ b/locales/te-IN.po @@ -2772,12 +2772,6 @@ msgstr "మీ పాస్‌వర్డ్‌ను రీసెట్ చే msgid "Resources" msgstr "వనరులు" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "రిజ్యూమ్" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "రిజ్యూమ్ విశ్లేషణ" @@ -3951,4 +3945,3 @@ msgstr "జూమ్ అవుట్ చేయండి" #: src/utils/locale.ts msgid "Zulu" msgstr "జులు" - diff --git a/locales/th-TH.po b/locales/th-TH.po index 4b1c38331..f845c7d74 100644 --- a/locales/th-TH.po +++ b/locales/th-TH.po @@ -2772,12 +2772,6 @@ msgstr "กำลังรีเซ็ตรหัสผ่านของคุ msgid "Resources" msgstr "ทรัพยากร" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "ประวัติย่อ" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "การวิเคราะห์ประวัติย่อ" @@ -3951,4 +3945,3 @@ msgstr "ซูมออก" #: src/utils/locale.ts msgid "Zulu" msgstr "ซูลู" - diff --git a/locales/tr-TR.po b/locales/tr-TR.po index 2da112c40..6cc431ea3 100644 --- a/locales/tr-TR.po +++ b/locales/tr-TR.po @@ -2772,12 +2772,6 @@ msgstr "Şifreniz sıfırlanıyor..." msgid "Resources" msgstr "Kaynaklar" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Özgeçmiş" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Özgeçmiş Analizi" @@ -3951,4 +3945,3 @@ msgstr "Uzaklaştır" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/uk-UA.po b/locales/uk-UA.po index 59dff5208..ad3b33128 100644 --- a/locales/uk-UA.po +++ b/locales/uk-UA.po @@ -2772,12 +2772,6 @@ msgstr "Скидання пароля..." msgid "Resources" msgstr "Ресурси" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Резюме" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Аналіз резюме" @@ -3951,4 +3945,3 @@ msgstr "Зменшити" #: src/utils/locale.ts msgid "Zulu" msgstr "Зулу" - diff --git a/locales/uz-UZ.po b/locales/uz-UZ.po index 9144d6b45..9af54add0 100644 --- a/locales/uz-UZ.po +++ b/locales/uz-UZ.po @@ -2772,12 +2772,6 @@ msgstr "Parolingiz tiklanmoqda..." msgid "Resources" msgstr "Resurslar" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Rezyume" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Rezyume tahlili" @@ -3951,4 +3945,3 @@ msgstr "Kichraytirish" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/vi-VN.po b/locales/vi-VN.po index 941ff39e0..437144582 100644 --- a/locales/vi-VN.po +++ b/locales/vi-VN.po @@ -2772,12 +2772,6 @@ msgstr "Đang đặt lại mật khẩu..." msgid "Resources" msgstr "Tài nguyên" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "Sơ yếu lý lịch" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "Phân tích sơ yếu lý lịch" @@ -3951,4 +3945,3 @@ msgstr "Thu nhỏ" #: src/utils/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/locales/zh-CN.po b/locales/zh-CN.po index c3aee3d97..220859587 100644 --- a/locales/zh-CN.po +++ b/locales/zh-CN.po @@ -2772,12 +2772,6 @@ msgstr "正在重置你的密码…" msgid "Resources" msgstr "资源" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "简历" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "简历分析" @@ -3951,4 +3945,3 @@ msgstr "缩小" #: src/utils/locale.ts msgid "Zulu" msgstr "祖鲁语" - diff --git a/locales/zh-TW.po b/locales/zh-TW.po index d88c019d2..c44cf9374 100644 --- a/locales/zh-TW.po +++ b/locales/zh-TW.po @@ -2772,12 +2772,6 @@ msgstr "正在重設您的密碼…" msgid "Resources" msgstr "資源" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "簡歷" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "履歷分析" @@ -3951,4 +3945,3 @@ msgstr "縮小" #: src/utils/locale.ts msgid "Zulu" msgstr "祖魯語" - diff --git a/locales/zu-ZA.po b/locales/zu-ZA.po index 93f362cfa..f87cd62f2 100644 --- a/locales/zu-ZA.po +++ b/locales/zu-ZA.po @@ -2767,12 +2767,6 @@ msgstr "" msgid "Resources" msgstr "" -#. Browser tab suffix for printable resume pages -#. Browser tab title before printable resume data finishes loading -#: src/routes/printer/$resumeId.tsx -msgid "Resume" -msgstr "" - #: src/utils/resume/section.tsx msgid "Resume Analysis" msgstr "" diff --git a/src/components/resume/store/resume.ts b/src/components/resume/store/resume.ts index 4531b7912..2bc6cb9be 100644 --- a/src/components/resume/store/resume.ts +++ b/src/components/resume/store/resume.ts @@ -13,9 +13,16 @@ import { useStoreWithEqualityFn } from "zustand/traditional"; import type { ResumeData } from "@/schema/resume/data"; -import { orpc, type RouterOutput } from "@/integrations/orpc/client"; +import { orpc } from "@/integrations/orpc/client"; -type Resume = Pick; +type Resume = { + id: string; + name: string; + slug: string; + tags: string[]; + data: ResumeData; + isLocked: boolean; +}; type ResumeStoreState = { resume: Resume; diff --git a/src/integrations/auth/config.ts b/src/integrations/auth/config.ts index 114bf2376..0c40127a8 100644 --- a/src/integrations/auth/config.ts +++ b/src/integrations/auth/config.ts @@ -17,7 +17,7 @@ import { eq, or } from "drizzle-orm"; import { env } from "@/utils/env"; import { hashPassword, verifyPassword } from "@/utils/password"; import { generateId, toUsername } from "@/utils/string"; -import { isPrivateOrLoopbackHost, parseAllowedHostList, parseUrl } from "@/utils/url-security"; +import { isAllowedOAuthRedirectUri, parseAllowedHostList } from "@/utils/url-security"; import { schema } from "../drizzle"; import { db } from "../drizzle/client"; @@ -74,25 +74,6 @@ function getTrustedOrigins(): string[] { const TRUSTED_ORIGINS = getTrustedOrigins(); const OAUTH_DYNAMIC_CLIENT_REDIRECT_HOSTS = parseAllowedHostList(env.OAUTH_DYNAMIC_CLIENT_REDIRECT_HOSTS); -function isAllowedDynamicClientRedirectHost(origin: string, hostname: string): boolean { - if (TRUSTED_ORIGINS.includes(origin)) return true; - if (OAUTH_DYNAMIC_CLIENT_REDIRECT_HOSTS.has(origin)) return true; - return OAUTH_DYNAMIC_CLIENT_REDIRECT_HOSTS.has(hostname); -} - -function isAllowedDynamicClientRedirectUri(value: string) { - const parsed = parseUrl(value); - if (!parsed) return false; - if (parsed.username || parsed.password) return false; - if (parsed.hash) return false; - if (parsed.protocol !== "https:") return false; - if (isPrivateOrLoopbackHost(parsed.hostname)) return false; - - const origin = parsed.origin.toLowerCase(); - const hostname = parsed.hostname.toLowerCase(); - return isAllowedDynamicClientRedirectHost(origin, hostname); -} - async function findExistingUserByEmail(email: string) { const normalizedEmail = email.trim().toLowerCase(); @@ -284,7 +265,7 @@ const getAuthConfig = () => { if (typeof uri !== "string") { throw new APIError("BAD_REQUEST", { message: "redirect_uris entries must be strings" }); } - if (!isAllowedDynamicClientRedirectUri(uri)) { + if (!isAllowedOAuthRedirectUri(uri, TRUSTED_ORIGINS, OAUTH_DYNAMIC_CLIENT_REDIRECT_HOSTS)) { throw new APIError("BAD_REQUEST", { message: "redirect_uri is not allowed for dynamic client registration", }); @@ -409,6 +390,8 @@ const getAuthConfig = () => { consentPage: "/auth/oauth", validAudiences: OAUTH_AUDIENCES, allowDynamicClientRegistration: true, + // Required for MCP client onboarding (RFC 7591). Phishing vector is closed by the + // redirect_uri allowlist in the hooks.before middleware above and in src/routes/api/auth.$.ts. allowUnauthenticatedClientRegistration: true, rateLimit: { register: { window: 60, max: 5 }, diff --git a/src/integrations/orpc/router/resume.ts b/src/integrations/orpc/router/resume.ts index ffd255e02..36a804182 100644 --- a/src/integrations/orpc/router/resume.ts +++ b/src/integrations/orpc/router/resume.ts @@ -116,21 +116,6 @@ export const resumeRouter = { return resumeService.getById({ id: input.id, userId: context.user.id }); }), - getByIdForPrinter: publicProcedure - .route({ tags: ["Internal"], operationId: "getResumeForPrinter", summary: "Get resume by ID for printer" }) - .input( - resumeDto.getById.input.extend({ - token: z.string().optional(), - }), - ) - .handler(async ({ input, context }) => { - return resumeService.getByIdForPrinter({ - id: input.id, - currentUserId: context.user?.id, - printerToken: input.token, - }); - }), - getBySlug: publicProcedure .route({ method: "GET", diff --git a/src/routes/api/auth.$.ts b/src/routes/api/auth.$.ts index 7d21992c9..4d03cc197 100644 --- a/src/routes/api/auth.$.ts +++ b/src/routes/api/auth.$.ts @@ -2,9 +2,10 @@ import { createFileRoute } from "@tanstack/react-router"; import { auth } from "@/integrations/auth/config"; import { env } from "@/utils/env"; -import { isPrivateOrLoopbackHost, parseAllowedHostList, parseUrl } from "@/utils/url-security"; +import { isAllowedOAuthRedirectUri, parseAllowedHostList } from "@/utils/url-security"; const oauthDynamicClientRedirectHosts = parseAllowedHostList(env.OAUTH_DYNAMIC_CLIENT_REDIRECT_HOSTS); +const oauthTrustedOrigins = [new URL(env.APP_URL).origin.toLowerCase()]; const oauthAuthorizeSanitizedParams = [ "prompt", "redirect_uri", @@ -17,25 +18,6 @@ const oauthAuthorizeSanitizedParams = [ "resource", ] as const; -function isAllowedDynamicClientRedirectUri(value: string) { - const parsed = parseUrl(value); - if (!parsed) return false; - if (parsed.protocol !== "https:") return false; - if (parsed.username || parsed.password) return false; - if (parsed.hash) return false; - if (isPrivateOrLoopbackHost(parsed.hostname)) return false; - - const appOrigin = new URL(env.APP_URL).origin.toLowerCase(); - const origin = parsed.origin.toLowerCase(); - const hostname = parsed.hostname.toLowerCase(); - - if (origin === appOrigin) return true; - if (oauthDynamicClientRedirectHosts.has(origin)) return true; - if (oauthDynamicClientRedirectHosts.has(hostname)) return true; - - return false; -} - function sanitizeOAuthAuthorizeRequest(request: Request): Request { if (request.method !== "GET") return request; @@ -117,8 +99,14 @@ async function validateDynamicClientRegistrationRequest(request: Request): Promi const redirectUris = Array.isArray(body.redirect_uris) ? body.redirect_uris : []; for (const redirectUri of redirectUris) { - if (typeof redirectUri !== "string" || !isAllowedDynamicClientRedirectUri(redirectUri)) { - return Response.json({ message: "redirect_uri is not allowed" }, { status: 400 }); + if ( + typeof redirectUri !== "string" || + !isAllowedOAuthRedirectUri(redirectUri, oauthTrustedOrigins, oauthDynamicClientRedirectHosts) + ) { + return Response.json( + { error: "invalid_redirect_uri", error_description: "redirect_uri is not allowed" }, + { status: 400 }, + ); } } } diff --git a/src/routes/printer/$resumeId.tsx b/src/routes/printer/$resumeId.tsx index c9001282d..a9e800dd2 100644 --- a/src/routes/printer/$resumeId.tsx +++ b/src/routes/printer/$resumeId.tsx @@ -1,5 +1,5 @@ -import { t } from "@lingui/core/macro"; import { createFileRoute, redirect } from "@tanstack/react-router"; +import { createServerFn } from "@tanstack/react-start"; import { zodValidator } from "@tanstack/zod-adapter"; import { useEffect } from "react"; import { z } from "zod"; @@ -7,7 +7,7 @@ import { z } from "zod"; import { LoadingScreen } from "@/components/layout/loading-screen"; import { ResumePreview } from "@/components/resume/preview"; import { useResumeStore } from "@/components/resume/store/resume"; -import { getORPCClient } from "@/integrations/orpc/client"; +import { resumeService } from "@/integrations/orpc/services/resume"; import { env } from "@/utils/env"; import { verifyPrinterToken } from "@/utils/printer-token"; @@ -15,6 +15,12 @@ const searchSchema = z.object({ token: z.string().catch(""), }); +const getResumeForPrinterFn = createServerFn({ method: "GET" }) + .inputValidator(z.object({ id: z.string(), token: z.string() })) + .handler(({ data }) => { + return resumeService.getByIdForPrinter({ id: data.id, printerToken: data.token }); + }); + function assertValidPrinterToken(token: string, resumeId: string): void { const tokenResumeId = verifyPrinterToken(token); if (tokenResumeId === resumeId) return; @@ -35,25 +41,12 @@ export const Route = createFileRoute("/printer/$resumeId")({ }, loaderDeps: ({ search }) => ({ token: search.token }), loader: async ({ params, deps }) => { - const client = getORPCClient(); - const resume = await client.resume.getByIdForPrinter({ id: params.resumeId, token: deps.token }); + const resume = await getResumeForPrinterFn({ data: { id: params.resumeId, token: deps.token } }); return { resume }; }, head: ({ loaderData }) => ({ - meta: [ - { - title: loaderData - ? `${loaderData.resume.data.basics.name} - ${t({ - comment: "Browser tab suffix for printable resume pages", - message: "Resume", - })}` - : t({ - comment: "Browser tab title before printable resume data finishes loading", - message: "Resume", - }), - }, - ], + meta: [{ title: loaderData ? `${loaderData.resume.data.basics.name} - Resume` : "Resume" }], }), }); diff --git a/src/utils/url-security.test.ts b/src/utils/url-security.test.ts index 7241d4b06..4afc7d51e 100644 --- a/src/utils/url-security.test.ts +++ b/src/utils/url-security.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from "vite-plus/test"; import { + isAllowedOAuthRedirectUri, isAllowedExternalUrl, isPrivateOrLoopbackHost, parseAllowedHostList, @@ -55,6 +56,32 @@ describe("isAllowedExternalUrl", () => { }); }); +describe("isAllowedOAuthRedirectUri", () => { + const trustedOrigins = ["https://rxresu.me"]; + const allowedHosts = new Set(["https://client.example.com", "trusted.example.com"]); + + it("allows local loopback HTTP callbacks for native OAuth clients", () => { + expect(isAllowedOAuthRedirectUri("http://localhost:6188/callback", trustedOrigins, allowedHosts)).toBe(true); + expect(isAllowedOAuthRedirectUri("http://127.0.0.1:6188/callback", trustedOrigins, allowedHosts)).toBe(true); + expect(isAllowedOAuthRedirectUri("http://[::1]:6188/callback", trustedOrigins, allowedHosts)).toBe(true); + }); + + it("keeps rejecting unsafe HTTP and malformed redirects", () => { + expect(isAllowedOAuthRedirectUri("http://192.168.1.20:6188/callback", trustedOrigins, allowedHosts)).toBe(false); + expect(isAllowedOAuthRedirectUri("http://example.com/callback", trustedOrigins, allowedHosts)).toBe(false); + expect(isAllowedOAuthRedirectUri("not-a-url", trustedOrigins, allowedHosts)).toBe(false); + }); + + it("allows only trusted HTTPS redirects without credentials or fragments", () => { + expect(isAllowedOAuthRedirectUri("https://rxresu.me/callback", trustedOrigins, allowedHosts)).toBe(true); + expect(isAllowedOAuthRedirectUri("https://client.example.com/callback", trustedOrigins, allowedHosts)).toBe(true); + expect(isAllowedOAuthRedirectUri("https://trusted.example.com/callback", trustedOrigins, allowedHosts)).toBe(true); + expect(isAllowedOAuthRedirectUri("https://evil.example.com/callback", trustedOrigins, allowedHosts)).toBe(false); + expect(isAllowedOAuthRedirectUri("https://user:pass@rxresu.me/callback", trustedOrigins, allowedHosts)).toBe(false); + expect(isAllowedOAuthRedirectUri("https://rxresu.me/callback#token", trustedOrigins, allowedHosts)).toBe(false); + }); +}); + describe("sanitizeResumePictureUrl", () => { const appUrl = "https://rxresu.me"; diff --git a/src/utils/url-security.ts b/src/utils/url-security.ts index c0e00c847..a2b193835 100644 --- a/src/utils/url-security.ts +++ b/src/utils/url-security.ts @@ -47,6 +47,11 @@ export function isPrivateOrLoopbackHost(hostname: string) { return false; } +function isOAuthLoopbackRedirectHost(hostname: string) { + const normalized = stripIpv6Brackets(normalizeHostname(hostname)); + return normalized === "localhost" || normalized === "127.0.0.1" || normalized === "::1"; +} + export function parseUrl(input: string) { try { return new URL(input); @@ -80,6 +85,24 @@ export function isAllowedExternalUrl(input: string, allowedHosts: Set) { return allowedHosts.has(origin); } +export function isAllowedOAuthRedirectUri(input: string, trustedOrigins: string[], allowedHosts: Set) { + const parsed = parseUrl(input); + if (!parsed) return false; + if (parsed.username || parsed.password) return false; + if (parsed.hash) return false; + + const origin = parsed.origin.toLowerCase(); + const hostname = normalizeHostname(parsed.hostname); + + if (parsed.protocol === "http:") return isOAuthLoopbackRedirectHost(hostname); + if (parsed.protocol !== "https:") return false; + if (isPrivateOrLoopbackHost(hostname)) return false; + + if (trustedOrigins.includes(origin)) return true; + if (allowedHosts.has(origin)) return true; + return allowedHosts.has(hostname); +} + export function sanitizeResumePictureUrl(url: string, appUrl: string) { if (!url) return ""; if (url.startsWith("/uploads/")) return url;