Fix workspace hydratation (#12452)
We must separate the concept of hydratation which happens at the request level (take the token and pass auth/user context), from the concept of authorization which happens at the query/endpoint/mutation level. Previously, hydratation exemption happened at the operation name level which is not correct because the operation name is meaningless and optional. Still this gave an impression of security by enforcing a blacklist. So in this PR we introduce linting rule that aim to achieve a similar behavior, now every api method has to have a guard. That way if and endpoint is not protected by AuthUserGuard or AuthWorspaceGuard, then it has to be stated explicitly next to its code. --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { ExecutionContext } from '@nestjs/common';
|
||||
import { GqlExecutionContext } from '@nestjs/graphql';
|
||||
|
||||
import { ImpersonateGuard } from 'src/engine/guards/impersonate-guard';
|
||||
|
||||
describe('ImpersonateGuard', () => {
|
||||
const guard = new ImpersonateGuard();
|
||||
|
||||
it('should return true if user can impersonate', async () => {
|
||||
const mockContext = {
|
||||
getContext: jest.fn(() => ({
|
||||
req: {
|
||||
user: {
|
||||
canImpersonate: true,
|
||||
},
|
||||
},
|
||||
})),
|
||||
};
|
||||
|
||||
jest
|
||||
.spyOn(GqlExecutionContext, 'create')
|
||||
.mockReturnValue(mockContext as any);
|
||||
|
||||
const mockExecutionContext = {} as ExecutionContext;
|
||||
|
||||
const result = await guard.canActivate(mockExecutionContext);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if user cannot impersonate', async () => {
|
||||
const mockContext = {
|
||||
getContext: jest.fn(() => ({
|
||||
req: {
|
||||
user: {
|
||||
canImpersonate: false,
|
||||
},
|
||||
},
|
||||
})),
|
||||
};
|
||||
|
||||
jest
|
||||
.spyOn(GqlExecutionContext, 'create')
|
||||
.mockReturnValue(mockContext as any);
|
||||
|
||||
const mockExecutionContext = {} as ExecutionContext;
|
||||
|
||||
const result = await guard.canActivate(mockExecutionContext);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
import { ExecutionContext } from '@nestjs/common';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { PublicEndpointGuard } from 'src/engine/guards/public-endpoint.guard';
|
||||
|
||||
describe('PublicEndpointGuard', () => {
|
||||
let guard: PublicEndpointGuard;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [PublicEndpointGuard],
|
||||
}).compile();
|
||||
|
||||
guard = module.get<PublicEndpointGuard>(PublicEndpointGuard);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(guard).toBeDefined();
|
||||
});
|
||||
|
||||
it('should always return true for any execution context', () => {
|
||||
const mockContext = {} as ExecutionContext;
|
||||
const result = guard.canActivate(mockContext);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true even with null context', () => {
|
||||
const result = guard.canActivate(null as any);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should be injectable', () => {
|
||||
expect(guard).toBeInstanceOf(PublicEndpointGuard);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user