// SSH Access — inbound admin SSH to this host. Lives in the Admin area (a
// sidebar item on the Config/Admin page) and renders into whatever container
// it's given (defaults to #config-section). Authorize public keys (paste to
// grant access), remove them, and toggle password login behind the backend's
// lockout guard. Reads /data/ssh/access.json; mutations run as
// `libreportal ssh ...` tasks. LibrePortal never handles a private key here.
class SshPage {
constructor(rootId = 'config-section') {
this.rootId = rootId;
this.taskManager = (typeof TaskManager !== 'undefined') ? new TaskManager() : null;
this.data = null;
this._bound = false;
}
root() { return document.getElementById(this.rootId); }
async init() {
const r = this.root();
if (r) r.innerHTML = '
No keys authorized yet — add one below to allow key-based login.
`;
// Reuse the config page's section layout (.config-category/.domains-*)
// so SSH Access looks like the rest of the Admin config pages.
const section = (title, desc, inner) => `
${title}
${desc}
${inner}
`;
const loginInner = `
Password login${pwOn ? 'On' : 'Key-only'}
Authorized keys${keys.length}
${pwOn
? ``
: ``}
`;
const addInner = `
`;
root.innerHTML = `
Tools
SSH Access
Control who can SSH into this server (logging in as ${this.escape(d.user)}). Grant access by adding a public key, and optionally require key-only login.
${section('Login', pwOn ? 'Password login is on. Add a key, then you can switch to key-only.' : 'Password login is disabled — only the keys below can connect.', loginInner)}
${section('Add a key', 'Authorize a new machine to log in.', addInner)}
${section('Authorized keys', 'Machines currently allowed to SSH in.', `
${keysHtml}
`)}
`;
}
async runTask(command) {
if (!this.taskManager) { this.notify('Task system unavailable', 'error'); return; }
try {
await this.taskManager.createTask(command, 'ssh', null);
setTimeout(() => this.refresh().then(() => this.render()), 1500);
} catch (e) {
this.notify(`Failed to queue task: ${e.message || e}`, 'error');
}
}
async addKey() {
const key = (document.getElementById('ssh-add-key-input')?.value || '').trim();
if (!key) { this.notify('Paste a public key first', 'error'); return; }
const b64 = btoa(unescape(encodeURIComponent(key)));
await this.runTask(`libreportal ssh key-add ${b64}`);
}
async removeKey(fp) {
if (!fp) return;
if (!confirm('Remove this key? That machine will no longer be able to SSH in.')) return;
await this.runTask(`libreportal ssh key-remove ${fp}`);
}
async togglePassword(next) {
if (next === 'off' && !confirm('Disable password login? Make sure a key above works first — otherwise you could lock yourself out.')) return;
await this.runTask(`libreportal ssh password-auth ${next}`);
}
}
window.SshPage = SshPage;