feat(auth): implement JWT-based authentication with admin access controls
This commit is contained in:
130
test/test.jwt-auth.ts
Normal file
130
test/test.jwt-auth.ts
Normal file
@ -0,0 +1,130 @@
|
||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||
import { DcRouter } from '../ts/index.js';
|
||||
import { TypedRequest } from '@api.global/typedrequest';
|
||||
import * as interfaces from '../ts_interfaces/index.js';
|
||||
|
||||
let testDcRouter: DcRouter;
|
||||
let identity: interfaces.data.IIdentity;
|
||||
|
||||
tap.test('should start DCRouter with OpsServer', async () => {
|
||||
testDcRouter = new DcRouter({
|
||||
// Minimal config for testing
|
||||
});
|
||||
|
||||
await testDcRouter.start();
|
||||
expect(testDcRouter.opsServer).toBeInstanceOf(Object);
|
||||
});
|
||||
|
||||
tap.test('should login with admin credentials and receive JWT', async () => {
|
||||
const loginRequest = new TypedRequest<interfaces.requests.IReq_AdminLoginWithUsernameAndPassword>(
|
||||
'http://localhost:3000/typedrequest',
|
||||
'adminLoginWithUsernameAndPassword'
|
||||
);
|
||||
|
||||
const response = await loginRequest.fire({
|
||||
username: 'admin',
|
||||
password: 'admin'
|
||||
});
|
||||
|
||||
expect(response).toHaveProperty('identity');
|
||||
expect(response.identity).toHaveProperty('jwt');
|
||||
expect(response.identity).toHaveProperty('userId');
|
||||
expect(response.identity).toHaveProperty('name');
|
||||
expect(response.identity).toHaveProperty('expiresAt');
|
||||
expect(response.identity).toHaveProperty('role');
|
||||
expect(response.identity.role).toEqual('admin');
|
||||
|
||||
identity = response.identity;
|
||||
console.log('JWT:', identity.jwt);
|
||||
});
|
||||
|
||||
tap.test('should verify valid JWT identity', async () => {
|
||||
const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>(
|
||||
'http://localhost:3000/typedrequest',
|
||||
'verifyIdentity'
|
||||
);
|
||||
|
||||
const response = await verifyRequest.fire({
|
||||
identity
|
||||
});
|
||||
|
||||
expect(response).toHaveProperty('valid');
|
||||
expect(response.valid).toBeTrue();
|
||||
expect(response).toHaveProperty('identity');
|
||||
expect(response.identity.userId).toEqual(identity.userId);
|
||||
});
|
||||
|
||||
tap.test('should reject invalid JWT', async () => {
|
||||
const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>(
|
||||
'http://localhost:3000/typedrequest',
|
||||
'verifyIdentity'
|
||||
);
|
||||
|
||||
const response = await verifyRequest.fire({
|
||||
identity: {
|
||||
...identity,
|
||||
jwt: 'invalid.jwt.token'
|
||||
}
|
||||
});
|
||||
|
||||
expect(response).toHaveProperty('valid');
|
||||
expect(response.valid).toBeFalse();
|
||||
});
|
||||
|
||||
tap.test('should verify JWT matches identity data', async () => {
|
||||
const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>(
|
||||
'http://localhost:3000/typedrequest',
|
||||
'verifyIdentity'
|
||||
);
|
||||
|
||||
// The response should contain the same identity data as the JWT
|
||||
const response = await verifyRequest.fire({
|
||||
identity
|
||||
});
|
||||
|
||||
expect(response).toHaveProperty('valid');
|
||||
expect(response.valid).toBeTrue();
|
||||
expect(response.identity.expiresAt).toEqual(identity.expiresAt);
|
||||
expect(response.identity.userId).toEqual(identity.userId);
|
||||
});
|
||||
|
||||
tap.test('should handle logout', async () => {
|
||||
const logoutRequest = new TypedRequest<interfaces.requests.IReq_AdminLogout>(
|
||||
'http://localhost:3000/typedrequest',
|
||||
'adminLogout'
|
||||
);
|
||||
|
||||
const response = await logoutRequest.fire({
|
||||
identity
|
||||
});
|
||||
|
||||
expect(response).toHaveProperty('success');
|
||||
expect(response.success).toBeTrue();
|
||||
});
|
||||
|
||||
tap.test('should reject wrong credentials', async () => {
|
||||
const loginRequest = new TypedRequest<interfaces.requests.IReq_AdminLoginWithUsernameAndPassword>(
|
||||
'http://localhost:3000/typedrequest',
|
||||
'adminLoginWithUsernameAndPassword'
|
||||
);
|
||||
|
||||
let errorOccurred = false;
|
||||
try {
|
||||
await loginRequest.fire({
|
||||
username: 'admin',
|
||||
password: 'wrongpassword'
|
||||
});
|
||||
} catch (error) {
|
||||
errorOccurred = true;
|
||||
// TypedResponseError is thrown
|
||||
expect(error).toBeTruthy();
|
||||
}
|
||||
|
||||
expect(errorOccurred).toBeTrue();
|
||||
});
|
||||
|
||||
tap.test('should stop DCRouter', async () => {
|
||||
await testDcRouter.stop();
|
||||
});
|
||||
|
||||
export default tap.start();
|
Reference in New Issue
Block a user