Files
BetterDesk/web-nodejs/tests/authService.providers.test.js
UNITRONIX 50d1942f8c fix(auth): show username collision when LDAP matches local account (#148)
Add Go LDAP verify endpoint and probe it from the console when a local
user's password fails, so valid domain credentials return HTTP 409 with a
clear collision message instead of a misleading password mismatch. Includes
i18n for auth.username_collision across all console locales.
2026-06-07 00:32:03 +02:00

88 lines
3.4 KiB
JavaScript

/**
* Auth provider helpers and database facade (Issue #148)
*/
const mockAdapter = {
createUser: jest.fn(),
syncUserFromGo: jest.fn(),
};
jest.mock('../services/dbAdapter', () => ({
getAdapter: () => mockAdapter,
DB_TYPE: 'sqlite',
}));
jest.mock('../config/config', () => ({
dataDir: '/tmp',
dbPath: '/tmp/test.db',
dbType: 'sqlite',
}));
const authService = require('../services/authService');
const db = require('../services/database');
describe('authService provider helpers', () => {
it('normalizeAuthProvider accepts ldap, oidc, local', () => {
expect(authService.normalizeAuthProvider('LDAP')).toBe('ldap');
expect(authService.normalizeAuthProvider('oidc')).toBe('oidc');
expect(authService.normalizeAuthProvider('')).toBe('local');
expect(authService.normalizeAuthProvider('saml')).toBe('local');
});
it('inferAuthProviderFromSSO prefers Go response auth_provider', () => {
expect(authService.inferAuthProviderFromSSO(
{ auth_provider: 'ldap', role: 'operator' },
{ ldap: true, oidc: false, any: true }
)).toBe('ldap');
});
it('inferAuthProviderFromSSO falls back to SSO status when Go omits provider', () => {
expect(authService.inferAuthProviderFromSSO(
{ role: 'viewer' },
{ ldap: false, oidc: true, any: true }
)).toBe('oidc');
expect(authService.inferAuthProviderFromSSO(
{ role: 'viewer' },
{ ldap: true, oidc: false, any: true }
)).toBe('ldap');
});
it('authFailure / isAuthFailure identify structured login failures', () => {
const failure = authService.authFailure('username_collision');
expect(authService.isAuthFailure(failure)).toBe(true);
expect(failure.__authFailure).toBe('username_collision');
expect(authService.isAuthFailure(null)).toBe(false);
expect(authService.isAuthFailure({ id: 1, username: 'u' })).toBe(false);
});
it('isExternalAuthProvider / isExternalAuthResult detect ldap/oidc', () => {
expect(authService.isExternalAuthProvider('ldap')).toBe(true);
expect(authService.isExternalAuthProvider('oidc')).toBe(true);
expect(authService.isExternalAuthProvider('local')).toBe(false);
expect(authService.isExternalAuthProvider('SAML')).toBe(false);
expect(authService.isExternalAuthResult({ auth_provider: 'ldap' })).toBe(true);
expect(authService.isExternalAuthResult({ auth_provider: 'oidc' })).toBe(true);
expect(authService.isExternalAuthResult({ auth_provider: 'local' })).toBe(false);
expect(authService.isExternalAuthResult(null)).toBe(false);
});
});
describe('database facade auth_provider', () => {
beforeEach(() => {
jest.clearAllMocks();
mockAdapter.createUser.mockResolvedValue({ id: 1, username: 'u', role: 'viewer', auth_provider: 'ldap' });
mockAdapter.syncUserFromGo.mockResolvedValue(undefined);
});
it('createUser forwards authProvider to the adapter', async () => {
await db.createUser('aduser', 'hash', 'operator', 'ldap');
expect(mockAdapter.createUser).toHaveBeenCalledWith('aduser', 'hash', 'operator', 'ldap');
});
it('syncUserFromGo is exposed on the facade', async () => {
await db.syncUserFromGo(3, { authProvider: 'ldap', role: 'admin' });
expect(mockAdapter.syncUserFromGo).toHaveBeenCalledWith(3, { authProvider: 'ldap', role: 'admin' });
});
});