Wire auth modal to register.telecom.quest API (login + register flow)
This commit is contained in:
parent
ccf82b5040
commit
004c8a1920
88
index.html
88
index.html
@ -1414,11 +1414,12 @@ const SCHEDULE = [
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* ── AUTH ──────────────────────────────────────────────
|
/* ── AUTH ──────────────────────────────────────────────
|
||||||
Single-form login/register:
|
Smart single-form auth backed by register.telecom.quest.
|
||||||
- "Askar Tuleev" → CDN "atuleev" (initial + lastname, lowercase, latin only)
|
- Login first (works for both FIO and CDN inputs).
|
||||||
- "askar" → CDN "askar" (passed through)
|
- On 404 with FIO input → register (creates folder + Gitea repo).
|
||||||
Submit → save to localStorage → redirect to code-server in that folder.
|
- On 404 with CDN input → "not found, type your full name to register".
|
||||||
*/
|
*/
|
||||||
|
const API_BASE = 'https://register.telecom.quest/api';
|
||||||
const CODE_BASE = 'https://code.telecom.quest/?folder=/Users/telecom/dev/';
|
const CODE_BASE = 'https://code.telecom.quest/?folder=/Users/telecom/dev/';
|
||||||
const STORAGE_KEY = 'vibe.cdn';
|
const STORAGE_KEY = 'vibe.cdn';
|
||||||
|
|
||||||
@ -1472,8 +1473,18 @@ const SCHEDULE = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function redirectTo(cdn) {
|
function redirectTo(cdn, vscodeUrl) {
|
||||||
window.location.href = CODE_BASE + encodeURIComponent(cdn) + '/';
|
window.location.href = vscodeUrl || (CODE_BASE + encodeURIComponent(cdn) + '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function apiCall(path, body) {
|
||||||
|
const res = await fetch(API_BASE + path, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
const data = await res.json().catch(() => ({}));
|
||||||
|
return { ok: res.ok, status: res.status, data };
|
||||||
}
|
}
|
||||||
|
|
||||||
function openModal() {
|
function openModal() {
|
||||||
@ -1511,22 +1522,73 @@ const SCHEDULE = [
|
|||||||
submit.disabled = false;
|
submit.disabled = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
submit.addEventListener('click', () => {
|
async function handleSubmit() {
|
||||||
const { cdn } = makeCdn(input.value);
|
const { cdn, mode } = makeCdn(input.value);
|
||||||
if (!cdn) return;
|
if (!cdn) return;
|
||||||
localStorage.setItem(STORAGE_KEY, cdn);
|
|
||||||
|
submit.disabled = true;
|
||||||
|
submit.textContent = 'Проверяю...';
|
||||||
|
hint.classList.remove('error');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Step 1: try login (works for both CDN and FIO inputs)
|
||||||
|
const login = await apiCall('/login', { value: input.value.trim() });
|
||||||
|
|
||||||
|
if (login.ok) {
|
||||||
|
localStorage.setItem(STORAGE_KEY, login.data.cdn);
|
||||||
refreshHeader();
|
refreshHeader();
|
||||||
redirectTo(cdn);
|
redirectTo(login.data.cdn, login.data.vscode_url);
|
||||||
});
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: not found — for FIO mode, offer to register
|
||||||
|
if (login.status === 404 && mode === 'fio') {
|
||||||
|
submit.textContent = 'Создаю аккаунт...';
|
||||||
|
hint.innerHTML = `Аккаунт <code>${cdn}</code> не найден — создаю новый...`;
|
||||||
|
const reg = await apiCall('/register', { fio: input.value.trim() });
|
||||||
|
if (reg.ok) {
|
||||||
|
localStorage.setItem(STORAGE_KEY, reg.data.cdn);
|
||||||
|
refreshHeader();
|
||||||
|
redirectTo(reg.data.cdn, reg.data.vscode_url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// registration failed
|
||||||
|
const msg = reg.data?.detail?.message || reg.data?.detail?.error || `HTTP ${reg.status}`;
|
||||||
|
hint.textContent = `Не удалось создать: ${msg}`;
|
||||||
|
hint.classList.add('error');
|
||||||
|
} else if (login.status === 404) {
|
||||||
|
// CDN mode, no exact match — prompt full name
|
||||||
|
hint.innerHTML = `CDN <code>${cdn}</code> не найден. Введи имя и фамилию для регистрации.`;
|
||||||
|
hint.classList.add('error');
|
||||||
|
} else {
|
||||||
|
const msg = login.data?.detail?.message || login.data?.detail?.error || `HTTP ${login.status}`;
|
||||||
|
hint.textContent = `Ошибка: ${msg}`;
|
||||||
|
hint.classList.add('error');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
hint.textContent = `Ошибка сети: ${err.message || err}`;
|
||||||
|
hint.classList.add('error');
|
||||||
|
} finally {
|
||||||
|
submit.disabled = false;
|
||||||
|
submit.textContent = 'Открыть VS Code →';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
submit.addEventListener('click', handleSubmit);
|
||||||
|
|
||||||
input.addEventListener('keydown', (e) => {
|
input.addEventListener('keydown', (e) => {
|
||||||
if (e.key === 'Enter' && !submit.disabled) submit.click();
|
if (e.key === 'Enter' && !submit.disabled) handleSubmit();
|
||||||
if (e.key === 'Escape') closeModal();
|
if (e.key === 'Escape') closeModal();
|
||||||
});
|
});
|
||||||
|
|
||||||
authBtn.addEventListener('click', () => {
|
authBtn.addEventListener('click', () => {
|
||||||
const saved = localStorage.getItem(STORAGE_KEY);
|
const saved = localStorage.getItem(STORAGE_KEY);
|
||||||
if (saved) redirectTo(saved); else openModal();
|
if (saved) {
|
||||||
|
// Direct redirect using saved CDN — fast path, no API hit
|
||||||
|
redirectTo(saved);
|
||||||
|
} else {
|
||||||
|
openModal();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cdnChip.addEventListener('click', () => {
|
cdnChip.addEventListener('click', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user