Merge pull request #1540 from automatisch/authentication-tests

feat: Add tests for authentication helper
This commit is contained in:
Ömer Faruk Aydın
2024-01-15 16:10:36 +01:00
committed by GitHub
10 changed files with 945 additions and 1027 deletions

View File

@@ -6,100 +6,74 @@ import { createRole } from '../../../test/factories/role';
import { createUser } from '../../../test/factories/user';
describe('graphQL getCurrentUser query', () => {
describe('with unauthenticated user', () => {
it('should throw not authorized error', async () => {
const invalidUserToken = 'invalid-token';
let role, currentUser, token, requestObject;
const query = `
query {
getCurrentUser {
id
email
}
}
`;
const response = await request(app)
.post('/graphql')
.set('Authorization', invalidUserToken)
.send({ query })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not Authorised!');
beforeEach(async () => {
role = await createRole({
key: 'sample',
name: 'sample',
});
currentUser = await createUser({
roleId: role.id,
});
token = createAuthTokenByUserId(currentUser.id);
requestObject = request(app).post('/graphql').set('Authorization', token);
});
describe('with authenticated user', () => {
let role, currentUser, token, requestObject;
beforeEach(async () => {
role = await createRole({
key: 'sample',
name: 'sample',
});
currentUser = await createUser({
roleId: role.id,
});
token = createAuthTokenByUserId(currentUser.id);
requestObject = request(app).post('/graphql').set('Authorization', token);
});
it('should return user data', async () => {
const query = `
query {
getCurrentUser {
it('should return user data', async () => {
const query = `
query {
getCurrentUser {
id
email
fullName
email
createdAt
updatedAt
role {
id
email
fullName
email
createdAt
updatedAt
role {
id
name
}
name
}
}
`;
}
`;
const response = await requestObject.send({ query }).expect(200);
const response = await requestObject.send({ query }).expect(200);
const expectedResponsePayload = {
data: {
getCurrentUser: {
createdAt: currentUser.createdAt.getTime().toString(),
email: currentUser.email,
fullName: currentUser.fullName,
id: currentUser.id,
role: { id: role.id, name: role.name },
updatedAt: currentUser.updatedAt.getTime().toString(),
},
const expectedResponsePayload = {
data: {
getCurrentUser: {
createdAt: currentUser.createdAt.getTime().toString(),
email: currentUser.email,
fullName: currentUser.fullName,
id: currentUser.id,
role: { id: role.id, name: role.name },
updatedAt: currentUser.updatedAt.getTime().toString(),
},
};
},
};
expect(response.body).toEqual(expectedResponsePayload);
});
expect(response.body).toEqual(expectedResponsePayload);
});
it('should not return user password', async () => {
const query = `
query {
getCurrentUser {
id
email
password
}
it('should not return user password', async () => {
const query = `
query {
getCurrentUser {
id
email
password
}
`;
}
`;
const response = await requestObject.send({ query }).expect(400);
const response = await requestObject.send({ query }).expect(400);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual(
'Cannot query field "password" on type "User".'
);
});
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual(
'Cannot query field "password" on type "User".'
);
});
});

View File

@@ -40,307 +40,291 @@ describe('graphQL getExecutions query', () => {
}
`;
const invalidToken = 'invalid-token';
describe('with unauthenticated user', () => {
describe('and without correct permissions', () => {
it('should throw not authorized error', async () => {
const userWithoutPermissions = await createUser();
const token = createAuthTokenByUserId(userWithoutPermissions.id);
const response = await request(app)
.post('/graphql')
.set('Authorization', invalidToken)
.set('Authorization', token)
.send({ query })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not Authorised!');
expect(response.body.errors[0].message).toEqual('Not authorized!');
});
});
describe('with authenticated user', () => {
describe('and without permissions', () => {
it('should throw not authorized error', async () => {
const userWithoutPermissions = await createUser();
const token = createAuthTokenByUserId(userWithoutPermissions.id);
describe('and with correct permission', () => {
let role,
currentUser,
anotherUser,
token,
flowOne,
stepOneForFlowOne,
stepTwoForFlowOne,
executionOne,
flowTwo,
stepOneForFlowTwo,
stepTwoForFlowTwo,
executionTwo,
flowThree,
stepOneForFlowThree,
stepTwoForFlowThree,
executionThree,
expectedResponseForExecutionOne,
expectedResponseForExecutionTwo,
expectedResponseForExecutionThree;
beforeEach(async () => {
role = await createRole({
key: 'sample',
name: 'sample',
});
currentUser = await createUser({
roleId: role.id,
fullName: 'Current User',
});
anotherUser = await createUser();
token = createAuthTokenByUserId(currentUser.id);
flowOne = await createFlow({
userId: currentUser.id,
});
stepOneForFlowOne = await createStep({
flowId: flowOne.id,
});
stepTwoForFlowOne = await createStep({
flowId: flowOne.id,
});
executionOne = await createExecution({
flowId: flowOne.id,
});
await createExecutionStep({
executionId: executionOne.id,
stepId: stepOneForFlowOne.id,
status: 'success',
});
await createExecutionStep({
executionId: executionOne.id,
stepId: stepTwoForFlowOne.id,
status: 'success',
});
flowTwo = await createFlow({
userId: currentUser.id,
});
stepOneForFlowTwo = await createStep({
flowId: flowTwo.id,
});
stepTwoForFlowTwo = await createStep({
flowId: flowTwo.id,
});
executionTwo = await createExecution({
flowId: flowTwo.id,
});
await createExecutionStep({
executionId: executionTwo.id,
stepId: stepOneForFlowTwo.id,
status: 'success',
});
await createExecutionStep({
executionId: executionTwo.id,
stepId: stepTwoForFlowTwo.id,
status: 'failure',
});
flowThree = await createFlow({
userId: anotherUser.id,
});
stepOneForFlowThree = await createStep({
flowId: flowThree.id,
});
stepTwoForFlowThree = await createStep({
flowId: flowThree.id,
});
executionThree = await createExecution({
flowId: flowThree.id,
});
await createExecutionStep({
executionId: executionThree.id,
stepId: stepOneForFlowThree.id,
status: 'success',
});
await createExecutionStep({
executionId: executionThree.id,
stepId: stepTwoForFlowThree.id,
status: 'failure',
});
expectedResponseForExecutionOne = {
node: {
createdAt: executionOne.createdAt.getTime().toString(),
flow: {
active: flowOne.active,
id: flowOne.id,
name: flowOne.name,
steps: [
{
iconUrl: `${appConfig.baseUrl}/apps/${stepOneForFlowOne.appKey}/assets/favicon.svg`,
},
{
iconUrl: `${appConfig.baseUrl}/apps/${stepTwoForFlowOne.appKey}/assets/favicon.svg`,
},
],
},
id: executionOne.id,
status: 'success',
testRun: executionOne.testRun,
updatedAt: executionOne.updatedAt.getTime().toString(),
},
};
expectedResponseForExecutionTwo = {
node: {
createdAt: executionTwo.createdAt.getTime().toString(),
flow: {
active: flowTwo.active,
id: flowTwo.id,
name: flowTwo.name,
steps: [
{
iconUrl: `${appConfig.baseUrl}/apps/${stepTwoForFlowTwo.appKey}/assets/favicon.svg`,
},
{
iconUrl: `${appConfig.baseUrl}/apps/${stepTwoForFlowTwo.appKey}/assets/favicon.svg`,
},
],
},
id: executionTwo.id,
status: 'failure',
testRun: executionTwo.testRun,
updatedAt: executionTwo.updatedAt.getTime().toString(),
},
};
expectedResponseForExecutionThree = {
node: {
createdAt: executionThree.createdAt.getTime().toString(),
flow: {
active: flowThree.active,
id: flowThree.id,
name: flowThree.name,
steps: [
{
iconUrl: `${appConfig.baseUrl}/apps/${stepOneForFlowThree.appKey}/assets/favicon.svg`,
},
{
iconUrl: `${appConfig.baseUrl}/apps/${stepTwoForFlowThree.appKey}/assets/favicon.svg`,
},
],
},
id: executionThree.id,
status: 'failure',
testRun: executionThree.testRun,
updatedAt: executionThree.updatedAt.getTime().toString(),
},
};
});
describe('and with isCreator condition', () => {
beforeEach(async () => {
await createPermission({
action: 'read',
subject: 'Execution',
roleId: role.id,
conditions: ['isCreator'],
});
});
it('should return executions data of the current user', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not authorized!');
const expectedResponsePayload = {
data: {
getExecutions: {
edges: [
expectedResponseForExecutionTwo,
expectedResponseForExecutionOne,
],
pageInfo: { currentPage: 1, totalPages: 1 },
},
},
};
expect(response.body).toEqual(expectedResponsePayload);
});
});
describe('and with correct permission', () => {
let role,
currentUser,
anotherUser,
token,
flowOne,
stepOneForFlowOne,
stepTwoForFlowOne,
executionOne,
flowTwo,
stepOneForFlowTwo,
stepTwoForFlowTwo,
executionTwo,
flowThree,
stepOneForFlowThree,
stepTwoForFlowThree,
executionThree,
expectedResponseForExecutionOne,
expectedResponseForExecutionTwo,
expectedResponseForExecutionThree;
describe('and without isCreator condition', () => {
beforeEach(async () => {
role = await createRole({
key: 'sample',
name: 'sample',
});
currentUser = await createUser({
await createPermission({
action: 'read',
subject: 'Execution',
roleId: role.id,
fullName: 'Current User',
});
anotherUser = await createUser();
token = createAuthTokenByUserId(currentUser.id);
flowOne = await createFlow({
userId: currentUser.id,
});
stepOneForFlowOne = await createStep({
flowId: flowOne.id,
});
stepTwoForFlowOne = await createStep({
flowId: flowOne.id,
});
executionOne = await createExecution({
flowId: flowOne.id,
});
await createExecutionStep({
executionId: executionOne.id,
stepId: stepOneForFlowOne.id,
status: 'success',
});
await createExecutionStep({
executionId: executionOne.id,
stepId: stepTwoForFlowOne.id,
status: 'success',
});
flowTwo = await createFlow({
userId: currentUser.id,
});
stepOneForFlowTwo = await createStep({
flowId: flowTwo.id,
});
stepTwoForFlowTwo = await createStep({
flowId: flowTwo.id,
});
executionTwo = await createExecution({
flowId: flowTwo.id,
});
await createExecutionStep({
executionId: executionTwo.id,
stepId: stepOneForFlowTwo.id,
status: 'success',
});
await createExecutionStep({
executionId: executionTwo.id,
stepId: stepTwoForFlowTwo.id,
status: 'failure',
});
flowThree = await createFlow({
userId: anotherUser.id,
});
stepOneForFlowThree = await createStep({
flowId: flowThree.id,
});
stepTwoForFlowThree = await createStep({
flowId: flowThree.id,
});
executionThree = await createExecution({
flowId: flowThree.id,
});
await createExecutionStep({
executionId: executionThree.id,
stepId: stepOneForFlowThree.id,
status: 'success',
});
await createExecutionStep({
executionId: executionThree.id,
stepId: stepTwoForFlowThree.id,
status: 'failure',
});
expectedResponseForExecutionOne = {
node: {
createdAt: executionOne.createdAt.getTime().toString(),
flow: {
active: flowOne.active,
id: flowOne.id,
name: flowOne.name,
steps: [
{
iconUrl: `${appConfig.baseUrl}/apps/${stepOneForFlowOne.appKey}/assets/favicon.svg`,
},
{
iconUrl: `${appConfig.baseUrl}/apps/${stepTwoForFlowOne.appKey}/assets/favicon.svg`,
},
],
},
id: executionOne.id,
status: 'success',
testRun: executionOne.testRun,
updatedAt: executionOne.updatedAt.getTime().toString(),
},
};
expectedResponseForExecutionTwo = {
node: {
createdAt: executionTwo.createdAt.getTime().toString(),
flow: {
active: flowTwo.active,
id: flowTwo.id,
name: flowTwo.name,
steps: [
{
iconUrl: `${appConfig.baseUrl}/apps/${stepTwoForFlowTwo.appKey}/assets/favicon.svg`,
},
{
iconUrl: `${appConfig.baseUrl}/apps/${stepTwoForFlowTwo.appKey}/assets/favicon.svg`,
},
],
},
id: executionTwo.id,
status: 'failure',
testRun: executionTwo.testRun,
updatedAt: executionTwo.updatedAt.getTime().toString(),
},
};
expectedResponseForExecutionThree = {
node: {
createdAt: executionThree.createdAt.getTime().toString(),
flow: {
active: flowThree.active,
id: flowThree.id,
name: flowThree.name,
steps: [
{
iconUrl: `${appConfig.baseUrl}/apps/${stepOneForFlowThree.appKey}/assets/favicon.svg`,
},
{
iconUrl: `${appConfig.baseUrl}/apps/${stepTwoForFlowThree.appKey}/assets/favicon.svg`,
},
],
},
id: executionThree.id,
status: 'failure',
testRun: executionThree.testRun,
updatedAt: executionThree.updatedAt.getTime().toString(),
},
};
});
describe('and with isCreator condition', () => {
beforeEach(async () => {
await createPermission({
action: 'read',
subject: 'Execution',
roleId: role.id,
conditions: ['isCreator'],
});
});
it('should return executions data of the current user', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query })
.expect(200);
const expectedResponsePayload = {
data: {
getExecutions: {
edges: [
expectedResponseForExecutionTwo,
expectedResponseForExecutionOne,
],
pageInfo: { currentPage: 1, totalPages: 1 },
},
},
};
expect(response.body).toEqual(expectedResponsePayload);
conditions: [],
});
});
describe('and without isCreator condition', () => {
beforeEach(async () => {
await createPermission({
action: 'read',
subject: 'Execution',
roleId: role.id,
conditions: [],
});
});
it('should return executions data of all users', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query })
.expect(200);
it('should return executions data of all users', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query })
.expect(200);
const expectedResponsePayload = {
data: {
getExecutions: {
edges: [
expectedResponseForExecutionThree,
expectedResponseForExecutionTwo,
expectedResponseForExecutionOne,
],
pageInfo: { currentPage: 1, totalPages: 1 },
},
const expectedResponsePayload = {
data: {
getExecutions: {
edges: [
expectedResponseForExecutionThree,
expectedResponseForExecutionTwo,
expectedResponseForExecutionOne,
],
pageInfo: { currentPage: 1, totalPages: 1 },
},
};
},
};
expect(response.body).toEqual(expectedResponsePayload);
expect(response.body).toEqual(expectedResponsePayload);
});
});
describe('and with filters', () => {
beforeEach(async () => {
await createPermission({
action: 'read',
subject: 'Execution',
roleId: role.id,
conditions: [],
});
});
describe('and with filters', () => {
beforeEach(async () => {
await createPermission({
action: 'read',
subject: 'Execution',
roleId: role.id,
conditions: [],
});
});
it('should return executions data for the specified flow', async () => {
const query = `
it('should return executions data for the specified flow', async () => {
const query = `
query {
getExecutions(limit: 10, offset: 0, filters: { flowId: "${flowOne.id}" }) {
pageInfo {
@@ -368,26 +352,26 @@ describe('graphQL getExecutions query', () => {
}
`;
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query })
.expect(200);
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query })
.expect(200);
const expectedResponsePayload = {
data: {
getExecutions: {
edges: [expectedResponseForExecutionOne],
pageInfo: { currentPage: 1, totalPages: 1 },
},
const expectedResponsePayload = {
data: {
getExecutions: {
edges: [expectedResponseForExecutionOne],
pageInfo: { currentPage: 1, totalPages: 1 },
},
};
},
};
expect(response.body).toEqual(expectedResponsePayload);
});
expect(response.body).toEqual(expectedResponsePayload);
});
it('should return only executions data with success status', async () => {
const query = `
it('should return only executions data with success status', async () => {
const query = `
query {
getExecutions(limit: 10, offset: 0, filters: { status: "success" }) {
pageInfo {
@@ -415,30 +399,30 @@ describe('graphQL getExecutions query', () => {
}
`;
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query })
.expect(200);
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query })
.expect(200);
const expectedResponsePayload = {
data: {
getExecutions: {
edges: [expectedResponseForExecutionOne],
pageInfo: { currentPage: 1, totalPages: 1 },
},
const expectedResponsePayload = {
data: {
getExecutions: {
edges: [expectedResponseForExecutionOne],
pageInfo: { currentPage: 1, totalPages: 1 },
},
};
},
};
expect(response.body).toEqual(expectedResponsePayload);
});
expect(response.body).toEqual(expectedResponsePayload);
});
it('should return only executions data within date range', async () => {
const createdAtFrom = executionOne.createdAt.getTime().toString();
it('should return only executions data within date range', async () => {
const createdAtFrom = executionOne.createdAt.getTime().toString();
const createdAtTo = executionOne.createdAt.getTime().toString();
const createdAtTo = executionOne.createdAt.getTime().toString();
const query = `
const query = `
query {
getExecutions(limit: 10, offset: 0, filters: { createdAt: { from: "${createdAtFrom}", to: "${createdAtTo}" }}) {
pageInfo {
@@ -466,23 +450,22 @@ describe('graphQL getExecutions query', () => {
}
`;
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query })
.expect(200);
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query })
.expect(200);
const expectedResponsePayload = {
data: {
getExecutions: {
edges: [expectedResponseForExecutionOne],
pageInfo: { currentPage: 1, totalPages: 1 },
},
const expectedResponsePayload = {
data: {
getExecutions: {
edges: [expectedResponseForExecutionOne],
pageInfo: { currentPage: 1, totalPages: 1 },
},
};
},
};
expect(response.body).toEqual(expectedResponsePayload);
});
expect(response.body).toEqual(expectedResponsePayload);
});
});
});

View File

@@ -40,222 +40,200 @@ describe('graphQL getFlow query', () => {
`;
};
describe('with unauthenticated user', () => {
describe('and without permissions', () => {
it('should throw not authorized error', async () => {
const invalidToken = 'invalid-token';
const userWithoutPermissions = await createUser();
const token = createAuthTokenByUserId(userWithoutPermissions.id);
const flow = await createFlow();
const response = await request(app)
.post('/graphql')
.set('Authorization', invalidToken)
.set('Authorization', token)
.send({ query: query(flow.id) })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not Authorised!');
expect(response.body.errors[0].message).toEqual('Not authorized!');
});
});
describe('with authenticated user', () => {
describe('and without permissions', () => {
it('should throw not authorized error', async () => {
const userWithoutPermissions = await createUser();
const token = createAuthTokenByUserId(userWithoutPermissions.id);
const flow = await createFlow();
describe('and with correct permission', () => {
let currentUser, currentUserRole, currentUserFlow;
beforeEach(async () => {
currentUserRole = await createRole();
currentUser = await createUser({ roleId: currentUserRole.id });
currentUserFlow = await createFlow({ userId: currentUser.id });
});
describe('and with isCreator condition', () => {
it('should return executions data of the current user', async () => {
await createPermission({
action: 'read',
subject: 'Flow',
roleId: currentUserRole.id,
conditions: ['isCreator'],
});
const triggerStep = await createStep({
flowId: currentUserFlow.id,
type: 'trigger',
key: 'catchRawWebhook',
webhookPath: `/webhooks/flows/${currentUserFlow.id}`,
});
const actionConnection = await createConnection({
userId: currentUser.id,
formattedData: {
screenName: 'Test',
authenticationKey: 'test key',
},
});
const actionStep = await createStep({
flowId: currentUserFlow.id,
type: 'action',
connectionId: actionConnection.id,
key: 'translateText',
});
const token = createAuthTokenByUserId(currentUser.id);
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query: query(flow.id) })
.send({ query: query(currentUserFlow.id) })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not authorized!');
const expectedResponsePayload = {
data: {
getFlow: {
active: currentUserFlow.active,
id: currentUserFlow.id,
name: currentUserFlow.name,
status: 'draft',
steps: [
{
appKey: triggerStep.appKey,
connection: null,
iconUrl: `${appConfig.baseUrl}/apps/${triggerStep.appKey}/assets/favicon.svg`,
id: triggerStep.id,
key: 'catchRawWebhook',
parameters: {},
position: 1,
status: triggerStep.status,
type: 'trigger',
webhookUrl: `${appConfig.baseUrl}/webhooks/flows/${currentUserFlow.id}`,
},
{
appKey: actionStep.appKey,
connection: {
createdAt: actionConnection.createdAt.getTime().toString(),
id: actionConnection.id,
verified: actionConnection.verified,
},
iconUrl: `${appConfig.baseUrl}/apps/${actionStep.appKey}/assets/favicon.svg`,
id: actionStep.id,
key: 'translateText',
parameters: {},
position: 1,
status: actionStep.status,
type: 'action',
webhookUrl: 'http://localhost:3000/null',
},
],
},
},
};
expect(response.body).toEqual(expectedResponsePayload);
});
});
describe('and with correct permission', () => {
let currentUser, currentUserRole, currentUserFlow;
beforeEach(async () => {
currentUserRole = await createRole();
currentUser = await createUser({ roleId: currentUserRole.id });
currentUserFlow = await createFlow({ userId: currentUser.id });
});
describe('and with isCreator condition', () => {
it('should return executions data of the current user', async () => {
await createPermission({
action: 'read',
subject: 'Flow',
roleId: currentUserRole.id,
conditions: ['isCreator'],
});
const triggerStep = await createStep({
flowId: currentUserFlow.id,
type: 'trigger',
key: 'catchRawWebhook',
webhookPath: `/webhooks/flows/${currentUserFlow.id}`,
});
const actionConnection = await createConnection({
userId: currentUser.id,
formattedData: {
screenName: 'Test',
authenticationKey: 'test key',
},
});
const actionStep = await createStep({
flowId: currentUserFlow.id,
type: 'action',
connectionId: actionConnection.id,
key: 'translateText',
});
const token = createAuthTokenByUserId(currentUser.id);
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query: query(currentUserFlow.id) })
.expect(200);
const expectedResponsePayload = {
data: {
getFlow: {
active: currentUserFlow.active,
id: currentUserFlow.id,
name: currentUserFlow.name,
status: 'draft',
steps: [
{
appKey: triggerStep.appKey,
connection: null,
iconUrl: `${appConfig.baseUrl}/apps/${triggerStep.appKey}/assets/favicon.svg`,
id: triggerStep.id,
key: 'catchRawWebhook',
parameters: {},
position: 1,
status: triggerStep.status,
type: 'trigger',
webhookUrl: `${appConfig.baseUrl}/webhooks/flows/${currentUserFlow.id}`,
},
{
appKey: actionStep.appKey,
connection: {
createdAt: actionConnection.createdAt
.getTime()
.toString(),
id: actionConnection.id,
verified: actionConnection.verified,
},
iconUrl: `${appConfig.baseUrl}/apps/${actionStep.appKey}/assets/favicon.svg`,
id: actionStep.id,
key: 'translateText',
parameters: {},
position: 1,
status: actionStep.status,
type: 'action',
webhookUrl: 'http://localhost:3000/null',
},
],
},
},
};
expect(response.body).toEqual(expectedResponsePayload);
describe('and without isCreator condition', () => {
it('should return executions data of all users', async () => {
await createPermission({
action: 'read',
subject: 'Flow',
roleId: currentUserRole.id,
conditions: [],
});
});
describe('and without isCreator condition', () => {
it('should return executions data of all users', async () => {
await createPermission({
action: 'read',
subject: 'Flow',
roleId: currentUserRole.id,
conditions: [],
});
const anotherUser = await createUser();
const anotherUserFlow = await createFlow({ userId: anotherUser.id });
const anotherUser = await createUser();
const anotherUserFlow = await createFlow({ userId: anotherUser.id });
const triggerStep = await createStep({
flowId: anotherUserFlow.id,
type: 'trigger',
key: 'catchRawWebhook',
webhookPath: `/webhooks/flows/${anotherUserFlow.id}`,
});
const actionConnection = await createConnection({
userId: anotherUser.id,
formattedData: {
screenName: 'Test',
authenticationKey: 'test key',
},
});
const actionStep = await createStep({
flowId: anotherUserFlow.id,
type: 'action',
connectionId: actionConnection.id,
key: 'translateText',
});
const token = createAuthTokenByUserId(currentUser.id);
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query: query(anotherUserFlow.id) })
.expect(200);
const expectedResponsePayload = {
data: {
getFlow: {
active: anotherUserFlow.active,
id: anotherUserFlow.id,
name: anotherUserFlow.name,
status: 'draft',
steps: [
{
appKey: triggerStep.appKey,
connection: null,
iconUrl: `${appConfig.baseUrl}/apps/${triggerStep.appKey}/assets/favicon.svg`,
id: triggerStep.id,
key: 'catchRawWebhook',
parameters: {},
position: 1,
status: triggerStep.status,
type: 'trigger',
webhookUrl: `${appConfig.baseUrl}/webhooks/flows/${anotherUserFlow.id}`,
},
{
appKey: actionStep.appKey,
connection: {
createdAt: actionConnection.createdAt
.getTime()
.toString(),
id: actionConnection.id,
verified: actionConnection.verified,
},
iconUrl: `${appConfig.baseUrl}/apps/${actionStep.appKey}/assets/favicon.svg`,
id: actionStep.id,
key: 'translateText',
parameters: {},
position: 1,
status: actionStep.status,
type: 'action',
webhookUrl: 'http://localhost:3000/null',
},
],
},
},
};
expect(response.body).toEqual(expectedResponsePayload);
const triggerStep = await createStep({
flowId: anotherUserFlow.id,
type: 'trigger',
key: 'catchRawWebhook',
webhookPath: `/webhooks/flows/${anotherUserFlow.id}`,
});
const actionConnection = await createConnection({
userId: anotherUser.id,
formattedData: {
screenName: 'Test',
authenticationKey: 'test key',
},
});
const actionStep = await createStep({
flowId: anotherUserFlow.id,
type: 'action',
connectionId: actionConnection.id,
key: 'translateText',
});
const token = createAuthTokenByUserId(currentUser.id);
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query: query(anotherUserFlow.id) })
.expect(200);
const expectedResponsePayload = {
data: {
getFlow: {
active: anotherUserFlow.active,
id: anotherUserFlow.id,
name: anotherUserFlow.name,
status: 'draft',
steps: [
{
appKey: triggerStep.appKey,
connection: null,
iconUrl: `${appConfig.baseUrl}/apps/${triggerStep.appKey}/assets/favicon.svg`,
id: triggerStep.id,
key: 'catchRawWebhook',
parameters: {},
position: 1,
status: triggerStep.status,
type: 'trigger',
webhookUrl: `${appConfig.baseUrl}/webhooks/flows/${anotherUserFlow.id}`,
},
{
appKey: actionStep.appKey,
connection: {
createdAt: actionConnection.createdAt.getTime().toString(),
id: actionConnection.id,
verified: actionConnection.verified,
},
iconUrl: `${appConfig.baseUrl}/apps/${actionStep.appKey}/assets/favicon.svg`,
id: actionStep.id,
key: 'translateText',
parameters: {},
position: 1,
status: actionStep.status,
type: 'action',
webhookUrl: 'http://localhost:3000/null',
},
],
},
},
};
expect(response.body).toEqual(expectedResponsePayload);
});
});
});

View File

@@ -17,7 +17,6 @@ describe('graphQL getRole query', () => {
userWithoutPermissions,
tokenWithPermissions,
tokenWithoutPermissions,
invalidToken,
permissionOne,
permissionTwo;
@@ -74,108 +73,91 @@ describe('graphQL getRole query', () => {
tokenWithoutPermissions = createAuthTokenByUserId(
userWithoutPermissions.id
);
invalidToken = 'invalid-token';
});
describe('with unauthenticated user', () => {
it('should throw not authorized error', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', invalidToken)
.send({ query: queryWithValidRole })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not Authorised!');
describe('and with valid license', () => {
beforeEach(async () => {
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true);
});
});
describe('with authenticated user', () => {
describe('and with valid license', () => {
beforeEach(async () => {
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true);
describe('and without permissions', () => {
it('should throw not authorized error', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithoutPermissions)
.send({ query: queryWithValidRole })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not authorized!');
});
});
describe('and without permissions', () => {
it('should throw not authorized error', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithoutPermissions)
.send({ query: queryWithValidRole })
.expect(200);
describe('and correct permissions', () => {
it('should return role data for a valid role id', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithPermissions)
.send({ query: queryWithValidRole })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not authorized!');
});
});
describe('and correct permissions', () => {
it('should return role data for a valid role id', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithPermissions)
.send({ query: queryWithValidRole })
.expect(200);
const expectedResponsePayload = {
data: {
getRole: {
description: validRole.description,
id: validRole.id,
isAdmin: validRole.key === 'admin',
key: validRole.key,
name: validRole.name,
permissions: [
{
action: permissionOne.action,
conditions: permissionOne.conditions,
id: permissionOne.id,
subject: permissionOne.subject,
},
{
action: permissionTwo.action,
conditions: permissionTwo.conditions,
id: permissionTwo.id,
subject: permissionTwo.subject,
},
],
},
const expectedResponsePayload = {
data: {
getRole: {
description: validRole.description,
id: validRole.id,
isAdmin: validRole.key === 'admin',
key: validRole.key,
name: validRole.name,
permissions: [
{
action: permissionOne.action,
conditions: permissionOne.conditions,
id: permissionOne.id,
subject: permissionOne.subject,
},
{
action: permissionTwo.action,
conditions: permissionTwo.conditions,
id: permissionTwo.id,
subject: permissionTwo.subject,
},
],
},
};
},
};
expect(response.body).toEqual(expectedResponsePayload);
});
expect(response.body).toEqual(expectedResponsePayload);
});
it('should return not found for invalid role id', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithPermissions)
.send({ query: queryWithInvalidRole })
.expect(200);
it('should return not found for invalid role id', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithPermissions)
.send({ query: queryWithInvalidRole })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('NotFoundError');
});
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('NotFoundError');
});
});
});
describe('and without valid license', () => {
beforeEach(async () => {
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(false);
});
describe('and without valid license', () => {
beforeEach(async () => {
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(false);
});
describe('and correct permissions', () => {
it('should throw not authorized error', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithPermissions)
.send({ query: queryWithInvalidRole })
.expect(200);
describe('and correct permissions', () => {
it('should throw not authorized error', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithPermissions)
.send({ query: queryWithInvalidRole })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not authorized!');
});
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not authorized!');
});
});
});

View File

@@ -15,8 +15,7 @@ describe('graphQL getRoles query', () => {
userWithPermissions,
userWithoutPermissions,
tokenWithPermissions,
tokenWithoutPermissions,
invalidToken;
tokenWithoutPermissions;
beforeEach(async () => {
currentUserRole = await createRole({ name: 'Current user role' });
@@ -53,99 +52,82 @@ describe('graphQL getRoles query', () => {
tokenWithoutPermissions = createAuthTokenByUserId(
userWithoutPermissions.id
);
invalidToken = 'invalid-token';
});
describe('with unauthenticated user', () => {
it('should throw not authorized error', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', invalidToken)
.send({ query })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not Authorised!');
describe('and with valid license', () => {
beforeEach(async () => {
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true);
});
});
describe('with authenticated user', () => {
describe('and with valid license', () => {
beforeEach(async () => {
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true);
});
describe('and without permissions', () => {
it('should throw not authorized error', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithoutPermissions)
.send({ query })
.expect(200);
describe('and without permissions', () => {
it('should throw not authorized error', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithoutPermissions)
.send({ query })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not authorized!');
});
});
describe('and correct permissions', () => {
it('should return roles data', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithPermissions)
.send({ query })
.expect(200);
const expectedResponsePayload = {
data: {
getRoles: [
{
description: currentUserRole.description,
id: currentUserRole.id,
isAdmin: currentUserRole.key === 'admin',
key: currentUserRole.key,
name: currentUserRole.name,
},
{
description: roleOne.description,
id: roleOne.id,
isAdmin: roleOne.key === 'admin',
key: roleOne.key,
name: roleOne.name,
},
{
description: roleSecond.description,
id: roleSecond.id,
isAdmin: roleSecond.key === 'admin',
key: roleSecond.key,
name: roleSecond.name,
},
],
},
};
expect(response.body).toEqual(expectedResponsePayload);
});
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not authorized!');
});
});
describe('and without valid license', () => {
beforeEach(async () => {
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(false);
describe('and correct permissions', () => {
it('should return roles data', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithPermissions)
.send({ query })
.expect(200);
const expectedResponsePayload = {
data: {
getRoles: [
{
description: currentUserRole.description,
id: currentUserRole.id,
isAdmin: currentUserRole.key === 'admin',
key: currentUserRole.key,
name: currentUserRole.name,
},
{
description: roleOne.description,
id: roleOne.id,
isAdmin: roleOne.key === 'admin',
key: roleOne.key,
name: roleOne.name,
},
{
description: roleSecond.description,
id: roleSecond.id,
isAdmin: roleSecond.key === 'admin',
key: roleSecond.key,
name: roleSecond.name,
},
],
},
};
expect(response.body).toEqual(expectedResponsePayload);
});
});
});
describe('and correct permissions', () => {
it('should throw not authorized error', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithPermissions)
.send({ query })
.expect(200);
describe('and without valid license', () => {
beforeEach(async () => {
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(false);
});
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not authorized!');
});
describe('and correct permissions', () => {
it('should throw not authorized error', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', tokenWithPermissions)
.send({ query })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not authorized!');
});
});
});

View File

@@ -16,34 +16,46 @@ describe('graphQL getTrialStatus query', () => {
}
`;
const invalidToken = 'invalid-token';
let user, userToken;
describe('with unauthenticated user', () => {
it('should throw not authorized error', async () => {
beforeEach(async () => {
const trialExpiryDate = DateTime.now().plus({ days: 30 }).toISODate();
user = await createUser({ trialExpiryDate });
userToken = createAuthTokenByUserId(user.id);
});
describe('and with cloud flag disabled', () => {
beforeEach(async () => {
vi.spyOn(appConfig, 'isCloud', 'get').mockReturnValue(false);
});
it('should return null', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', invalidToken)
.set('Authorization', userToken)
.send({ query })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not Authorised!');
const expectedResponsePayload = {
data: { getTrialStatus: null },
};
expect(response.body).toEqual(expectedResponsePayload);
});
});
describe('with authenticated user', () => {
let user, userToken;
describe('and with cloud flag enabled', () => {
beforeEach(async () => {
const trialExpiryDate = DateTime.now().plus({ days: 30 }).toISODate();
user = await createUser({ trialExpiryDate });
userToken = createAuthTokenByUserId(user.id);
vi.spyOn(appConfig, 'isCloud', 'get').mockReturnValue(true);
});
describe('and with cloud flag disabled', () => {
describe('and not in trial and has active subscription', () => {
beforeEach(async () => {
vi.spyOn(appConfig, 'isCloud', 'get').mockReturnValue(false);
vi.spyOn(User.prototype, 'inTrial').mockResolvedValue(false);
vi.spyOn(User.prototype, 'hasActiveSubscription').mockResolvedValue(
true
);
});
it('should return null', async () => {
@@ -61,56 +73,27 @@ describe('graphQL getTrialStatus query', () => {
});
});
describe('and with cloud flag enabled', () => {
describe('and in trial period', () => {
beforeEach(async () => {
vi.spyOn(appConfig, 'isCloud', 'get').mockReturnValue(true);
vi.spyOn(User.prototype, 'inTrial').mockResolvedValue(true);
});
describe('and not in trial and has active subscription', () => {
beforeEach(async () => {
vi.spyOn(User.prototype, 'inTrial').mockResolvedValue(false);
vi.spyOn(User.prototype, 'hasActiveSubscription').mockResolvedValue(
true
);
});
it('should return null', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', userToken)
.send({ query })
.expect(200);
it('should return null', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', userToken)
.send({ query })
.expect(200);
const expectedResponsePayload = {
data: { getTrialStatus: null },
};
expect(response.body).toEqual(expectedResponsePayload);
});
});
describe('and in trial period', () => {
beforeEach(async () => {
vi.spyOn(User.prototype, 'inTrial').mockResolvedValue(true);
});
it('should return null', async () => {
const response = await request(app)
.post('/graphql')
.set('Authorization', userToken)
.send({ query })
.expect(200);
const expectedResponsePayload = {
data: {
getTrialStatus: {
expireAt: new Date(user.trialExpiryDate).getTime().toString(),
},
const expectedResponsePayload = {
data: {
getTrialStatus: {
expireAt: new Date(user.trialExpiryDate).getTime().toString(),
},
};
},
};
expect(response.body).toEqual(expectedResponsePayload);
});
expect(response.body).toEqual(expectedResponsePayload);
});
});
});

View File

@@ -8,37 +8,12 @@ import { createPermission } from '../../../test/factories/permission';
import { createUser } from '../../../test/factories/user';
describe('graphQL getUser query', () => {
describe('with unauthenticated user', () => {
describe('and without permissions', () => {
it('should throw not authorized error', async () => {
const invalidUserId = '123123123';
const userWithoutPermissions = await createUser();
const anotherUser = await createUser();
const query = `
query {
getUser(id: "${invalidUserId}") {
id
email
}
}
`;
const response = await request(app)
.post('/graphql')
.set('Authorization', 'invalid-token')
.send({ query })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not Authorised!');
});
});
describe('with authenticated user', () => {
describe('and without permissions', () => {
it('should throw not authorized error', async () => {
const userWithoutPermissions = await createUser();
const anotherUser = await createUser();
const query = `
query {
getUser(id: "${anotherUser.id}") {
id
@@ -47,50 +22,48 @@ describe('graphQL getUser query', () => {
}
`;
const token = createAuthTokenByUserId(userWithoutPermissions.id);
const token = createAuthTokenByUserId(userWithoutPermissions.id);
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query })
.expect(200);
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not authorized!');
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not authorized!');
});
});
describe('and correct permissions', () => {
let role, currentUser, anotherUser, token, requestObject;
beforeEach(async () => {
role = await createRole({
key: 'sample',
name: 'sample',
});
await createPermission({
action: 'read',
subject: 'User',
roleId: role.id,
});
currentUser = await createUser({
roleId: role.id,
});
anotherUser = await createUser({
roleId: role.id,
});
token = createAuthTokenByUserId(currentUser.id);
requestObject = request(app).post('/graphql').set('Authorization', token);
});
describe('and correct permissions', () => {
let role, currentUser, anotherUser, token, requestObject;
beforeEach(async () => {
role = await createRole({
key: 'sample',
name: 'sample',
});
await createPermission({
action: 'read',
subject: 'User',
roleId: role.id,
});
currentUser = await createUser({
roleId: role.id,
});
anotherUser = await createUser({
roleId: role.id,
});
token = createAuthTokenByUserId(currentUser.id);
requestObject = request(app)
.post('/graphql')
.set('Authorization', token);
});
it('should return user data for a valid user id', async () => {
const query = `
it('should return user data for a valid user id', async () => {
const query = `
query {
getUser(id: "${anotherUser.id}") {
id
@@ -107,26 +80,26 @@ describe('graphQL getUser query', () => {
}
`;
const response = await requestObject.send({ query }).expect(200);
const response = await requestObject.send({ query }).expect(200);
const expectedResponsePayload = {
data: {
getUser: {
createdAt: anotherUser.createdAt.getTime().toString(),
email: anotherUser.email,
fullName: anotherUser.fullName,
id: anotherUser.id,
role: { id: role.id, name: role.name },
updatedAt: anotherUser.updatedAt.getTime().toString(),
},
const expectedResponsePayload = {
data: {
getUser: {
createdAt: anotherUser.createdAt.getTime().toString(),
email: anotherUser.email,
fullName: anotherUser.fullName,
id: anotherUser.id,
role: { id: role.id, name: role.name },
updatedAt: anotherUser.updatedAt.getTime().toString(),
},
};
},
};
expect(response.body).toEqual(expectedResponsePayload);
});
expect(response.body).toEqual(expectedResponsePayload);
});
it('should not return user password for a valid user id', async () => {
const query = `
it('should not return user password for a valid user id', async () => {
const query = `
query {
getUser(id: "${anotherUser.id}") {
id
@@ -136,18 +109,18 @@ describe('graphQL getUser query', () => {
}
`;
const response = await requestObject.send({ query }).expect(400);
const response = await requestObject.send({ query }).expect(400);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual(
'Cannot query field "password" on type "User".'
);
});
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual(
'Cannot query field "password" on type "User".'
);
});
it('should return not found for invalid user id', async () => {
const invalidUserId = Crypto.randomUUID();
it('should return not found for invalid user id', async () => {
const invalidUserId = Crypto.randomUUID();
const query = `
const query = `
query {
getUser(id: "${invalidUserId}") {
id
@@ -164,11 +137,10 @@ describe('graphQL getUser query', () => {
}
`;
const response = await requestObject.send({ query }).expect(200);
const response = await requestObject.send({ query }).expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('NotFoundError');
});
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('NotFoundError');
});
});
});

View File

@@ -30,111 +30,95 @@ describe('graphQL getUsers query', () => {
}
`;
describe('with unauthenticated user', () => {
describe('and without permissions', () => {
it('should throw not authorized error', async () => {
const userWithoutPermissions = await createUser();
const token = createAuthTokenByUserId(userWithoutPermissions.id);
const response = await request(app)
.post('/graphql')
.set('Authorization', 'invalid-token')
.set('Authorization', token)
.send({ query })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not Authorised!');
expect(response.body.errors[0].message).toEqual('Not authorized!');
});
});
describe('with authenticated user', () => {
describe('and without permissions', () => {
it('should throw not authorized error', async () => {
const userWithoutPermissions = await createUser();
const token = createAuthTokenByUserId(userWithoutPermissions.id);
describe('and with correct permissions', () => {
let role, currentUser, anotherUser, token, requestObject;
const response = await request(app)
.post('/graphql')
.set('Authorization', token)
.send({ query })
.expect(200);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual('Not authorized!');
beforeEach(async () => {
role = await createRole({
key: 'sample',
name: 'sample',
});
await createPermission({
action: 'read',
subject: 'User',
roleId: role.id,
});
currentUser = await createUser({
roleId: role.id,
fullName: 'Current User',
});
anotherUser = await createUser({
roleId: role.id,
fullName: 'Another User',
});
token = createAuthTokenByUserId(currentUser.id);
requestObject = request(app).post('/graphql').set('Authorization', token);
});
describe('and with correct permissions', () => {
let role, currentUser, anotherUser, token, requestObject;
it('should return users data', async () => {
const response = await requestObject.send({ query }).expect(200);
beforeEach(async () => {
role = await createRole({
key: 'sample',
name: 'sample',
});
await createPermission({
action: 'read',
subject: 'User',
roleId: role.id,
});
currentUser = await createUser({
roleId: role.id,
fullName: 'Current User',
});
anotherUser = await createUser({
roleId: role.id,
fullName: 'Another User',
});
token = createAuthTokenByUserId(currentUser.id);
requestObject = request(app)
.post('/graphql')
.set('Authorization', token);
});
it('should return users data', async () => {
const response = await requestObject.send({ query }).expect(200);
const expectedResponsePayload = {
data: {
getUsers: {
edges: [
{
node: {
email: anotherUser.email,
fullName: anotherUser.fullName,
id: anotherUser.id,
role: {
id: role.id,
name: role.name,
},
const expectedResponsePayload = {
data: {
getUsers: {
edges: [
{
node: {
email: anotherUser.email,
fullName: anotherUser.fullName,
id: anotherUser.id,
role: {
id: role.id,
name: role.name,
},
},
{
node: {
email: currentUser.email,
fullName: currentUser.fullName,
id: currentUser.id,
role: {
id: role.id,
name: role.name,
},
},
},
],
pageInfo: {
currentPage: 1,
totalPages: 1,
},
totalCount: 2,
{
node: {
email: currentUser.email,
fullName: currentUser.fullName,
id: currentUser.id,
role: {
id: role.id,
name: role.name,
},
},
},
],
pageInfo: {
currentPage: 1,
totalPages: 1,
},
totalCount: 2,
},
};
},
};
expect(response.body).toEqual(expectedResponsePayload);
});
expect(response.body).toEqual(expectedResponsePayload);
});
it('should not return users data with password', async () => {
const query = `
it('should not return users data with password', async () => {
const query = `
query {
getUsers(limit: 10, offset: 0) {
pageInfo {
@@ -153,13 +137,12 @@ describe('graphQL getUsers query', () => {
}
`;
const response = await requestObject.send({ query }).expect(400);
const response = await requestObject.send({ query }).expect(400);
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual(
'Cannot query field "password" on type "User".'
);
});
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toEqual(
'Cannot query field "password" on type "User".'
);
});
});
});

View File

@@ -3,7 +3,7 @@ import jwt from 'jsonwebtoken';
import appConfig from '../config/app.js';
import User from '../models/user.js';
const isAuthenticated = rule()(async (_parent, _args, req) => {
export const isAuthenticated = async (_parent, _args, req) => {
const token = req.headers['authorization'];
if (token == null) return false;
@@ -26,29 +26,32 @@ const isAuthenticated = rule()(async (_parent, _args, req) => {
} catch (error) {
return false;
}
});
};
const authentication = shield(
{
Query: {
'*': isAuthenticated,
getAutomatischInfo: allow,
getConfig: allow,
getNotifications: allow,
healthcheck: allow,
listSamlAuthProviders: allow,
},
Mutation: {
'*': isAuthenticated,
forgotPassword: allow,
login: allow,
registerUser: allow,
resetPassword: allow,
},
const isAuthenticatedRule = rule()(isAuthenticated);
export const authenticationRules = {
Query: {
'*': isAuthenticatedRule,
getAutomatischInfo: allow,
getConfig: allow,
getNotifications: allow,
healthcheck: allow,
listSamlAuthProviders: allow,
},
{
allowExternalErrors: true,
}
);
Mutation: {
'*': isAuthenticatedRule,
forgotPassword: allow,
login: allow,
registerUser: allow,
resetPassword: allow,
},
};
const authenticationOptions = {
allowExternalErrors: true,
};
const authentication = shield(authenticationRules, authenticationOptions);
export default authentication;

View File

@@ -0,0 +1,78 @@
import { describe, it, expect, vi } from 'vitest';
import { allow } from 'graphql-shield';
import jwt from 'jsonwebtoken';
import User from '../models/user.js';
import { isAuthenticated, authenticationRules } from './authentication.js';
vi.mock('jsonwebtoken');
vi.mock('../models/user.js');
describe('isAuthenticated', () => {
it('should return false if no token is provided', async () => {
const req = { headers: {} };
expect(await isAuthenticated(null, null, req)).toBe(false);
});
it('should return false if token is invalid', async () => {
jwt.verify.mockImplementation(() => {
throw new Error('invalid token');
});
const req = { headers: { authorization: 'invalidToken' } };
expect(await isAuthenticated(null, null, req)).toBe(false);
});
it('should return true if token is valid', async () => {
jwt.verify.mockReturnValue({ userId: '123' });
User.query.mockReturnValue({
findById: vi.fn().mockReturnValue({
leftJoinRelated: vi.fn().mockReturnThis(),
withGraphFetched: vi
.fn()
.mockResolvedValue({ id: '123', role: {}, permissions: {} }),
}),
});
const req = { headers: { authorization: 'validToken' } };
expect(await isAuthenticated(null, null, req)).toBe(true);
});
});
describe('authentication rules', () => {
const getQueryAndMutationNames = (rules) => {
const queries = Object.keys(rules.Query || {});
const mutations = Object.keys(rules.Mutation || {});
return { queries, mutations };
};
const { queries, mutations } = getQueryAndMutationNames(authenticationRules);
describe('for queries', () => {
queries.forEach((query) => {
it(`should apply correct rule for query: ${query}`, () => {
const ruleApplied = authenticationRules.Query[query];
if (query === '*') {
expect(ruleApplied.func).toBe(isAuthenticated);
} else {
expect(ruleApplied).toEqual(allow);
}
});
});
});
describe('for mutations', () => {
mutations.forEach((mutation) => {
it(`should apply correct rule for mutation: ${mutation}`, () => {
const ruleApplied = authenticationRules.Mutation[mutation];
if (mutation === '*') {
expect(ruleApplied.func).toBe(isAuthenticated);
} else {
expect(ruleApplied).toBe(allow);
}
});
});
});
});