mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
feat: RBAC (#8922)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> Co-authored-by: Val <68596159+valya@users.noreply.github.com> Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in> Co-authored-by: Valya Bullions <valya@n8n.io> Co-authored-by: Danny Martini <danny@n8n.io> Co-authored-by: Danny Martini <despair.blue@gmail.com> Co-authored-by: Iván Ovejero <ivov.src@gmail.com> Co-authored-by: Omar Ajoue <krynble@gmail.com> Co-authored-by: oleg <me@olegivaniv.com> Co-authored-by: Michael Kret <michael.k@radency.com> Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com> Co-authored-by: Elias Meire <elias@meire.dev> Co-authored-by: Giulio Andreini <andreini@netseven.it> Co-authored-by: Giulio Andreini <g.andreini@gmail.com> Co-authored-by: Ayato Hayashi <go12limchangyong@gmail.com>
This commit is contained in:
@@ -33,6 +33,7 @@ describe('hasScope', () => {
|
||||
{
|
||||
global: memberPermissions,
|
||||
},
|
||||
undefined,
|
||||
{ mode: 'oneOf' },
|
||||
),
|
||||
).toBe(true);
|
||||
@@ -43,6 +44,7 @@ describe('hasScope', () => {
|
||||
{
|
||||
global: memberPermissions,
|
||||
},
|
||||
undefined,
|
||||
{ mode: 'allOf' },
|
||||
),
|
||||
).toBe(true);
|
||||
@@ -53,6 +55,7 @@ describe('hasScope', () => {
|
||||
{
|
||||
global: memberPermissions,
|
||||
},
|
||||
undefined,
|
||||
{ mode: 'oneOf' },
|
||||
),
|
||||
).toBe(false);
|
||||
@@ -63,6 +66,7 @@ describe('hasScope', () => {
|
||||
{
|
||||
global: memberPermissions,
|
||||
},
|
||||
undefined,
|
||||
{ mode: 'allOf' },
|
||||
),
|
||||
).toBe(false);
|
||||
@@ -95,6 +99,7 @@ describe('hasScope', () => {
|
||||
{
|
||||
global: ownerPermissions,
|
||||
},
|
||||
undefined,
|
||||
{ mode: 'allOf' },
|
||||
),
|
||||
).toBe(true);
|
||||
@@ -105,6 +110,7 @@ describe('hasScope', () => {
|
||||
{
|
||||
global: memberPermissions,
|
||||
},
|
||||
undefined,
|
||||
{ mode: 'allOf' },
|
||||
),
|
||||
).toBe(false);
|
||||
@@ -115,6 +121,7 @@ describe('hasScope', () => {
|
||||
{
|
||||
global: memberPermissions,
|
||||
},
|
||||
undefined,
|
||||
{ mode: 'allOf' },
|
||||
),
|
||||
).toBe(false);
|
||||
@@ -125,8 +132,127 @@ describe('hasScope', () => {
|
||||
{
|
||||
global: memberPermissions,
|
||||
},
|
||||
undefined,
|
||||
{ mode: 'allOf' },
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasScope masking', () => {
|
||||
test('should return true without mask when scopes present', () => {
|
||||
expect(
|
||||
hasScope('workflow:read', {
|
||||
global: ['user:list'],
|
||||
project: ['workflow:read'],
|
||||
resource: [],
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false without mask when scopes are not present', () => {
|
||||
expect(
|
||||
hasScope('workflow:update', {
|
||||
global: ['user:list'],
|
||||
project: ['workflow:read'],
|
||||
resource: [],
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test('should return false when mask does not include scope but scopes list does contain required scope', () => {
|
||||
expect(
|
||||
hasScope(
|
||||
'workflow:update',
|
||||
{
|
||||
global: ['user:list'],
|
||||
project: ['workflow:read', 'workflow:update'],
|
||||
resource: [],
|
||||
},
|
||||
{
|
||||
sharing: ['workflow:read'],
|
||||
},
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test('should return true when mask does include scope and scope list includes scope', () => {
|
||||
expect(
|
||||
hasScope(
|
||||
'workflow:update',
|
||||
{
|
||||
global: ['user:list'],
|
||||
project: ['workflow:read', 'workflow:update'],
|
||||
resource: [],
|
||||
},
|
||||
{
|
||||
sharing: ['workflow:read', 'workflow:update'],
|
||||
},
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when mask does include scope and scopes list includes scope on multiple levels', () => {
|
||||
expect(
|
||||
hasScope(
|
||||
'workflow:update',
|
||||
{
|
||||
global: ['user:list'],
|
||||
project: ['workflow:read', 'workflow:update'],
|
||||
resource: ['workflow:update'],
|
||||
},
|
||||
{
|
||||
sharing: ['workflow:read', 'workflow:update'],
|
||||
},
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('should not mask out global scopes', () => {
|
||||
expect(
|
||||
hasScope(
|
||||
'workflow:update',
|
||||
{
|
||||
global: ['workflow:read', 'workflow:update'],
|
||||
project: ['workflow:read'],
|
||||
resource: ['workflow:read'],
|
||||
},
|
||||
{
|
||||
sharing: ['workflow:read'],
|
||||
},
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false when scope is not in mask or scope list', () => {
|
||||
expect(
|
||||
hasScope(
|
||||
'workflow:update',
|
||||
{
|
||||
global: ['workflow:read'],
|
||||
project: ['workflow:read'],
|
||||
resource: ['workflow:read'],
|
||||
},
|
||||
{
|
||||
sharing: ['workflow:read'],
|
||||
},
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test('should return false when scope is in mask or not scope list', () => {
|
||||
expect(
|
||||
hasScope(
|
||||
'workflow:update',
|
||||
{
|
||||
global: ['workflow:read'],
|
||||
project: ['workflow:read'],
|
||||
resource: ['workflow:read'],
|
||||
},
|
||||
{
|
||||
sharing: ['workflow:read', 'workflow:update'],
|
||||
},
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user