From 8c1eb882a3ffa6672ef388dd0671cba4e7ab1910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enes=20Yak=C4=B1=C5=9Ft=C4=B1r?= Date: Sun, 6 Sep 2026 11:35:45 +0300 Subject: [PATCH] feat: add auto-redirect-login setting with dynamic config synchronization (v1.0.7) --- README.md | 1 + client.js | 57 ++++++++++++++++++++++++++++++++++++- main.js | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 4 files changed, 138 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 32f7720..1974e16 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ In your PeerTube admin panel (**Administration > Plugins / Themes > Settings** f - **Client ID:** Your registered YakNet OAuth2 Application Client ID. - **Client Secret:** Your YakNet OAuth2 Client Secret. - **Auth Base URL:** Default is `https://auth.yakhub.com.tr`. +- **Auto-Redirect on Login:** Automatically bypass the standard login form and redirect users directly to YakNet SSO (also synchronizes `redirect_on_single_external_auth` in PeerTube configuration). --- diff --git a/client.js b/client.js index a794711..515d737 100644 --- a/client.js +++ b/client.js @@ -1,3 +1,58 @@ function registerClient({ registerHook, peertubeHelpers }) { - // YakNet client script + try { + fetch('/plugins/peertube-plugin-auth-yaknet/router/status') + .then(function (r) { + return r.json(); + }) + .then(function (status) { + if (!status || status.autoRedirectLogin === false) { + return; // Auto redirect is disabled by administrator + } + + var isLoginUrl = window.location.pathname.includes('/login'); + var isLocal = window.location.search.includes('local=true'); + var isError = window.location.search.includes('externalAuthError'); + + // If user directly visits /login without local override or error, forward to YakNet SSO + if (isLoginUrl && !isLocal && !isError) { + window.location.replace('/plugins/peertube-plugin-auth-yaknet/router/auth'); + return; + } + + // Intercept clicks on login links/buttons + document.addEventListener( + 'click', + function (e) { + var el = e.target; + if (el && el.closest) { + var isLoginBtn = el.closest( + 'my-login-link, .login-button, a[href*="/login"]:not(#yaktube-show-admin-login), a[aria-label*="Giriş"], a[title*="Giriş"], a[title*="login"], a[aria-label*="login"]' + ); + if (isLoginBtn && !window.location.search.includes('local=true')) { + e.preventDefault(); + e.stopPropagation(); + window.location.href = '/plugins/peertube-plugin-auth-yaknet/router/auth'; + } + } + }, + true + ); + }) + .catch(function () {}); + + // Alt+A shortcut for local admin login bypass + document.addEventListener('keydown', function (e) { + if (e.altKey && (e.key === 'a' || e.key === 'A')) { + if (!window.location.pathname.includes('/login')) { + window.location.href = '/login?local=true'; + } + } + }); + } catch (err) { + console.warn('[YakNet SSO] Client init error:', err); + } +} + +if (typeof module !== 'undefined' && module.exports) { + module.exports = { registerClient: registerClient }; } diff --git a/main.js b/main.js index a16abb8..bd6db43 100644 --- a/main.js +++ b/main.js @@ -109,13 +109,87 @@ async function register({ registerExternalAuth, registerSetting, settingsManager default: 'https://auth.yakhub.com.tr' }); + registerSetting({ + name: 'auto-redirect-login', + label: 'Giriş Sayfasında Doğrudan YakNet SSO\'ya Yönlendir', + type: 'input-checkbox', + description: 'Aktif olduğunda, kullanıcılar giriş butonuna veya /login sayfasına gittiğinde standart PeerTube şifre formu yerine doğrudan YakNet SSO sunucusuna yönlendirilir.', + private: false, + default: true + }); + + let autoRedirectLogin = true; + + function syncConfigFiles(enable) { + const fs = require('fs'); + const path = require('path'); + + // 1. Update local-production.json if present + const jsonCandidates = [ + path.resolve(process.cwd(), 'config', 'local-production.json'), + path.resolve(__dirname, '..', '..', 'config', 'local-production.json'), + path.resolve(__dirname, '..', '..', '..', 'config', 'local-production.json'), + 'c:/laragon/www/yaktube.yakhub.com.tr/config/local-production.json' + ]; + for (const jPath of jsonCandidates) { + if (fs.existsSync(jPath)) { + try { + const cfg = JSON.parse(fs.readFileSync(jPath, 'utf8')); + if (!cfg.menu) cfg.menu = {}; + if (!cfg.menu.login) cfg.menu.login = {}; + if (cfg.menu.login.redirect_on_single_external_auth !== enable) { + cfg.menu.login.redirect_on_single_external_auth = enable; + fs.writeFileSync(jPath, JSON.stringify(cfg, null, 2), 'utf8'); + logger.info(`[YakNet SSO] Synced local-production.json redirect_on_single_external_auth = ${enable}`); + } + } catch (e) { + logger.warn('[YakNet SSO] Error updating local-production.json:', e.message); + } + break; + } + } + + // 2. Update production.yaml if present + const yamlCandidates = [ + path.resolve(process.cwd(), 'config', 'production.yaml'), + path.resolve(__dirname, '..', '..', 'config', 'production.yaml'), + path.resolve(__dirname, '..', '..', '..', 'config', 'production.yaml'), + 'c:/laragon/www/yaktube.yakhub.com.tr/config/production.yaml' + ]; + for (const yPath of yamlCandidates) { + if (fs.existsSync(yPath)) { + try { + let yContent = fs.readFileSync(yPath, 'utf8'); + const pattern = /(redirect_on_single_external_auth:\s*)(true|false)/; + if (pattern.test(yContent)) { + const updated = yContent.replace(pattern, `$1${enable}`); + if (updated !== yContent) { + fs.writeFileSync(yPath, updated, 'utf8'); + logger.info(`[YakNet SSO] Synced production.yaml redirect_on_single_external_auth = ${enable}`); + } + } + } catch (e) { + logger.warn('[YakNet SSO] Error updating production.yaml:', e.message); + } + break; + } + } + } + async function loadSettings() { const cid = await settingsManager.getSetting('client-id'); const csec = await settingsManager.getSetting('client-secret'); const burl = await settingsManager.getSetting('auth-base-url'); + const autoRedir = await settingsManager.getSetting('auto-redirect-login'); if (cid) clientId = cid; if (csec) clientSecret = csec; if (burl) authBaseUrl = burl.replace(/\/+$/, ''); + if (autoRedir !== undefined && autoRedir !== null) { + autoRedirectLogin = autoRedir === true || autoRedir === 'true'; + } else { + autoRedirectLogin = true; + } + syncConfigFiles(autoRedirectLogin); } await loadSettings(); settingsManager.onSettingsChange(loadSettings); @@ -135,6 +209,12 @@ async function register({ registerExternalAuth, registerSetting, settingsManager const router = getRouter(); + router.get('/status', (req, res) => { + return res.json({ + autoRedirectLogin: autoRedirectLogin !== false + }); + }); + router.get('/auth', (req, res) => { const state = crypto.randomBytes(16).toString('hex'); const authUrl = `${authBaseUrl}/oauth/authorize?client_id=${encodeURIComponent(clientId)}&redirect_uri=${encodeURIComponent(callbackUrl)}&response_type=code&scope=&state=${state}`; diff --git a/package.json b/package.json index 9bd6ad8..a55d9c0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "peertube-plugin-auth-yaknet", - "version": "1.0.6", + "version": "1.0.7", "description": "YakNet SSO & OAuth2 Single Sign-On Authentication Plugin for PeerTube", "main": "main.js", "library": "./main.js",