Git Komut Rehberi & Terminal Asistanı
Sıfırdan Yeni Bir Depo Başlatın:
Mevcut Bir Git Deposu veya Klasörü Gönderin:
Hataları Geri Alma, İptal & Temizlik:
Son commit'i geri al (yapılan değişiklikleri korur):
git reset --soft HEAD~1
Yapılan yerel değişiklikleri iptal et (çalışma ağacını temizler):
git restore .
Takip edilmeyen gereksiz dosyaları sil:
git clean -fd
Değişiklikleri geçici sakla ve geri getir (stash):
git stash git stash pop
Dal (Branch) ve Sürüm Etiketleri:
Yeni dal aç ve geçiş yap:
git checkout -b yeni-ozellik git push -u origin yeni-ozellik
Sürüm etiketi (tag) oluştur ve gönder:
git tag -a v1.0.0 -m "Sürüm 1.0.0" git push origin --tags
v1.0.11: Standalone multi-instance OAuth callback routing, DB user pre-sync, and externalAuthToken redirect loop fix (no bridge.js needed)
This commit is contained in:
@@ -12,9 +12,10 @@ async function register({ registerHook, peertubeHelpers }) {
|
|||||||
var isLoginUrl = window.location.pathname.includes('/login');
|
var isLoginUrl = window.location.pathname.includes('/login');
|
||||||
var isLocal = window.location.search.includes('local=true');
|
var isLocal = window.location.search.includes('local=true');
|
||||||
var isError = window.location.search.includes('externalAuthError');
|
var isError = window.location.search.includes('externalAuthError');
|
||||||
|
var isExternalToken = window.location.search.includes('externalAuthToken');
|
||||||
|
|
||||||
// If user directly visits /login without local override or error, forward to YakNet SSO
|
// CRITICAL: Never intercept /login when PeerTube is completing the externalAuthToken handshake!
|
||||||
if (isLoginUrl && !isLocal && !isError) {
|
if (isLoginUrl && !isLocal && !isError && !isExternalToken) {
|
||||||
window.location.replace('/plugins/auth-yaknet/router/auth');
|
window.location.replace('/plugins/auth-yaknet/router/auth');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -28,7 +29,11 @@ async function register({ registerHook, peertubeHelpers }) {
|
|||||||
var isLoginBtn = 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"]'
|
'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')) {
|
if (
|
||||||
|
isLoginBtn &&
|
||||||
|
!window.location.search.includes('local=true') &&
|
||||||
|
!window.location.search.includes('externalAuthToken')
|
||||||
|
) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
window.location.href = '/plugins/auth-yaknet/router/auth';
|
window.location.href = '/plugins/auth-yaknet/router/auth';
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const http = require('http');
|
|||||||
let clientId = '';
|
let clientId = '';
|
||||||
let clientSecret = '';
|
let clientSecret = '';
|
||||||
let authBaseUrl = 'https://developer-console.yakhub.com.tr';
|
let authBaseUrl = 'https://developer-console.yakhub.com.tr';
|
||||||
|
let customCallbackUrl = '';
|
||||||
|
|
||||||
function normalizeAuthUrl(urlStr) {
|
function normalizeAuthUrl(urlStr) {
|
||||||
if (typeof urlStr === 'string' && urlStr.includes('auth.yakhub.com.tr')) {
|
if (typeof urlStr === 'string' && urlStr.includes('auth.yakhub.com.tr')) {
|
||||||
@@ -37,7 +38,6 @@ function postRequest(urlStr, data, maxRedirects = 5) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
res => {
|
res => {
|
||||||
// Follow 301, 302, 307, 308 redirects automatically
|
|
||||||
if ([301, 302, 307, 308].includes(res.statusCode) && res.headers.location) {
|
if ([301, 302, 307, 308].includes(res.statusCode) && res.headers.location) {
|
||||||
const nextUrl = new URL(res.headers.location, safeUrlStr).toString();
|
const nextUrl = new URL(res.headers.location, safeUrlStr).toString();
|
||||||
return resolve(postRequest(nextUrl, data, maxRedirects - 1));
|
return resolve(postRequest(nextUrl, data, maxRedirects - 1));
|
||||||
@@ -83,7 +83,6 @@ function getRequest(urlStr, token, maxRedirects = 5) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
res => {
|
res => {
|
||||||
// Follow 301, 302, 307, 308 redirects automatically
|
|
||||||
if ([301, 302, 307, 308].includes(res.statusCode) && res.headers.location) {
|
if ([301, 302, 307, 308].includes(res.statusCode) && res.headers.location) {
|
||||||
const nextUrl = new URL(res.headers.location, safeUrlStr).toString();
|
const nextUrl = new URL(res.headers.location, safeUrlStr).toString();
|
||||||
return resolve(getRequest(nextUrl, token, maxRedirects - 1));
|
return resolve(getRequest(nextUrl, token, maxRedirects - 1));
|
||||||
@@ -108,6 +107,12 @@ function getRequest(urlStr, token, maxRedirects = 5) {
|
|||||||
|
|
||||||
async function register({ registerExternalAuth, registerSetting, settingsManager, getRouter, peertubeHelpers }) {
|
async function register({ registerExternalAuth, registerSetting, settingsManager, getRouter, peertubeHelpers }) {
|
||||||
const logger = peertubeHelpers.logger;
|
const logger = peertubeHelpers.logger;
|
||||||
|
const webserverUrl = (peertubeHelpers.config.getWebserverUrl() || '').replace(/\/+$/, '');
|
||||||
|
const isOfficialYakTube = webserverUrl.includes('yaktube.yakhub.com.tr');
|
||||||
|
// Standard PeerTube plugin router path uses short name (/plugins/auth-yaknet/router/auth-callback)
|
||||||
|
const defaultCallbackUrl = isOfficialYakTube
|
||||||
|
? `${webserverUrl}/plugins/peertube-plugin-auth-yaknet/router/auth-callback`
|
||||||
|
: `${webserverUrl}/plugins/auth-yaknet/router/auth-callback`;
|
||||||
|
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: 'client-id',
|
name: 'client-id',
|
||||||
@@ -136,6 +141,15 @@ async function register({ registerExternalAuth, registerSetting, settingsManager
|
|||||||
default: 'https://developer-console.yakhub.com.tr'
|
default: 'https://developer-console.yakhub.com.tr'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
registerSetting({
|
||||||
|
name: 'callback-url',
|
||||||
|
label: 'OAuth Callback (Redirect) URL (Opsiyonel)',
|
||||||
|
type: 'input',
|
||||||
|
description: `Boş bırakılırsa otomatik olarak "${defaultCallbackUrl}" kullanılır. YakNet Geliştirici Konsolu'nda tanımladığınız Redirect URI adresini buraya yazabilirsiniz.`,
|
||||||
|
private: false,
|
||||||
|
default: ''
|
||||||
|
});
|
||||||
|
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: 'auto-redirect-login',
|
name: 'auto-redirect-login',
|
||||||
label: "Giriş Sayfasında Doğrudan YakNet SSO'ya Yönlendir",
|
label: "Giriş Sayfasında Doğrudan YakNet SSO'ya Yönlendir",
|
||||||
@@ -152,6 +166,14 @@ async function register({ registerExternalAuth, registerSetting, settingsManager
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
|
// Update in-memory PeerTube ServerConfig if accessible
|
||||||
|
try {
|
||||||
|
const srvCfg = peertubeHelpers.config.getServerConfig();
|
||||||
|
if (srvCfg && srvCfg.client && srvCfg.client.menu && srvCfg.client.menu.login) {
|
||||||
|
srvCfg.client.menu.login.redirectOnSingleExternalAuth = enable;
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
// 1. Update local-production.json if present
|
// 1. Update local-production.json if present
|
||||||
const jsonCandidates = [
|
const jsonCandidates = [
|
||||||
path.resolve(process.cwd(), 'config', 'local-production.json'),
|
path.resolve(process.cwd(), 'config', 'local-production.json'),
|
||||||
@@ -208,12 +230,14 @@ async function register({ registerExternalAuth, registerSetting, settingsManager
|
|||||||
const cid = await settingsManager.getSetting('client-id');
|
const cid = await settingsManager.getSetting('client-id');
|
||||||
const csec = await settingsManager.getSetting('client-secret');
|
const csec = await settingsManager.getSetting('client-secret');
|
||||||
const burl = await settingsManager.getSetting('auth-base-url');
|
const burl = await settingsManager.getSetting('auth-base-url');
|
||||||
|
const cburl = await settingsManager.getSetting('callback-url');
|
||||||
const autoRedir = await settingsManager.getSetting('auto-redirect-login');
|
const autoRedir = await settingsManager.getSetting('auto-redirect-login');
|
||||||
if (cid) clientId = cid;
|
if (cid) clientId = String(cid).trim();
|
||||||
if (csec) clientSecret = csec;
|
if (csec) clientSecret = String(csec).trim();
|
||||||
if (burl) {
|
if (burl && String(burl).trim()) {
|
||||||
authBaseUrl = normalizeAuthUrl(burl.replace(/\/+$/, ''));
|
authBaseUrl = normalizeAuthUrl(String(burl).trim().replace(/\/+$/, ''));
|
||||||
}
|
}
|
||||||
|
customCallbackUrl = cburl ? String(cburl).trim() : '';
|
||||||
if (autoRedir !== undefined && autoRedir !== null) {
|
if (autoRedir !== undefined && autoRedir !== null) {
|
||||||
autoRedirectLogin = autoRedir === true || autoRedir === 'true';
|
autoRedirectLogin = autoRedir === true || autoRedir === 'true';
|
||||||
} else {
|
} else {
|
||||||
@@ -224,15 +248,26 @@ async function register({ registerExternalAuth, registerSetting, settingsManager
|
|||||||
await loadSettings();
|
await loadSettings();
|
||||||
settingsManager.onSettingsChange(loadSettings);
|
settingsManager.onSettingsChange(loadSettings);
|
||||||
|
|
||||||
const webserverUrl = peertubeHelpers.config.getWebserverUrl();
|
function getActiveCallbackUrl() {
|
||||||
const callbackUrl = `${webserverUrl}/plugins/peertube-plugin-auth-yaknet/router/auth-callback`;
|
return customCallbackUrl || defaultCallbackUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function dbQuery(sql, bindParams = []) {
|
||||||
|
if (!peertubeHelpers || !peertubeHelpers.database || typeof peertubeHelpers.database.query !== 'function') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const res = await peertubeHelpers.database.query(sql, { bind: bindParams });
|
||||||
|
if (Array.isArray(res) && Array.isArray(res[0])) return res[0];
|
||||||
|
return Array.isArray(res) ? res : [];
|
||||||
|
}
|
||||||
|
|
||||||
const externalAuth = registerExternalAuth({
|
const externalAuth = registerExternalAuth({
|
||||||
authName: 'yaknet',
|
authName: 'yaknet',
|
||||||
authDisplayName: () => 'YakNet ile Giriş Yap',
|
authDisplayName: () => 'YakNet ile Giriş Yap',
|
||||||
onAuthRequest: (req, res) => {
|
onAuthRequest: (req, res) => {
|
||||||
const state = crypto.randomBytes(16).toString('hex');
|
const state = crypto.randomBytes(16).toString('hex');
|
||||||
const authUrl = `${normalizeAuthUrl(authBaseUrl)}/oauth/authorize?client_id=${encodeURIComponent(clientId)}&redirect_uri=${encodeURIComponent(callbackUrl)}&response_type=code&scope=&state=${state}`;
|
const cbUrl = getActiveCallbackUrl();
|
||||||
|
const authUrl = `${normalizeAuthUrl(authBaseUrl)}/oauth/authorize?client_id=${encodeURIComponent(clientId)}&redirect_uri=${encodeURIComponent(cbUrl)}&response_type=code&scope=&state=${state}`;
|
||||||
return res.redirect(authUrl);
|
return res.redirect(authUrl);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -241,17 +276,20 @@ async function register({ registerExternalAuth, registerSetting, settingsManager
|
|||||||
|
|
||||||
router.get('/status', (req, res) => {
|
router.get('/status', (req, res) => {
|
||||||
return res.json({
|
return res.json({
|
||||||
autoRedirectLogin: autoRedirectLogin !== false
|
autoRedirectLogin: autoRedirectLogin !== false,
|
||||||
|
callbackUrl: getActiveCallbackUrl()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/auth', (req, res) => {
|
router.get('/auth', (req, res) => {
|
||||||
const state = crypto.randomBytes(16).toString('hex');
|
const state = crypto.randomBytes(16).toString('hex');
|
||||||
const authUrl = `${normalizeAuthUrl(authBaseUrl)}/oauth/authorize?client_id=${encodeURIComponent(clientId)}&redirect_uri=${encodeURIComponent(callbackUrl)}&response_type=code&scope=&state=${state}`;
|
const cbUrl = getActiveCallbackUrl();
|
||||||
|
const authUrl = `${normalizeAuthUrl(authBaseUrl)}/oauth/authorize?client_id=${encodeURIComponent(clientId)}&redirect_uri=${encodeURIComponent(cbUrl)}&response_type=code&scope=&state=${state}`;
|
||||||
return res.redirect(authUrl);
|
return res.redirect(authUrl);
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/auth-callback', async (req, res) => {
|
async function handleOAuthCallback(req, res) {
|
||||||
|
await loadSettings();
|
||||||
const code = req.query.code;
|
const code = req.query.code;
|
||||||
const error = req.query.error;
|
const error = req.query.error;
|
||||||
|
|
||||||
@@ -266,11 +304,12 @@ async function register({ registerExternalAuth, registerSetting, settingsManager
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const targetAuthUrl = normalizeAuthUrl(authBaseUrl);
|
const targetAuthUrl = normalizeAuthUrl(authBaseUrl);
|
||||||
|
const cbUrl = getActiveCallbackUrl();
|
||||||
const tokenRes = await postRequest(`${targetAuthUrl}/oauth/token`, {
|
const tokenRes = await postRequest(`${targetAuthUrl}/oauth/token`, {
|
||||||
grant_type: 'authorization_code',
|
grant_type: 'authorization_code',
|
||||||
client_id: clientId,
|
client_id: clientId,
|
||||||
client_secret: clientSecret,
|
client_secret: clientSecret,
|
||||||
redirect_uri: callbackUrl,
|
redirect_uri: cbUrl,
|
||||||
code: code
|
code: code
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -308,6 +347,30 @@ async function register({ registerExternalAuth, registerSetting, settingsManager
|
|||||||
? 0
|
? 0
|
||||||
: 2;
|
: 2;
|
||||||
|
|
||||||
|
// Pre-sync with PeerTube DB so existing accounts or username collisions never fail without bridge.js
|
||||||
|
try {
|
||||||
|
const existingByEmail = await dbQuery(
|
||||||
|
`SELECT id, username FROM "user" WHERE LOWER(email) = LOWER($1) LIMIT 1`,
|
||||||
|
[email]
|
||||||
|
);
|
||||||
|
if (existingByEmail.length > 0) {
|
||||||
|
username = existingByEmail[0].username;
|
||||||
|
await dbQuery(
|
||||||
|
`UPDATE "user" SET "pluginAuth" = 'peertube-plugin-auth-yaknet', "emailVerified" = true WHERE id = $1`,
|
||||||
|
[existingByEmail[0].id]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const existingByUsername = await dbQuery(`SELECT id FROM "user" WHERE LOWER(username) = LOWER($1) LIMIT 1`, [
|
||||||
|
username
|
||||||
|
]);
|
||||||
|
if (existingByUsername.length > 0) {
|
||||||
|
username = (username.substring(0, 42) + '_' + crypto.randomBytes(2).toString('hex')).toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (dbErr) {
|
||||||
|
logger.warn('[YakNet SSO] Pre-sync DB warning: ' + dbErr.message);
|
||||||
|
}
|
||||||
|
|
||||||
logger.info(`YakNet Authenticated user: ${username} (${email})`);
|
logger.info(`YakNet Authenticated user: ${username} (${email})`);
|
||||||
|
|
||||||
externalAuth.userAuthenticated({
|
externalAuth.userAuthenticated({
|
||||||
@@ -319,24 +382,37 @@ async function register({ registerExternalAuth, registerSetting, settingsManager
|
|||||||
role
|
role
|
||||||
});
|
});
|
||||||
|
|
||||||
if (peertubeHelpers && peertubeHelpers.database && peertubeHelpers.database.query) {
|
setTimeout(async () => {
|
||||||
setTimeout(async () => {
|
try {
|
||||||
try {
|
await dbQuery(
|
||||||
await peertubeHelpers.database.query('UPDATE "user" SET "emailVerified" = true WHERE email = $1', {
|
`UPDATE "user" SET "emailVerified" = true, "pluginAuth" = 'peertube-plugin-auth-yaknet' WHERE LOWER(email) = LOWER($1)`,
|
||||||
bind: [email]
|
[email]
|
||||||
});
|
);
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
logger.warn('Failed to auto-verify email in DB for ' + email, e);
|
}, 1000);
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Error processing YakNet auth callback:', err);
|
logger.error('Error processing YakNet auth callback:', err);
|
||||||
return res.redirect('/login?externalAuthError=true');
|
return res.redirect('/login?externalAuthError=true');
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
logger.info('YakNet SSO Plugin initialized with Callback URL: ' + callbackUrl);
|
router.get('/auth-callback', handleOAuthCallback);
|
||||||
|
|
||||||
|
// Also support legacy /plugins/peertube-plugin-auth-yaknet/router/auth-callback on any PeerTube server without bridge.js
|
||||||
|
try {
|
||||||
|
if (peertubeHelpers && peertubeHelpers.server && typeof peertubeHelpers.server.getHTTPServer === 'function') {
|
||||||
|
const httpServer = peertubeHelpers.server.getHTTPServer();
|
||||||
|
const listeners = httpServer ? httpServer.listeners('request') : [];
|
||||||
|
const expressApp = listeners && listeners[0];
|
||||||
|
if (expressApp && typeof expressApp.get === 'function') {
|
||||||
|
expressApp.get('/plugins/peertube-plugin-auth-yaknet/router/auth-callback', (req, res) => {
|
||||||
|
return handleOAuthCallback(req, res);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
logger.info('YakNet SSO Plugin initialized with Callback URL: ' + getActiveCallbackUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
async function unregister() {
|
async function unregister() {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "peertube-plugin-auth-yaknet",
|
"name": "peertube-plugin-auth-yaknet",
|
||||||
"version": "1.0.10",
|
"version": "1.0.11",
|
||||||
"description": "YakNet SSO & OAuth2 Single Sign-On Authentication Plugin for PeerTube",
|
"description": "YakNet SSO & OAuth2 Single Sign-On Authentication Plugin for PeerTube",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"library": "./main.js",
|
"library": "./main.js",
|
||||||
|
|||||||
Reference in New Issue
Block a user