diff --git a/client.js b/client.js
index de15fde..459f02e 100644
--- a/client.js
+++ b/client.js
@@ -152,6 +152,117 @@
true
);
+ // 2.3 Dedicated Local Admin Login Modal (Alt+A)
+ function openLocalAdminLoginModal() {
+ var existingModal = document.getElementById('yaktube-admin-login-modal');
+ if (existingModal) {
+ existingModal.style.display = 'flex';
+ var uInput = existingModal.querySelector('#yaktube-admin-username');
+ if (uInput) uInput.focus();
+ return;
+ }
+
+ var modal = document.createElement('div');
+ modal.id = 'yaktube-admin-login-modal';
+ modal.className = 'yaktube-modal-overlay';
+ modal.setAttribute('role', 'dialog');
+ modal.setAttribute('aria-modal', 'true');
+ modal.setAttribute('aria-labelledby', 'yaktube-admin-modal-title');
+
+ modal.innerHTML =
+ '
' +
+ '
' +
+ '
⚙️ Sunucu Yöneticisi Girişi
' +
+ '' +
+ '' +
+ '
Yerel yönetici (admin) kullanıcı adı ve şifrenizle giriş yaparak PeerTube yönetim paneline erişebilirsiniz.
' +
+ '
' +
+ '
';
+
+ document.body.appendChild(modal);
+
+ modal.querySelector('#yaktube-admin-modal-close').addEventListener('click', function () {
+ modal.style.display = 'none';
+ });
+ modal.addEventListener('click', function (e) {
+ if (e.target === modal) modal.style.display = 'none';
+ });
+
+ var form = modal.querySelector('#yaktube-admin-direct-form');
+ var errEl = modal.querySelector('#yaktube-admin-login-error');
+ var uInput = modal.querySelector('#yaktube-admin-username');
+ var pInput = modal.querySelector('#yaktube-admin-password');
+ var sBtn = modal.querySelector('#yaktube-admin-login-submit');
+
+ uInput.focus();
+
+ form.addEventListener('submit', async function (ev) {
+ ev.preventDefault();
+ errEl.style.display = 'none';
+ sBtn.disabled = true;
+ sBtn.innerText = 'Giriş Yapılıyor...';
+
+ try {
+ var clientRes = await fetch('/api/v1/oauth-clients/local');
+ var clientData = await clientRes.json();
+
+ var bodyParams = new URLSearchParams({
+ client_id: clientData.client_id,
+ client_secret: clientData.client_secret,
+ grant_type: 'password',
+ username: uInput.value.trim(),
+ password: pInput.value
+ });
+
+ var tokenRes = await fetch('/api/v1/users/token', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+ body: bodyParams.toString()
+ });
+
+ var tokenData = await tokenRes.json();
+ if (!tokenRes.ok || !tokenData.access_token) {
+ throw new Error(tokenData.error_description || tokenData.error || 'Kullanıcı adı veya şifre hatalı.');
+ }
+
+ // Store tokens
+ localStorage.setItem('access_token', tokenData.access_token);
+ localStorage.setItem('refresh_token', tokenData.refresh_token);
+ localStorage.setItem('token_type', tokenData.token_type || 'Bearer');
+ localStorage.setItem('username', uInput.value.trim());
+
+ // Get user details
+ var meRes = await fetch('/api/v1/users/me', {
+ headers: { Authorization: 'Bearer ' + tokenData.access_token }
+ });
+ if (meRes.ok) {
+ var meData = await meRes.json();
+ localStorage.setItem('email', meData.email || '');
+ localStorage.setItem('displayName', meData.displayName || meData.username || '');
+ }
+
+ announce('Yönetici girişi başarılı! Yönetim paneline yönlendiriliyorsunuz.', true);
+ window.location.href = '/admin';
+ } catch (err) {
+ errEl.innerText = err.message;
+ errEl.style.display = 'block';
+ sBtn.disabled = false;
+ sBtn.innerText = 'Yönetici Olarak Giriş Yap';
+ }
+ });
+ }
+
// 2. YakNet SSO Header & Login Flow
function injectYakNetSSO() {
// 2.1 Header: Place YakNet Account widget in top-right .buttons-container
@@ -326,11 +437,7 @@
if (showAdminBtn) {
showAdminBtn.addEventListener('click', function (e) {
e.preventDefault();
- subElements.forEach(function (el) {
- el.style.display = '';
- });
- showAdminBtn.style.display = 'none';
- announce('Yönetici kullanıcı adı ve şifre giriş formu açıldı.');
+ openLocalAdminLoginModal();
});
}
}
@@ -340,6 +447,20 @@
// 3. Intelligent Branding & A11y DOM Auto-Fixer
function autoFixDOM() {
injectAccessiblePlayerBar();
+
+ // Check if on 403 / unauthorized page and provide admin login button
+ var notAuthorizedEl = document.querySelector('my-not-found, .not-found, .forbidden, my-forbidden, .error-page');
+ if (notAuthorizedEl && !document.getElementById('yaktube-403-admin-btn')) {
+ var btn403 = document.createElement('div');
+ btn403.id = 'yaktube-403-admin-btn';
+ btn403.style.margin = '20px auto';
+ btn403.style.textAlign = 'center';
+ btn403.innerHTML =
+ '';
+ btn403.querySelector('button').addEventListener('click', openLocalAdminLoginModal);
+ notAuthorizedEl.appendChild(btn403);
+ }
+
injectYakNetSSO();
// Aggressively remove generic Framasoft Open-in-App / Play Store banners
@@ -852,6 +973,13 @@
return;
}
+ // Admin Login: Alt+A
+ if (e.altKey && (e.key === 'a' || e.key === 'A') && !isInputFocused()) {
+ e.preventDefault();
+ openLocalAdminLoginModal();
+ return;
+ }
+
// Help Dialog: Alt+H, F1 or '?' key
if ((e.altKey && (e.key === 'h' || e.key === 'H')) || e.key === 'F1' || e.key === '?') {
if (!isInputFocused()) {
diff --git a/package.json b/package.json
index f7be73d..52cf8bb 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "peertube-plugin-yaktube-ondemand",
- "version": "1.4.1",
+ "version": "1.4.2",
"description": "Accessible On-Demand YouTube Import, Live Streams, Smart Recommendations and A11y Engine for PeerTube",
"main": "main.js",
"clientScripts": [