-
Notifications
You must be signed in to change notification settings - Fork 7.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(editor): Add routing middleware, permission checks, RBAC store, RBAC component #7702
Merged
Merged
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
ea4123a
feat: add routing middleware, rbac store, rbac component
alexgrozav 25bb007
test: add unit tests for rbac functionality
alexgrozav 0a334c2
feat: replace existing isAuthorized permissions check
alexgrozav f43648b
test: add tests for permission checks
alexgrozav 21501ef
chore: merge master
alexgrozav e8b6123
fix: fix /users route permission
alexgrozav 659d93d
feat: code improvements and test coverage increase
alexgrozav ebb6645
chore: add intermediary const
alexgrozav 449a219
fix: fix tag scope name
alexgrozav 2be9594
fix: remove .only
alexgrozav 14bc6f2
Merge remote-tracking branch 'origin/master' into pay-1005-front-end-…
cstuncsik 4229f24
Merge remote-tracking branch 'origin/master' into pay-1005-front-end-…
cstuncsik e77a9bd
Merge remote-tracking branch 'origin/master' into pay-1005-front-end-…
cstuncsik 2e918c6
fix: Update permission package
cstuncsik b57306e
fix: Add RBAC store to permissions
cstuncsik edb3679
fix: Remove unnecessary permission setting
cstuncsik 04f4c17
fix: Update variables view unit test
cstuncsik 5493903
chore: merge master
alexgrozav 6a6ffef
feat: add init functions
alexgrozav e93c2f2
fix: Update permissions
cstuncsik 0bd74d3
Merge branch 'pay-1005-front-end-permissions-overhaul' of github.com:…
cstuncsik ddeeb25
fix: Remove unused import
cstuncsik fdc3d09
fix: Add back user to variable view test
cstuncsik 34eb0d2
fix: Roll back variable view changes
cstuncsik 6d7c77e
fix: Update permissions
cstuncsik d403b14
fix: Permission object is not optional in test function
cstuncsik 1eba640
Merge remote-tracking branch 'origin/master' into pay-1005-front-end-…
cstuncsik File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<script lang="ts"> | ||
import type { PropType } from 'vue'; | ||
import { computed, defineComponent } from 'vue'; | ||
import { useRBACStore } from '@/stores/rbac.store'; | ||
import type { HasScopeMode, Scope, Resource } from '@n8n/permissions'; | ||
import { | ||
inferProjectIdFromRoute, | ||
inferResourceIdFromRoute, | ||
inferResourceTypeFromRoute, | ||
} from '@/utils/rbacUtils'; | ||
import { useRoute } from 'vue-router'; | ||
|
||
export default defineComponent({ | ||
props: { | ||
scope: { | ||
type: [String, Array] as PropType<Scope | Scope[]>, | ||
required: true, | ||
}, | ||
mode: { | ||
type: String as PropType<HasScopeMode>, | ||
default: 'allOf', | ||
}, | ||
resourceType: { | ||
type: String as PropType<Resource>, | ||
default: undefined, | ||
}, | ||
resourceId: { | ||
type: String, | ||
default: undefined, | ||
}, | ||
projectId: { | ||
type: String, | ||
default: undefined, | ||
}, | ||
}, | ||
setup(props, { slots }) { | ||
const rbacStore = useRBACStore(); | ||
const route = useRoute(); | ||
|
||
const hasScope = computed(() => { | ||
const projectId = props.projectId ?? inferProjectIdFromRoute(route); | ||
const resourceType = props.resourceType ?? inferResourceTypeFromRoute(route); | ||
const resourceId = resourceType | ||
? props.resourceId ?? inferResourceIdFromRoute(route) | ||
: undefined; | ||
|
||
return rbacStore.hasScope( | ||
props.scope, | ||
{ | ||
projectId, | ||
resourceType, | ||
resourceId, | ||
}, | ||
{ mode: props.mode }, | ||
); | ||
}); | ||
|
||
return () => (hasScope.value ? slots.default?.() : slots.fallback?.()); | ||
}, | ||
}); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { useUsersStore } from '@/stores'; | ||
import type { RouterMiddleware } from '@/types/router'; | ||
import { VIEWS } from '@/constants'; | ||
|
||
export type AuthenticatedMiddlewareOptions = {}; | ||
|
||
export const authenticated: RouterMiddleware<AuthenticatedMiddlewareOptions> = async ( | ||
to, | ||
from, | ||
next, | ||
) => { | ||
const usersStore = useUsersStore(); | ||
const redirect = | ||
to.query.redirect ?? encodeURIComponent(`${window.location.pathname}${window.location.search}`); | ||
|
||
if (!usersStore.currentUser) { | ||
return next({ name: VIEWS.SIGNIN, query: { redirect } }); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import type { RouterMiddleware } from '@/types/router'; | ||
import { useSettingsStore } from '@/stores'; | ||
import type { EnterpriseEditionFeature } from '@/constants'; | ||
import { VIEWS } from '@/constants'; | ||
|
||
export type EnterpriseMiddlewareOptions = { | ||
features: EnterpriseEditionFeature[]; | ||
mode?: 'oneOf' | 'allOf'; | ||
}; | ||
|
||
export const enterprise: RouterMiddleware<EnterpriseMiddlewareOptions> = async ( | ||
to, | ||
from, | ||
next, | ||
options, | ||
) => { | ||
const settingsStore = useSettingsStore(); | ||
const mode = options.mode ?? 'allOf'; | ||
|
||
let valid: boolean; | ||
if (mode === 'allOf') { | ||
valid = options.features.every((feature) => settingsStore.isEnterpriseFeatureEnabled(feature)); | ||
} else { | ||
valid = options.features.some((feature) => settingsStore.isEnterpriseFeatureEnabled(feature)); | ||
} | ||
|
||
if (!valid) { | ||
return next({ name: VIEWS.HOMEPAGE }); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { useUsersStore } from '@/stores'; | ||
import type { RouterMiddleware } from '@/types/router'; | ||
import { VIEWS } from '@/constants'; | ||
|
||
export type GuestMiddlewareOptions = {}; | ||
|
||
export const guest: RouterMiddleware<GuestMiddlewareOptions> = async (to, from, next) => { | ||
const usersStore = useUsersStore(); | ||
const redirect = to.query.redirect as string; | ||
|
||
if (usersStore.currentUser) { | ||
if (redirect && redirect.startsWith('/')) { | ||
next(redirect); | ||
} | ||
|
||
return next({ name: VIEWS.HOMEPAGE }); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import type { RouterMiddlewareType, RouterMiddleware } from '@/types/router'; | ||
import { authenticated } from './authenticated'; | ||
import { enterprise } from './enterprise'; | ||
import { guest } from './guest'; | ||
import { rbac } from './rbac'; | ||
|
||
export const middleware: Record<RouterMiddlewareType, RouterMiddleware> = { | ||
authenticated, | ||
enterprise, | ||
guest, | ||
rbac, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import type { RouterMiddleware } from '@/types/router'; | ||
import { VIEWS } from '@/constants'; | ||
import type { HasScopeOptions, Scope } from '@n8n/permissions'; | ||
import { useRBACStore } from '@/stores/rbac.store'; | ||
import { | ||
inferProjectIdFromRoute, | ||
inferResourceIdFromRoute, | ||
inferResourceTypeFromRoute, | ||
} from '@/utils/rbacUtils'; | ||
|
||
export type RBACMiddlewareOptions = { | ||
scope: Scope | Scope[]; | ||
options?: HasScopeOptions; | ||
}; | ||
|
||
export const rbac: RouterMiddleware<RBACMiddlewareOptions> = async ( | ||
to, | ||
from, | ||
next, | ||
{ scope, options }, | ||
) => { | ||
const rbacStore = useRBACStore(); | ||
|
||
const projectId = inferProjectIdFromRoute(to); | ||
const resourceType = inferResourceTypeFromRoute(to); | ||
const resourceId = resourceType ? inferResourceIdFromRoute(to) : undefined; | ||
|
||
const valid = rbacStore.hasScope( | ||
scope, | ||
{ | ||
projectId, | ||
resourceType, | ||
resourceId, | ||
}, | ||
options, | ||
); | ||
|
||
if (!valid) { | ||
return next({ name: VIEWS.HOMEPAGE }); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a nitpick (coming from my functional programming self :))
it could be pointfree (same below)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!