diff --git a/app/Http/Middleware/App/HandleInertiaRequests.php b/app/Http/Middleware/App/HandleInertiaRequests.php index 77a875e4..1978e0a4 100644 --- a/app/Http/Middleware/App/HandleInertiaRequests.php +++ b/app/Http/Middleware/App/HandleInertiaRequests.php @@ -51,6 +51,10 @@ public function share(Request $request): array 'hasActiveSubscription' => $account ? $account->hasActiveSubscription() : false, 'subscriptionPastDue' => $account ? $account->isPastDue() : false, ], + 'legal' => [ + 'terms' => (string) config('trypost.legal.terms_url'), + 'privacy' => (string) config('trypost.legal.privacy_url'), + ], 'usage' => $account && ! $isSelfHosted ? $account->usage() : null, 'features' => $account && ! $isSelfHosted ? $account->featureLimits() : null, 'onboardingProgress' => $this->onboardingProgress($request, $user), diff --git a/config/trypost.php b/config/trypost.php index f9d038e4..bfad557d 100644 --- a/config/trypost.php +++ b/config/trypost.php @@ -16,6 +16,22 @@ 'self_hosted' => env('SELF_HOSTED', true), + /* + |-------------------------------------------------------------------------- + | Legal pages + |-------------------------------------------------------------------------- + | + | Linked from the auth screens. Platform app reviews (TikTok explicitly) + | require Terms and Privacy links to be clearly visible; self-hosted + | installs point these at wherever they publish their own documents. + | + */ + + 'legal' => [ + 'terms_url' => env('LEGAL_TERMS_URL', 'https://trypost.it/terms'), + 'privacy_url' => env('LEGAL_PRIVACY_URL', 'https://trypost.it/privacy'), + ], + /* |-------------------------------------------------------------------------- | Meta page walk budget diff --git a/lang/ar/auth.php b/lang/ar/auth.php index 180f90dd..e02c18e7 100644 --- a/lang/ar/auth.php +++ b/lang/ar/auth.php @@ -22,7 +22,7 @@ 'welcome_trial' => 'مرحبًا بك في TryPost! لقد بدأت فترتك التجريبية.', ], - 'legal' => 'بمتابعتك، فإنك توافق على شروط الخدمة وسياسة الخصوصية.', + 'legal' => 'بمتابعتك، فإنك توافق على شروط الخدمة وسياسة الخصوصية.', 'slides' => [ 'calendar' => [ diff --git a/lang/de/auth.php b/lang/de/auth.php index 33733248..1be25cf6 100644 --- a/lang/de/auth.php +++ b/lang/de/auth.php @@ -24,7 +24,7 @@ 'welcome_trial' => 'Willkommen bei TryPost! Deine Testphase hat begonnen.', ], - 'legal' => 'Indem du fortfährst, stimmst du unseren Nutzungsbedingungen und unserer Datenschutzerklärung zu.', + 'legal' => 'Indem du fortfährst, stimmst du unseren Nutzungsbedingungen und unserer Datenschutzerklärung zu.', 'slides' => [ 'calendar' => [ diff --git a/lang/el/auth.php b/lang/el/auth.php index 2b480cda..7f92bd01 100644 --- a/lang/el/auth.php +++ b/lang/el/auth.php @@ -22,7 +22,7 @@ 'welcome_trial' => 'Καλώς ήρθατε στο TryPost! Η δοκιμαστική σας περίοδος ξεκίνησε.', ], - 'legal' => 'Συνεχίζοντας, συμφωνείτε με τους Όρους Χρήσης και την Πολιτική Απορρήτου μας.', + 'legal' => 'Συνεχίζοντας, συμφωνείτε με τους Όρους Χρήσης και την Πολιτική Απορρήτου μας.', 'slides' => [ 'calendar' => [ diff --git a/lang/en/auth.php b/lang/en/auth.php index 637a9441..4fa03da6 100644 --- a/lang/en/auth.php +++ b/lang/en/auth.php @@ -22,7 +22,7 @@ 'welcome_trial' => 'Welcome to TryPost! Your trial has started.', ], - 'legal' => 'By continuing, you agree to our Terms of Service and Privacy Policy.', + 'legal' => 'By continuing, you agree to our Terms of Service and Privacy Policy.', 'slides' => [ 'calendar' => [ diff --git a/lang/es/auth.php b/lang/es/auth.php index 77445a99..61bec34b 100644 --- a/lang/es/auth.php +++ b/lang/es/auth.php @@ -10,7 +10,7 @@ 'welcome_trial' => '¡Bienvenido a TryPost! Tu prueba ha comenzado.', ], - 'legal' => 'Al continuar, aceptas nuestros Términos de Servicio y Política de Privacidad.', + 'legal' => 'Al continuar, aceptas nuestros Términos de Servicio y Política de Privacidad.', 'slides' => [ 'calendar' => [ @@ -124,4 +124,5 @@ 'expired_description' => 'El workspace de esta invitación fue eliminado. Pide al propietario de la cuenta una nueva invitación si aún necesitas acceso.', 'expired_action' => 'Ir al inicio', ], + ]; diff --git a/lang/fr/auth.php b/lang/fr/auth.php index 904b4c1c..580693ca 100644 --- a/lang/fr/auth.php +++ b/lang/fr/auth.php @@ -22,7 +22,7 @@ 'welcome_trial' => 'Bienvenue sur TryPost ! Votre essai a commencé.', ], - 'legal' => 'En continuant, vous acceptez nos Conditions d\'utilisation et notre Politique de confidentialité.', + 'legal' => 'En continuant, vous acceptez nos Conditions d\'utilisation et notre Politique de confidentialité.', 'slides' => [ 'calendar' => [ diff --git a/lang/it/auth.php b/lang/it/auth.php index 44511b14..5defda15 100644 --- a/lang/it/auth.php +++ b/lang/it/auth.php @@ -22,7 +22,7 @@ 'welcome_trial' => 'Benvenuto su TryPost! La tua prova è iniziata.', ], - 'legal' => 'Continuando, accetti i nostri Termini di servizio e la nostra Informativa sulla privacy.', + 'legal' => 'Continuando, accetti i nostri Termini di servizio e la nostra Informativa sulla privacy.', 'slides' => [ 'calendar' => [ diff --git a/lang/ja/auth.php b/lang/ja/auth.php index 98df02db..3d6929c6 100644 --- a/lang/ja/auth.php +++ b/lang/ja/auth.php @@ -22,7 +22,7 @@ 'welcome_trial' => 'TryPost へようこそ!トライアルが開始されました。', ], - 'legal' => '続行すると、利用規約およびプライバシーポリシーに同意したものとみなされます。', + 'legal' => '続行すると、利用規約およびプライバシーポリシーに同意したものとみなされます。', 'slides' => [ 'calendar' => [ diff --git a/lang/ko/auth.php b/lang/ko/auth.php index cdf172d5..1f55b848 100644 --- a/lang/ko/auth.php +++ b/lang/ko/auth.php @@ -22,7 +22,7 @@ 'welcome_trial' => 'TryPost에 오신 것을 환영합니다! 체험이 시작되었습니다.', ], - 'legal' => '계속 진행하면 서비스 약관개인정보 처리방침에 동의하는 것입니다.', + 'legal' => '계속 진행하면 서비스 약관개인정보 처리방침에 동의하는 것입니다.', 'slides' => [ 'calendar' => [ diff --git a/lang/nl/auth.php b/lang/nl/auth.php index 471c6801..995f3ebb 100644 --- a/lang/nl/auth.php +++ b/lang/nl/auth.php @@ -22,7 +22,7 @@ 'welcome_trial' => 'Welkom bij TryPost! Je proefperiode is gestart.', ], - 'legal' => 'Door door te gaan ga je akkoord met onze Servicevoorwaarden en Privacybeleid.', + 'legal' => 'Door door te gaan ga je akkoord met onze Servicevoorwaarden en Privacybeleid.', 'slides' => [ 'calendar' => [ diff --git a/lang/pl/auth.php b/lang/pl/auth.php index 1cce8921..1d80a685 100644 --- a/lang/pl/auth.php +++ b/lang/pl/auth.php @@ -22,7 +22,7 @@ 'welcome_trial' => 'Witamy w TryPost! Twój okres próbny właśnie się rozpoczął.', ], - 'legal' => 'Kontynuując, akceptujesz nasze Warunki korzystania z usługi oraz Politykę prywatności.', + 'legal' => 'Kontynuując, akceptujesz nasze Warunki korzystania z usługi oraz Politykę prywatności.', 'slides' => [ 'calendar' => [ diff --git a/lang/pt-BR/auth.php b/lang/pt-BR/auth.php index 2ba690c7..34e4f8c6 100644 --- a/lang/pt-BR/auth.php +++ b/lang/pt-BR/auth.php @@ -22,7 +22,7 @@ 'welcome_trial' => 'Bem-vindo ao TryPost! Seu período de teste começou.', ], - 'legal' => 'Ao continuar, você concorda com nossos Termos de Serviço e Política de Privacidade.', + 'legal' => 'Ao continuar, você concorda com nossos Termos de Serviço e Política de Privacidade.', 'slides' => [ 'calendar' => [ diff --git a/lang/ru/auth.php b/lang/ru/auth.php index e813ed65..df7bc03c 100644 --- a/lang/ru/auth.php +++ b/lang/ru/auth.php @@ -22,7 +22,7 @@ 'welcome_trial' => 'Добро пожаловать в TryPost! Ваш пробный период начался.', ], - 'legal' => 'Продолжая, вы соглашаетесь с нашими Условиями использования и Политикой конфиденциальности.', + 'legal' => 'Продолжая, вы соглашаетесь с нашими Условиями использования и Политикой конфиденциальности.', 'slides' => [ 'calendar' => [ diff --git a/lang/tr/auth.php b/lang/tr/auth.php index d11255b4..a8ecbc75 100644 --- a/lang/tr/auth.php +++ b/lang/tr/auth.php @@ -24,7 +24,7 @@ 'welcome_trial' => 'TryPost\'a hoş geldiniz! Deneme süreniz başladı.', ], - 'legal' => 'Devam ederek Hizmet Şartları ve Gizlilik Politikası\'nı kabul etmiş olursunuz.', + 'legal' => 'Devam ederek Hizmet Şartları ve Gizlilik Politikası\'nı kabul etmiş olursunuz.', 'slides' => [ 'calendar' => [ diff --git a/lang/uk/auth.php b/lang/uk/auth.php index 33918920..f4ff78ce 100644 --- a/lang/uk/auth.php +++ b/lang/uk/auth.php @@ -22,7 +22,7 @@ 'welcome_trial' => 'Ласкаво просимо до TryPost! Ваш пробний період розпочато.', ], - 'legal' => 'Продовжуючи, ви погоджуєтеся з нашими Умовами використання та Політикою конфіденційності.', + 'legal' => 'Продовжуючи, ви погоджуєтеся з нашими Умовами використання та Політикою конфіденційності.', 'slides' => [ 'calendar' => [ diff --git a/lang/zh/auth.php b/lang/zh/auth.php index 4d3528fd..0b914697 100644 --- a/lang/zh/auth.php +++ b/lang/zh/auth.php @@ -22,7 +22,7 @@ 'welcome_trial' => '欢迎使用 TryPost!你的试用已开始。', ], - 'legal' => '继续即表示你同意我们的服务条款隐私政策。', + 'legal' => '继续即表示你同意我们的服务条款隐私政策。', 'slides' => [ 'calendar' => [ diff --git a/resources/js/components/auth/LegalLinks.vue b/resources/js/components/auth/LegalLinks.vue new file mode 100644 index 00000000..ea227693 --- /dev/null +++ b/resources/js/components/auth/LegalLinks.vue @@ -0,0 +1,25 @@ + + + diff --git a/resources/js/pages/auth/Login.vue b/resources/js/pages/auth/Login.vue index 02eab226..b285a62e 100644 --- a/resources/js/pages/auth/Login.vue +++ b/resources/js/pages/auth/Login.vue @@ -3,6 +3,7 @@ import { Form, Head, usePage } from '@inertiajs/vue3'; import { IconEye, IconEyeOff } from '@tabler/icons-vue'; import { computed, ref } from 'vue'; +import LegalLinks from '@/components/auth/LegalLinks.vue'; import SocialLogin from '@/components/auth/SocialLogin.vue'; import InputError from '@/components/InputError.vue'; import TextLink from '@/components/TextLink.vue'; @@ -183,6 +184,8 @@ const pageErrors = usePageErrors(); }} + + diff --git a/resources/js/pages/auth/Register.vue b/resources/js/pages/auth/Register.vue index 793d62e0..2c5c5087 100644 --- a/resources/js/pages/auth/Register.vue +++ b/resources/js/pages/auth/Register.vue @@ -3,6 +3,7 @@ import { Form, Head, usePage } from '@inertiajs/vue3'; import { IconEye, IconEyeOff, IconMail } from '@tabler/icons-vue'; import { computed, ref } from 'vue'; +import LegalLinks from '@/components/auth/LegalLinks.vue'; import SocialLogin from '@/components/auth/SocialLogin.vue'; import InputError from '@/components/InputError.vue'; import TextLink from '@/components/TextLink.vue'; @@ -29,7 +30,6 @@ const showPassword = ref(false); const showEmailForm = ref(false); const page = usePage(); -const isSelfHosted = computed(() => Boolean(page.props.selfHosted)); const hasSocial = computed( () => Boolean(page.props.googleAuthEnabled) || @@ -175,12 +175,7 @@ const emailFormVisible = computed(() => !hasSocial.value || showEmailForm.value) - -
+
diff --git a/resources/js/types/index.d.ts b/resources/js/types/index.d.ts index 8fe3313d..ea013048 100644 --- a/resources/js/types/index.d.ts +++ b/resources/js/types/index.d.ts @@ -85,6 +85,11 @@ export interface ContentTypeMediaRule { auto_fits_image: boolean; } +export interface LegalLinks { + terms: string; + privacy: string; +} + export interface SharedData { name: string; auth: Auth; @@ -93,6 +98,7 @@ export interface SharedData { sidebarOpen: boolean; selfHosted: boolean; allowMultipleSocialAccounts: boolean; + legal: LegalLinks; contentTypeMediaRules?: Record; [key: string]: unknown; } diff --git a/tests/Browser/AuthLegalLinksTest.php b/tests/Browser/AuthLegalLinksTest.php new file mode 100644 index 00000000..f512eea8 --- /dev/null +++ b/tests/Browser/AuthLegalLinksTest.php @@ -0,0 +1,21 @@ +assertVisible('@legal-links') + ->assertSeeLink('Terms of Service') + ->assertSeeLink('Privacy Policy') + ->assertNoJavaScriptErrors(); +}); + +test('the register screen shows the legal sentence to a logged out visitor', function () { + config(['trypost.self_hosted' => false]); + + visit(route('register')) + ->assertVisible('@legal-links') + ->assertSeeLink('Terms of Service') + ->assertSeeLink('Privacy Policy') + ->assertNoJavaScriptErrors(); +}); diff --git a/tests/Feature/Auth/LegalLinksTest.php b/tests/Feature/Auth/LegalLinksTest.php new file mode 100644 index 00000000..a94a20ea --- /dev/null +++ b/tests/Feature/Auth/LegalLinksTest.php @@ -0,0 +1,39 @@ +set('trypost.self_hosted', false); + config()->set('trypost.legal.terms_url', 'https://example.test/terms'); + config()->set('trypost.legal.privacy_url', 'https://example.test/privacy'); + + $this->get(route($route)) + ->assertOk() + ->assertInertia(fn ($page) => $page + ->where('legal.terms', 'https://example.test/terms') + ->where('legal.privacy', 'https://example.test/privacy') + ); +})->with(['login', 'register']); + +test('a self-hosted install can point the legal links at its own documents', function () { + config()->set('trypost.legal.terms_url', 'https://acme.test/legal/tos'); + config()->set('trypost.legal.privacy_url', 'https://acme.test/legal/privacy'); + + $this->get(route('login')) + ->assertInertia(fn ($page) => $page + ->where('legal.terms', 'https://acme.test/legal/tos') + ->where('legal.privacy', 'https://acme.test/legal/privacy') + ); +}); + +test('the legal sentence carries a url placeholder rather than a hardcoded host', function (string $locale) { + $sentence = require base_path("lang/{$locale}/auth.php"); + + expect($sentence['legal']) + ->toContain(':terms_url') + ->toContain(':privacy_url') + ->not->toContain('trypost.it'); +})->with(array_map( + fn (string $path) => basename(dirname($path)), + glob(dirname(__DIR__, 3).'/lang/*/auth.php'), +));