- Updated all package.json name fields and dependency references - Updated all TypeScript/JavaScript imports - Updated .woodpecker/publish.yml filters and registry paths - Updated tools/install.sh scope default - Updated .npmrc registry paths (worktree + host) - Enhanced update-checker.ts with checkForAllUpdates() multi-package support - Updated CLI update command to show table of all packages - Added KNOWN_PACKAGES, formatAllPackagesTable, getInstallAllCommand - Marked checkForUpdate() with @deprecated JSDoc Closes #391
162 lines
6.4 KiB
TypeScript
162 lines
6.4 KiB
TypeScript
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
import { buildOAuthProviders } from './auth.js';
|
|
|
|
describe('buildOAuthProviders', () => {
|
|
const originalEnv = process.env;
|
|
|
|
beforeEach(() => {
|
|
process.env = { ...originalEnv };
|
|
delete process.env['AUTHENTIK_CLIENT_ID'];
|
|
delete process.env['AUTHENTIK_CLIENT_SECRET'];
|
|
delete process.env['AUTHENTIK_ISSUER'];
|
|
delete process.env['WORKOS_CLIENT_ID'];
|
|
delete process.env['WORKOS_CLIENT_SECRET'];
|
|
delete process.env['WORKOS_ISSUER'];
|
|
delete process.env['KEYCLOAK_CLIENT_ID'];
|
|
delete process.env['KEYCLOAK_CLIENT_SECRET'];
|
|
delete process.env['KEYCLOAK_ISSUER'];
|
|
delete process.env['KEYCLOAK_URL'];
|
|
delete process.env['KEYCLOAK_REALM'];
|
|
});
|
|
|
|
afterEach(() => {
|
|
process.env = originalEnv;
|
|
});
|
|
|
|
it('returns empty array when no SSO env vars are set', () => {
|
|
const providers = buildOAuthProviders();
|
|
expect(providers).toHaveLength(0);
|
|
});
|
|
|
|
describe('WorkOS', () => {
|
|
it('includes workos provider when all required env vars are set', () => {
|
|
process.env['WORKOS_CLIENT_ID'] = 'client_test123';
|
|
process.env['WORKOS_CLIENT_SECRET'] = 'sk_live_test';
|
|
process.env['WORKOS_ISSUER'] = 'https://example.authkit.app/';
|
|
|
|
const providers = buildOAuthProviders();
|
|
const workos = providers.find((p) => p.providerId === 'workos');
|
|
|
|
expect(workos).toBeDefined();
|
|
expect(workos?.clientId).toBe('client_test123');
|
|
expect(workos?.issuer).toBe('https://example.authkit.app');
|
|
expect(workos?.discoveryUrl).toBe(
|
|
'https://example.authkit.app/.well-known/openid-configuration',
|
|
);
|
|
expect(workos?.scopes).toEqual(['openid', 'email', 'profile']);
|
|
});
|
|
|
|
it('throws when WorkOS is partially configured', () => {
|
|
process.env['WORKOS_CLIENT_ID'] = 'client_test123';
|
|
|
|
expect(() => buildOAuthProviders()).toThrow(
|
|
'@mosaicstack/auth: WorkOS SSO requires WORKOS_ISSUER, WORKOS_CLIENT_ID, WORKOS_CLIENT_SECRET.',
|
|
);
|
|
});
|
|
|
|
it('excludes workos provider when WorkOS is not configured', () => {
|
|
const providers = buildOAuthProviders();
|
|
const workos = providers.find((p) => p.providerId === 'workos');
|
|
expect(workos).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('Keycloak', () => {
|
|
it('includes keycloak provider when KEYCLOAK_ISSUER is set', () => {
|
|
process.env['KEYCLOAK_CLIENT_ID'] = 'mosaic';
|
|
process.env['KEYCLOAK_CLIENT_SECRET'] = 'secret123';
|
|
process.env['KEYCLOAK_ISSUER'] = 'https://auth.example.com/realms/myrealm/';
|
|
|
|
const providers = buildOAuthProviders();
|
|
const keycloakProvider = providers.find((p) => p.providerId === 'keycloak');
|
|
|
|
expect(keycloakProvider).toBeDefined();
|
|
expect(keycloakProvider?.clientId).toBe('mosaic');
|
|
expect(keycloakProvider?.discoveryUrl).toBe(
|
|
'https://auth.example.com/realms/myrealm/.well-known/openid-configuration',
|
|
);
|
|
expect(keycloakProvider?.scopes).toEqual(['openid', 'email', 'profile']);
|
|
});
|
|
|
|
it('supports deriving the Keycloak issuer from KEYCLOAK_URL and KEYCLOAK_REALM', () => {
|
|
process.env['KEYCLOAK_CLIENT_ID'] = 'mosaic';
|
|
process.env['KEYCLOAK_CLIENT_SECRET'] = 'secret123';
|
|
process.env['KEYCLOAK_URL'] = 'https://auth.example.com/';
|
|
process.env['KEYCLOAK_REALM'] = 'myrealm';
|
|
|
|
const providers = buildOAuthProviders();
|
|
const keycloakProvider = providers.find((p) => p.providerId === 'keycloak');
|
|
|
|
expect(keycloakProvider?.discoveryUrl).toBe(
|
|
'https://auth.example.com/realms/myrealm/.well-known/openid-configuration',
|
|
);
|
|
});
|
|
|
|
it('throws when Keycloak is partially configured', () => {
|
|
process.env['KEYCLOAK_CLIENT_ID'] = 'mosaic';
|
|
process.env['KEYCLOAK_CLIENT_SECRET'] = 'secret123';
|
|
|
|
expect(() => buildOAuthProviders()).toThrow(
|
|
'@mosaicstack/auth: Keycloak SSO requires KEYCLOAK_CLIENT_ID, KEYCLOAK_CLIENT_SECRET, KEYCLOAK_ISSUER.',
|
|
);
|
|
});
|
|
|
|
it('excludes keycloak provider when Keycloak is not configured', () => {
|
|
const providers = buildOAuthProviders();
|
|
const keycloakProvider = providers.find((p) => p.providerId === 'keycloak');
|
|
expect(keycloakProvider).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('Authentik', () => {
|
|
it('includes authentik provider when all required env vars are set', () => {
|
|
process.env['AUTHENTIK_CLIENT_ID'] = 'authentik-client';
|
|
process.env['AUTHENTIK_CLIENT_SECRET'] = 'authentik-secret';
|
|
process.env['AUTHENTIK_ISSUER'] = 'https://auth.example.com/application/o/mosaic/';
|
|
|
|
const providers = buildOAuthProviders();
|
|
const authentik = providers.find((p) => p.providerId === 'authentik');
|
|
|
|
expect(authentik).toBeDefined();
|
|
expect(authentik?.clientId).toBe('authentik-client');
|
|
expect(authentik?.issuer).toBe('https://auth.example.com/application/o/mosaic');
|
|
expect(authentik?.discoveryUrl).toBe(
|
|
'https://auth.example.com/application/o/mosaic/.well-known/openid-configuration',
|
|
);
|
|
});
|
|
|
|
it('throws when Authentik is partially configured', () => {
|
|
process.env['AUTHENTIK_CLIENT_ID'] = 'authentik-client';
|
|
|
|
expect(() => buildOAuthProviders()).toThrow(
|
|
'@mosaicstack/auth: Authentik SSO requires AUTHENTIK_ISSUER, AUTHENTIK_CLIENT_ID, AUTHENTIK_CLIENT_SECRET.',
|
|
);
|
|
});
|
|
|
|
it('excludes authentik provider when Authentik is not configured', () => {
|
|
const providers = buildOAuthProviders();
|
|
const authentik = providers.find((p) => p.providerId === 'authentik');
|
|
expect(authentik).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
it('registers all three providers when all env vars are set', () => {
|
|
process.env['AUTHENTIK_CLIENT_ID'] = 'a-id';
|
|
process.env['AUTHENTIK_CLIENT_SECRET'] = 'a-secret';
|
|
process.env['AUTHENTIK_ISSUER'] = 'https://auth.example.com/application/o/mosaic';
|
|
process.env['WORKOS_CLIENT_ID'] = 'w-id';
|
|
process.env['WORKOS_CLIENT_SECRET'] = 'w-secret';
|
|
process.env['WORKOS_ISSUER'] = 'https://example.authkit.app';
|
|
process.env['KEYCLOAK_CLIENT_ID'] = 'k-id';
|
|
process.env['KEYCLOAK_CLIENT_SECRET'] = 'k-secret';
|
|
process.env['KEYCLOAK_ISSUER'] = 'https://kc.example.com/realms/test';
|
|
|
|
const providers = buildOAuthProviders();
|
|
expect(providers).toHaveLength(3);
|
|
const ids = providers.map((p) => p.providerId);
|
|
expect(ids).toContain('authentik');
|
|
expect(ids).toContain('workos');
|
|
expect(ids).toContain('keycloak');
|
|
});
|
|
});
|