Skip to content

Instantly share code, notes, and snippets.

@mrpotatoes
Last active December 9, 2022 21:48
Show Gist options
  • Save mrpotatoes/b588eca7a26b2d81338ac5a3e3faccc5 to your computer and use it in GitHub Desktop.
Save mrpotatoes/b588eca7a26b2d81338ac5a3e3faccc5 to your computer and use it in GitHub Desktop.
functional-help.js
console.clear()
const { matchPath } = require('react-router-dom');
const { isNil, trim, flow, identity } = require('lodash');
const patterns = [
{ path: '/' },
{ path: '/new' },
{ path: '/dashboard' },
{ path: '/details/:claimId' },
{ path: '/add-policy/:claimId' },
{ path: '/details/:claimId/documents' },
{ path: '/details/:claimId/claimants' },
{ path: '/details/:claimId/indicators' },
{ path: '/details/:claimId/indicators' },
{ path: '/details/:claimId/case-history' },
{ path: '/details/:claimId/communications' },
{ path: '/edit-policy/:claimId/:policyNumber' },
{ path: '/details/:claimid/claimants/:claimantId' },
];
const urls = [
'/add-policy/',
'/add-policy',
'/add-policy/1',
'/details/3/indicators',
]
const entitlements = {
SOME_ROLE: {
resources: {
'/details/:id/indicators': ['GET', 'POST', 'DEL'],
'/add-policy/:claimId': ['*'],
'/details/:claimId/communications': [],
},
}
}
const patternFinder = (path, pattern) => matchPath(path, {
path: pattern.path,
exact: true,
strict: false
})
const slashedUp = (route) => `/${trim(route, '/')}/`
const normalizedRoute = (route) => slashedUp(route).replace(/(?<=\/)(\:.*?)(?=\/)/gm, '*')
const normalizedResources = (resources) =>
(Object.keys(resources).reduce((previous, current) => ({
...previous,
[normalizedRoute(current)]: resources[current],
}), {}))
/**
* What is the best way, here, to get patterns?
*/
const match = index => (index >= 0) ? resources[normalizedRoute(patterns[index].path)] : []
/**
* What is the best way, here, to get resources?
*/
const AuthZ = flow([
identity,
(path) => patterns.findIndex(pattern => !isNil(patternFinder(path, pattern))),
match,
])
const resources = normalizedResources(entitlements.SOME_ROLE.resources)
for (const url of urls) {
const methods = AuthZ(url, resources)
/**
* Output
* []
* []
* [ '*' ]
* [ 'GET', 'POST', 'DEL' ]
*/
console.log(methods)
}
console.clear()
const { matchPath } = require('react-router-dom');
const { isNil, trim, flow, identity } = require('lodash');
const urls = [
'/details/3/claimants',
'/details/3/communications',
]
const patterns = [
{ path: '/' },
{ path: '/new' },
{ path: '/dashboard' },
{ path: '/details/:claimId' },
{ path: '/add-policy/:claimId' },
{ path: '/details/:claimId/documents' },
{ path: '/details/:claimId/claimants' },
{ path: '/details/:claimId/indicators' },
{ path: '/details/:claimId/indicators' },
{ path: '/details/:claimId/case-history' },
{ path: '/details/:claimId/communications' },
{ path: '/edit-policy/:claimId/:policyNumber' },
{ path: '/details/:claimid/claimants/:claimantId' },
];
const entitlements = {
agent: {
resources: {
'/details/:id/indicators': ['GET', 'POST', 'DEL'],
'/add-policy/:claimId': ['*'], // TODO: This isn't implimented, dunno if it's required yet
'/details/:claimId/communications': ['GET', 'POST', 'DEL'],
'/details/:claimId/claimants': ['POST', 'DEL'],
}
}
}
const patternFinder = (path, pattern) => matchPath(path, {
path: pattern.path,
exact: true,
strict: false
})
// Remove and add the slashes back. To be, you know, safe.
const slashedUp = (route) => `/${trim(route, '/')}/`
// This replaces all :id (whatever the string is) with *
const normalizedRoute = (route) => slashedUp(route).replace(/(?<=\/)(\:.*?)(?=\/)/gm, '*')
// Go through all the resources and normalize them so that we can compare
const normalizedResources = (resources) =>
(Object.keys(resources).reduce((previous, current) => ({
...previous,
[normalizedRoute(current)]: resources[current],
}), {}))
// Find a match against the global resources object.
const isMatched = (resources, patterns) => (index) => (index >= 0) ? resources[normalizedRoute(patterns[index].path)] : []
// Does user have access given the request method? Better with a Maybe.
const hasAccess = (request, methods) =>
(isNil(methods))
? false
: (request === '*') ? true : methods.includes(request)
/**
* Get the methods one is allowed to access for a given route
*/
const AuthZ = flow([
identity,
(path) => patterns.findIndex(pattern => !isNil(patternFinder(path, pattern))),
isMatched(normalizedResources(entitlements.agent.resources), patterns),
])
// -----------------------------------------------------------------------------
// IMPURE
// -----------------------------------------------------------------------------
for (const url of urls) {
const allowed = AuthZ(url)
console.log(JSON.stringify({
url,
matches: allowed,
allowed: hasAccess('GET', allowed),
}, null, 2))
console.log('\n\n--------------------------------------')
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment