feat: Admin UI — Accounts tab on service pages (Step 6)
Unit Tests / test (push) Failing after 11s

Admins previously had no UI path to provision per-peer accounts for
email, calendar, and files: they had to hit the AccountManager API
routes directly.  This change wires those routes to a dedicated Accounts
tab on each service page so any peer can be granted or revoked service
access in two clicks.

- webui/src/services/api.js: add accountsAPI with list/provision/
  deprovision/getCredentials, pointing to
  /api/services/catalog/{serviceId}/accounts
- webui/src/components/ServiceAccountsPanel.jsx: new reusable panel;
  handles credential reveal, removal confirmation, load-error state,
  and humanized credential labels
- EmailPage, CalendarPage, FilesPage: Overview/Accounts tab nav (admin
  only); Accounts tab renders ServiceAccountsPanel; AdminConfigSection
  is hidden while on the Accounts tab

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-28 20:29:57 -04:00
parent 16fb362df7
commit ad5731073d
5 changed files with 320 additions and 7 deletions
+14
View File
@@ -273,6 +273,20 @@ export const servicesAPI = {
restartService: (serviceName) => api.post(`/api/services/bus/services/${serviceName}/restart`),
};
// Accounts API (peer service account provisioning via AccountManager)
export const accountsAPI = {
list: (serviceId) => api.get(`/api/services/catalog/${serviceId}/accounts`),
provision: (serviceId, username, password) =>
api.post(`/api/services/catalog/${serviceId}/accounts`, {
username,
...(password ? { password } : {}),
}),
deprovision: (serviceId, username) =>
api.delete(`/api/services/catalog/${serviceId}/accounts/${username}`),
getCredentials: (serviceId, username) =>
api.get(`/api/services/catalog/${serviceId}/accounts/${username}/credentials`),
};
// Cell-to-cell connections API
export const cellLinkAPI = {
getInvite: () => api.get('/api/cells/invite'),