Merge pull request #2108 from automatisch/aut-1282

test(access-token): write model tests
This commit is contained in:
Ömer Faruk Aydın
2024-10-02 10:16:49 +03:00
committed by GitHub
5 changed files with 161 additions and 7 deletions

View File

@@ -0,0 +1,41 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`AccessToken model > jsonSchema should have correct validations 1`] = `
{
"properties": {
"expiresIn": {
"type": "integer",
},
"id": {
"format": "uuid",
"type": "string",
},
"revokedAt": {
"format": "date-time",
"type": [
"string",
"null",
],
},
"samlSessionId": {
"type": [
"string",
"null",
],
},
"token": {
"minLength": 32,
"type": "string",
},
"userId": {
"format": "uuid",
"type": "string",
},
},
"required": [
"token",
"expiresIn",
],
"type": "object",
}
`;

View File

@@ -34,24 +34,25 @@ class AccessToken extends Base {
return;
}
const user = await this
.$relatedQuery('user');
const user = await this.$relatedQuery('user');
const firstIdentity = await user
.$relatedQuery('identities')
.first();
const firstIdentity = await user.$relatedQuery('identities').first();
const samlAuthProvider = await firstIdentity
.$relatedQuery('samlAuthProvider')
.throwIfNotFound();
const response = await samlAuthProvider.terminateRemoteSession(this.samlSessionId);
const response = await samlAuthProvider.terminateRemoteSession(
this.samlSessionId
);
return response;
}
async revoke() {
const response = await this.$query().patch({ revokedAt: new Date().toISOString() });
const response = await this.$query().patch({
revokedAt: new Date().toISOString(),
});
try {
await this.terminateRemoteSamlSession();

View File

@@ -0,0 +1,84 @@
import { describe, it, expect, vi } from 'vitest';
import AccessToken from './access-token.js';
import User from './user.js';
import Base from './base.js';
import SamlAuthProvider from './saml-auth-provider.ee.js';
import { createAccessToken } from '../../test/factories/access-token.js';
import { createUser } from '../../test/factories/user.js';
import { createIdentity } from '../../test/factories/identity.js';
describe('AccessToken model', () => {
it('tableName should return correct name', () => {
expect(AccessToken.tableName).toBe('access_tokens');
});
it('jsonSchema should have correct validations', () => {
expect(AccessToken.jsonSchema).toMatchSnapshot();
});
it('relationMappings should return correct associations', () => {
const relationMappings = AccessToken.relationMappings();
const expectedRelations = {
user: {
relation: Base.BelongsToOneRelation,
modelClass: User,
join: {
from: 'access_tokens.user_id',
to: 'users.id',
},
},
};
expect(relationMappings).toStrictEqual(expectedRelations);
});
it('revoke should set revokedAt and terminate remote SAML session', async () => {
const accessToken = await createAccessToken();
const terminateRemoteSamlSessionSpy = vi
.spyOn(accessToken, 'terminateRemoteSamlSession')
.mockImplementation(() => {});
await accessToken.revoke();
expect(terminateRemoteSamlSessionSpy).toHaveBeenCalledOnce();
expect(accessToken.revokedAt).not.toBeUndefined();
});
describe('terminateRemoteSamlSession', () => {
it('should terminate remote SAML session when exists', async () => {
const user = await createUser();
const accessToken = await createAccessToken({
userId: user.id,
samlSessionId: 'random-remote-session-id',
});
await createIdentity({ userId: user.id });
const terminateRemoteSamlSessionSpy = vi
.spyOn(SamlAuthProvider.prototype, 'terminateRemoteSession')
.mockImplementation(() => {});
await accessToken.terminateRemoteSamlSession();
expect(terminateRemoteSamlSessionSpy).toHaveBeenCalledWith(
accessToken.samlSessionId
);
});
it(`should return undefined when remote SALM session doesn't exist`, async () => {
const user = await createUser();
const accessToken = await createAccessToken({ userId: user.id });
await createIdentity({ userId: user.id });
const terminateRemoteSamlSessionSpy = vi
.spyOn(SamlAuthProvider.prototype, 'terminateRemoteSession')
.mockImplementation(() => {});
const expected = await accessToken.terminateRemoteSamlSession();
expect(terminateRemoteSamlSessionSpy).not.toHaveBeenCalledOnce();
expect(expected).toBeUndefined();
});
});
});

View File

@@ -0,0 +1,13 @@
import crypto from 'crypto';
import AccessToken from '../../src/models/access-token.js';
import { createUser } from './user.js';
export const createAccessToken = async (params = {}) => {
params.userId = params.userId || (await createUser()).id;
params.token = params.token || (await crypto.randomBytes(48).toString('hex'));
params.expiresIn = params.expiresIn || 14 * 24 * 60 * 60; // 14 days in seconds
const accessToken = await AccessToken.query().insertAndFetch(params);
return accessToken;
};

View File

@@ -0,0 +1,15 @@
import { faker } from '@faker-js/faker';
import Identity from '../../src/models/identity.ee.js';
import { createUser } from './user.js';
import { createSamlAuthProvider } from './saml-auth-provider.ee.js';
export const createIdentity = async (params = {}) => {
params.userId = params.userId || (await createUser()).id;
params.remoteId = params.remoteId || faker.string.uuid();
params.providerId = params.providerId || (await createSamlAuthProvider()).id;
params.providerType = 'saml';
const identity = await Identity.query().insertAndFetch(params);
return identity;
};