sync: update from private repo (88dd58b)
CI / build-and-test (push) Has been cancelled

This commit is contained in:
oss-sync
2026-06-09 10:50:27 +00:00
parent 2bab882d08
commit 2ec9853655
17 changed files with 1099 additions and 27 deletions
+22 -4
View File
@@ -22,7 +22,7 @@ import { setSessionManager } from '../engine/tools/browser.js';
import { setUserFolderToolDeps } from '../engine/tools/user-folder.js';
import { setSkillToolDeps } from '../engine/tools/skills.js';
import { setAppDocsDeps } from '../engine/tools/app-docs.js';
import { setupAuth, requireAuth, requireAdmin, isProviderConfigured } from './auth.js';
import { setupAuth, requireAuth, requireAdmin, isProviderConfigured, isLocalEnabled, buildChangePasswordHandler } from './auth.js';
import { canUserSeeTask } from './visibility.js';
import { mountAdminApi } from './admin-api.js';
import { createAdminGatewayApi } from './admin-gateway-api.js';
@@ -238,14 +238,20 @@ export function createCoreServer(opts: CoreServerOptions): {
const _hasAnyField = (p?: { clientId?: string; clientSecret?: string; callbackUrl?: string; baseUrl?: string }) =>
!!(p?.clientId || p?.clientSecret || p?.callbackUrl || p?.baseUrl);
const authIntended = _hasAnyField(_authProviders?.google) || _hasAnyField(_authProviders?.gitea);
if (authIntended && !authUsable) {
// Local email+password is a first-class auth mode: when enabled, auth is
// active even without any OAuth provider.
const localEnabled = !!opts.authConfig && isLocalEnabled(opts.authConfig);
// Fail closed on a partial OAuth config ONLY when it would otherwise drop to
// no-auth. If local auth is on, auth is already active (no fail-open), so a
// half-configured OAuth provider just stays inactive rather than aborting boot.
if (authIntended && !authUsable && !localEnabled) {
throw new Error(
'[auth] auth is partially configured: a provider has a client_id but is missing ' +
'client_secret / callback_url (Gitea also needs base_url). Refusing to start in an ' +
'insecure no-auth state — complete the provider config or remove it from config.yaml.',
);
}
const authActive = authUsable;
const authActive = authUsable || localEnabled;
if (!authActive) {
// No-auth single-user mode: per-user rows are owned by the synthetic
// 'local' id, and several tables FK to users(id) (ssh_user_deks,
@@ -256,6 +262,15 @@ export function createCoreServer(opts: CoreServerOptions): {
let authenticateUpgrade: import('./auth.js').UpgradeAuthChecker | undefined;
if (authActive) {
// Idempotently seed the shared `local` system admin (id='local', the same
// owner the no-auth path uses) so an existing single-user / no-auth
// deployment gains a login mid-stream and keeps its `local`-owned data.
const bootstrap = opts.authConfig?.local?.bootstrapAdmin;
if (localEnabled && bootstrap?.email && bootstrap?.password) {
repo.upsertLocalSystemAdmin({ email: bootstrap.email, password: bootstrap.password });
logger.info(`[auth] seeded local system admin id=local email=${bootstrap.email}`);
}
const auth = setupAuth(
repo,
opts.authConfig!,
@@ -280,6 +295,9 @@ export function createCoreServer(opts: CoreServerOptions): {
res.json(req.user);
});
// Self-service password change for local accounts (see auth.ts).
app.post('/api/auth/password', requireAuth, express.json(), buildChangePasswordHandler(repo));
// Protect all API routes (except /api/version and /health)
app.use('/api/local', requireAuth);
app.use('/api/repos', requireAuth);
@@ -304,7 +322,7 @@ export function createCoreServer(opts: CoreServerOptions): {
// Admin user management API (always mounted; protected by requireAdmin when auth is active)
app.use('/api/admin', express.json());
mountAdminApi(app, repo, authActive);
mountAdminApi(app, repo, authActive, loadConfig()?.userFolderRoot ?? './data/users');
// AAO Gateway Phase 2a: admin-only CRUD over gateway_virtual_keys.
// Enabled regardless of gateway.enabled so an admin can prep keys