feat: Replace owner checks with scope checks (no-changelog) (#7846)

Github issue / Community forum post (link here to close automatically):
This commit is contained in:
Val
2023-11-29 14:48:36 +00:00
committed by GitHub
parent d5762a7539
commit 1cb92ffe16
26 changed files with 136 additions and 78 deletions

View File

@@ -97,7 +97,6 @@ describe('POST /login', () => {
const ownerUser = await createUser({
password: randomValidPassword(),
globalRole: globalOwnerRole,
isOwner: true,
});
const response = await testServer.authAgentFor(ownerUser).get('/login');

View File

@@ -16,7 +16,7 @@ import { getGlobalAdminRole, getGlobalMemberRole, getGlobalOwnerRole } from './r
*/
export async function createUser(attributes: Partial<User> = {}): Promise<User> {
const { email, password, firstName, lastName, globalRole, ...rest } = attributes;
const user: Partial<User> = {
const user = Container.get(UserRepository).create({
email: email ?? randomEmail(),
password: await hash(password ?? randomValidPassword(), 10),
firstName: firstName ?? randomName(),
@@ -24,7 +24,8 @@ export async function createUser(attributes: Partial<User> = {}): Promise<User>
globalRoleId: (globalRole ?? (await getGlobalMemberRole())).id,
globalRole,
...rest,
};
});
user.computeIsOwner();
return Container.get(UserRepository).save(user);
}

View File

@@ -362,7 +362,6 @@ describe('PATCH /users/:id/role', () => {
let authlessAgent: SuperAgentTest;
const {
NO_MEMBER,
MISSING_NEW_ROLE_KEY,
MISSING_NEW_ROLE_VALUE,
NO_ADMIN_ON_OWNER,
@@ -372,6 +371,8 @@ describe('PATCH /users/:id/role', () => {
NO_ADMIN_IF_UNLICENSED,
} = UsersController.ERROR_MESSAGES.CHANGE_ROLE;
const UNAUTHORIZED = 'Unauthorized';
beforeAll(async () => {
await testDb.truncate(['User']);
@@ -406,7 +407,7 @@ describe('PATCH /users/:id/role', () => {
});
expect(response.statusCode).toBe(403);
expect(response.body.message).toBe(NO_MEMBER);
expect(response.body.message).toBe(UNAUTHORIZED);
});
test('should fail to demote owner to admin', async () => {
@@ -415,7 +416,7 @@ describe('PATCH /users/:id/role', () => {
});
expect(response.statusCode).toBe(403);
expect(response.body.message).toBe(NO_MEMBER);
expect(response.body.message).toBe(UNAUTHORIZED);
});
test('should fail to demote admin to member', async () => {
@@ -424,7 +425,7 @@ describe('PATCH /users/:id/role', () => {
});
expect(response.statusCode).toBe(403);
expect(response.body.message).toBe(NO_MEMBER);
expect(response.body.message).toBe(UNAUTHORIZED);
});
test('should fail to promote other member to owner', async () => {
@@ -433,7 +434,7 @@ describe('PATCH /users/:id/role', () => {
});
expect(response.statusCode).toBe(403);
expect(response.body.message).toBe(NO_MEMBER);
expect(response.body.message).toBe(UNAUTHORIZED);
});
test('should fail to promote other member to admin', async () => {
@@ -442,7 +443,7 @@ describe('PATCH /users/:id/role', () => {
});
expect(response.statusCode).toBe(403);
expect(response.body.message).toBe(NO_MEMBER);
expect(response.body.message).toBe(UNAUTHORIZED);
});
test('should fail to promote self to admin', async () => {
@@ -451,7 +452,7 @@ describe('PATCH /users/:id/role', () => {
});
expect(response.statusCode).toBe(403);
expect(response.body.message).toBe(NO_MEMBER);
expect(response.body.message).toBe(UNAUTHORIZED);
});
test('should fail to promote self to owner', async () => {
@@ -460,7 +461,7 @@ describe('PATCH /users/:id/role', () => {
});
expect(response.statusCode).toBe(403);
expect(response.body.message).toBe(NO_MEMBER);
expect(response.body.message).toBe(UNAUTHORIZED);
});
});

View File

@@ -6,6 +6,8 @@ import type { CredentialsEntity } from '@db/entities/CredentialsEntity';
import { SharedCredentials } from '@db/entities/SharedCredentials';
import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository';
import { mockInstance } from '../../shared/mocking';
import { memberPermissions, ownerPermissions } from '@/permissions/roles';
import { hasScope } from '@n8n/permissions';
describe('SharedCredentialsRepository', () => {
const entityManager = mockInstance(EntityManager);
@@ -20,8 +22,23 @@ describe('SharedCredentialsRepository', () => {
const credentialsId = 'cred_123';
const sharedCredential = mock<SharedCredentials>();
sharedCredential.credentials = mock<CredentialsEntity>({ id: credentialsId });
const owner = mock<User>({ isOwner: true });
const member = mock<User>({ isOwner: false, id: 'test' });
const owner = mock<User>({
isOwner: true,
hasGlobalScope: async (scope) => {
return hasScope(scope, {
global: ownerPermissions,
});
},
});
const member = mock<User>({
isOwner: false,
id: 'test',
hasGlobalScope: async (scope) => {
return hasScope(scope, {
global: memberPermissions,
});
},
});
beforeEach(() => {
jest.resetAllMocks();