Naut-Plugin-WebUI/public/js/api.js
ookami125 2df3f11cf4 webui: account management UI (users + change password)
Settings now has an Account card (current user/role + change password)
and, for admins, a Users card to add/delete users, reset passwords, and
toggle admin/user roles. Login captures the role; the Users section is
admin-only. api.js gains the account/user endpoints.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 21:48:05 -04:00

75 lines
3.3 KiB
JavaScript

// Thin API client + SSE live stream.
async function jget(url) {
const r = await fetch(url);
if (!r.ok) throw new Error(`${url}${r.status}`);
return r.json();
}
async function jpost(url, body) {
const r = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body || {}),
});
if (!r.ok) throw new Error(`${url}${r.status}`);
return r.json();
}
export const api = {
authStatus: () => jget('/api/auth/status'),
login: (username, password) => jpost('/api/login', { username, password }),
logout: () => jpost('/api/logout', {}),
// account management
changePassword: (oldPassword, newPassword) => jpost('/api/account/password', { oldPassword, newPassword }),
listUsers: () => jget('/api/users'),
createUser: (username, password, role) => jpost('/api/users', { username, password, role }),
deleteUser: (username) => jpost('/api/users/delete', { username }),
setUserPassword: (username, password) => jpost('/api/users/password', { username, password }),
setUserRole: (username, role) => jpost('/api/users/role', { username, role }),
plugins: () => jget('/api/plugins'),
meta: () => jget('/api/meta'),
snapshot: () => jget('/api/snapshot'),
torrent: (hash) => jget(`/api/torrents/${hash}`),
trackers: (hash) => jget(`/api/torrents/${hash}/trackers`),
peers: (hash) => jget(`/api/torrents/${hash}/peers`),
files: (hash) => jget(`/api/torrents/${hash}/files`),
pieces: (hash) => jget(`/api/torrents/${hash}/pieces`),
action: (action, hashes, params) => jpost('/api/action', { action, hashes, params }),
remove: (hashes, deleteFiles) => jpost('/api/delete', { hashes, deleteFiles }),
add: (opts) => jpost('/api/add', opts),
toggleAltSpeed: () => jpost('/api/altspeed', {}),
createCategory: (name, savePath) => jpost('/api/categories', { name, savePath }),
deleteCategory: (name) => jpost('/api/categories/delete', { name }),
editCategory: (name, newName, savePath) =>
jpost('/api/categories/edit', { name, newName, savePath }),
createTag: (name) => jpost('/api/tags', { name }),
deleteTag: (name) => jpost('/api/tags/delete', { name }),
rss: () => jget('/api/rss'),
rssRules: () => jget('/api/rss/rules'),
addFeed: (name, url) => jpost('/api/rss', { name, url }),
deleteFeed: (name) => jpost('/api/rss/delete', { name }),
saveRssRule: (rule) => jpost('/api/rss/rules', rule),
deleteRssRule: (name) => jpost('/api/rss/rules/delete', { name }),
runRssRule: (name) => jpost('/api/rss/rules/run', { name }),
refreshFeeds: (name) => jpost('/api/rss/refresh', name ? { name } : {}),
rssDownload: (item) => jpost('/api/rss/download', item),
saveIndexer: (ix) => jpost('/api/indexers', ix),
deleteIndexer: (name) => jpost('/api/indexers/delete', { name }),
script: () => jget('/api/script'),
saveScript: (source) => jpost('/api/script', { source }),
saveScriptSettings: (settings) => jpost('/api/script/settings', { settings }),
search: (q) => jget(`/api/search?q=${encodeURIComponent(q)}`),
// Live snapshot stream. onSnapshot(snapshot) called ~1/s.
stream(onSnapshot, onStatus) {
const es = new EventSource('/api/stream');
es.addEventListener('snapshot', (e) => onSnapshot(JSON.parse(e.data)));
es.onopen = () => onStatus && onStatus('connected');
es.onerror = () => onStatus && onStatus('reconnecting');
return es;
},
};