Skip to content

Commit

Permalink
fix: env in payload (#411)
Browse files Browse the repository at this point in the history
* fix: env in payload

send the environment to css app

* chore: add env

add env to axios callout

* chore: tests

comment back in tests
  • Loading branch information
jlangy authored Dec 3, 2024
1 parent 1097913 commit 2b12f0c
Show file tree
Hide file tree
Showing 6 changed files with 336 additions and 160 deletions.
9 changes: 4 additions & 5 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
name: Run unit tests

on:
# Commenting out as tests are empty
workflow_dispatch:
# push:
# paths:
# - 'docker/kc-cron-job/**'
# - '.github/workflows/unit-test.yml'
push:
paths:
- 'docker/kc-cron-job/**'
- '.github/workflows/unit-test.yml'

jobs:
unit_test:
Expand Down
1 change: 1 addition & 0 deletions docker/kc-cron-job/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ node_modules
npm-debug.log
__tests__
jest.config.js
.env
150 changes: 150 additions & 0 deletions docker/kc-cron-job/__tests__/remove-inactive-idir-users.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
const {
removeStaleUsersByEnv,
checkUserExistsAtIDIM,
removeUserFromCssApp,
MAX_DELETED_USERS_PER_RUNNER
} = require('../remove-inactive-idir-users');
const { getAdminClient, removeUserFromKc, getUserRolesMappings } = require('../helpers');
const axios = require('axios');

const pgMock = {
connect: jest.fn(() => Promise.resolve(true)),
query: jest.fn(() => Promise.resolve(true)),
end: jest.fn(() => Promise.resolve(true))
};

const mockUser = {
id: '123',
username: 'testuser@idir',
email: 'testemail',
firstName: 'john',
lastName: 'doe',
attributes: { idir_user_guid: 1, display_name: 'testuser' }
};

const realmRoles = ['realmRole'];
const clientRoles = [
{
client: 'test-client',
roles: ['role1', 'role2']
}
];

jest.mock('../helpers', () => {
return {
...jest.requireActual('../helpers'),
getAdminClient: jest.fn(() =>
Promise.resolve({
users: {
find: jest.fn(() => {
const users = Array(100).fill(mockUser);
return Promise.resolve(users);
}),
listRoleMappings: jest.fn(() =>
Promise.resolve({
realmMappings: [],
clientMappings: []
})
),
del: jest.fn(() => Promise.resolve(true))
},
reauth: jest.fn()
})
),
removeUserFromKc: jest.fn(() => Promise.resolve()),
getUserRolesMappings: jest.fn(() =>
Promise.resolve({
clientRoles,
realmRoles
})
)
};
});

jest.mock('../utils/bceid-webservice', () => {
const actualModule = jest.requireActual('../utils/bceid-webservice');
return {
...actualModule,
checkUserExistsAtIDIM: jest.fn(() => Promise.resolve('notexists'))
};
});

jest.mock('axios', () => {
return {
...jest.requireActual('axios'),
post: jest.fn(() => Promise.resolve({ status: 200 }))
};
});

describe('removeUserFromCssApp', () => {
it('Calls the CSS api with userdata, clientdata and environment', async () => {
const user = { id: 1, username: 'test' };
const clientData = [{ client: 'client', roles: ['role1', 'role2'] }];
await removeUserFromCssApp({ id: 1, username: 'test' }, [{ client: 'client', roles: ['role1', 'role2'] }], 'dev');

expect(axios.post).toHaveBeenCalledTimes(1);
const firstCallArgs = axios.post.mock.calls[0];
expect(firstCallArgs[1]).toEqual({ ...user, clientData, env: 'dev' });
});
});

describe('removeStaleUsersByEnv', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('Stops deleting once maximum is reached', async () => {
await removeStaleUsersByEnv('dev', pgMock, 'runnername', 0, () => {});
expect(removeUserFromKc).toHaveBeenCalledTimes(MAX_DELETED_USERS_PER_RUNNER);
expect(axios.post).toHaveBeenCalledTimes(MAX_DELETED_USERS_PER_RUNNER);
});

it('Saves deletion record to the database', async () => {
await removeStaleUsersByEnv('dev', pgMock, 'runnername', 0, () => {});
expect(pgMock.connect).toHaveBeenCalledTimes(1);

expect(pgMock.query).toHaveBeenCalledTimes(MAX_DELETED_USERS_PER_RUNNER);
pgMock.query.mock.calls.forEach((args) => {
// pg query arguments are Objects with keys text, values. Checking expected values match input data
const pgValues = args[0].values;
expect(pgValues).toEqual([
'dev',
mockUser.id,
mockUser.username,
mockUser.email,
mockUser.firstName,
mockUser.lastName,
JSON.stringify(mockUser.attributes),
realmRoles,
clientRoles.map((r) => JSON.stringify(r)),
// True indicates successful CSS response
true
]);
});
});

it('Records whether CSS App callout was successful to the database', async () => {
// Fail axios calls with not found
axios.post.mockResolvedValue({ status: 404 });
await removeStaleUsersByEnv('test', pgMock, 'runnername', 0, () => {});

expect(pgMock.query).toHaveBeenCalledTimes(MAX_DELETED_USERS_PER_RUNNER);
pgMock.query.mock.calls.forEach((args) => {
// pg query arguments are Objects with keys text, values. Checking expected values match input data
const pgValues = args[0].values;
expect(pgValues).toEqual([
'test',
mockUser.id,
mockUser.username,
mockUser.email,
mockUser.firstName,
mockUser.lastName,
JSON.stringify(mockUser.attributes),
realmRoles,
clientRoles.map((r) => JSON.stringify(r)),
// Records the CSS Failure
false
]);
});
});
});
32 changes: 31 additions & 1 deletion docker/kc-cron-job/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,34 @@ const getKcConfig = (environment) => {
};
};

async function removeUserFromKc(adminClient, id) {
try {
await adminClient.users.del({ realm: 'standard', id });
} catch (err) {
console.error(err);
}
}

async function getUserRolesMappings(adminClient, userId) {
try {
const clientRoles = [];
const roleMappings = await adminClient.users.listRoleMappings({ realm: 'standard', id: userId });
const realmRoles = roleMappings.realmMappings ? roleMappings.realmMappings.map((map) => map.name) : [];
if (roleMappings.clientMappings) {
for (const map in roleMappings.clientMappings) {
clientRoles.push({
client: roleMappings.clientMappings[map].client,
roles: roleMappings.clientMappings[map].mappings.map((role) => role.name)
});
}
}
return { realmRoles, clientRoles };
} catch (err) {
console.error(err);
throw new Error(`cannot fetch roles of user ${userId}`);
}
}

module.exports = {
oneMin: 60 * 1000,
getAdminClient: async function (env) {
Expand Down Expand Up @@ -108,5 +136,7 @@ module.exports = {
} finally {
await client.end();
}
}
},
removeUserFromKc,
getUserRolesMappings
};
Loading

0 comments on commit 2b12f0c

Please sign in to comment.