110 lines
3.4 KiB
TypeScript
110 lines
3.4 KiB
TypeScript
|
|
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||
|
|
import * as smartdata from '@push.rocks/smartdata';
|
||
|
|
import * as smartdb from '@push.rocks/smartdb';
|
||
|
|
import * as path from 'path';
|
||
|
|
import * as os from 'os';
|
||
|
|
import * as fs from 'fs';
|
||
|
|
import { AccountAuthService, SmartdataAccountStore } from '../ts_server/index.js';
|
||
|
|
|
||
|
|
const createTestStore = async () => {
|
||
|
|
const storagePath = path.join(os.tmpdir(), `idp-sdk-account-store-${Date.now()}-${Math.random().toString(16).slice(2)}`);
|
||
|
|
const localSmartDb = new smartdb.LocalSmartDb({ folderPath: storagePath });
|
||
|
|
const connectionInfo = await localSmartDb.start();
|
||
|
|
const smartdataDb = new smartdata.SmartdataDb({
|
||
|
|
mongoDbUrl: connectionInfo.connectionUri,
|
||
|
|
mongoDbName: `idp-sdk-test-${Date.now()}`,
|
||
|
|
});
|
||
|
|
await smartdataDb.init();
|
||
|
|
const store = new SmartdataAccountStore({ smartdataDb });
|
||
|
|
await smartdataDb.mongoDb.createCollection('__test_init');
|
||
|
|
return {
|
||
|
|
store,
|
||
|
|
async cleanup() {
|
||
|
|
await smartdataDb.close();
|
||
|
|
await localSmartDb.stop();
|
||
|
|
await fs.promises.rm(storagePath, { recursive: true, force: true });
|
||
|
|
},
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
let testStore: Awaited<ReturnType<typeof createTestStore>>;
|
||
|
|
|
||
|
|
tap.test('setup account store test db', async () => {
|
||
|
|
testStore = await createTestStore();
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('SmartdataAccountStore only persists explicitly created accounts', async () => {
|
||
|
|
expect(await testStore.store.hasActiveAdminAccount()).toEqual(false);
|
||
|
|
expect(await testStore.store.getAccountByEmail('admin@example.com')).toBeNull();
|
||
|
|
|
||
|
|
const account = await testStore.store.createAccount({
|
||
|
|
email: 'Admin@Example.com',
|
||
|
|
name: 'Admin User',
|
||
|
|
role: 'admin',
|
||
|
|
authSources: ['local'],
|
||
|
|
password: 'correct horse battery staple',
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(account.emailNormalized).toEqual('admin@example.com');
|
||
|
|
expect(await testStore.store.hasActiveAdminAccount()).toEqual(true);
|
||
|
|
expect(account.passwordHash).not.toEqual('correct horse battery staple');
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('AccountAuthService authenticates local accounts only with valid password', async () => {
|
||
|
|
const authService = new AccountAuthService({ store: testStore.store });
|
||
|
|
|
||
|
|
expect(await authService.authenticate({
|
||
|
|
email: 'admin@example.com',
|
||
|
|
password: 'wrong',
|
||
|
|
authSource: 'local',
|
||
|
|
})).toBeNull();
|
||
|
|
|
||
|
|
const result = await authService.authenticate({
|
||
|
|
email: 'ADMIN@example.com',
|
||
|
|
password: 'correct horse battery staple',
|
||
|
|
authSource: 'local',
|
||
|
|
});
|
||
|
|
expect(result?.account.role).toEqual('admin');
|
||
|
|
expect(result?.authSource).toEqual('local');
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('AccountAuthService rejects IdP email mismatches', async () => {
|
||
|
|
await testStore.store.createAccount({
|
||
|
|
email: 'idp-admin@example.com',
|
||
|
|
name: 'IdP Admin User',
|
||
|
|
role: 'admin',
|
||
|
|
authSources: ['idp.global'],
|
||
|
|
});
|
||
|
|
const authService = new AccountAuthService({
|
||
|
|
store: testStore.store,
|
||
|
|
idpClient: {
|
||
|
|
loginWithEmailAndPassword: async () => ({
|
||
|
|
jwt: 'jwt',
|
||
|
|
refreshToken: 'refresh',
|
||
|
|
user: {
|
||
|
|
id: 'idp-user-1',
|
||
|
|
data: {
|
||
|
|
name: 'Other User',
|
||
|
|
username: 'other@example.com',
|
||
|
|
email: 'other@example.com',
|
||
|
|
status: 'active',
|
||
|
|
connectedOrgs: [],
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}),
|
||
|
|
} as any,
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(await authService.authenticate({
|
||
|
|
email: 'idp-admin@example.com',
|
||
|
|
password: 'idp-password',
|
||
|
|
authSource: 'idp.global',
|
||
|
|
})).toBeNull();
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('cleanup account store test db', async () => {
|
||
|
|
await testStore.cleanup();
|
||
|
|
});
|
||
|
|
|
||
|
|
export default tap.start();
|