Last active
December 9, 2022 21:48
-
-
Save mrpotatoes/b588eca7a26b2d81338ac5a3e3faccc5 to your computer and use it in GitHub Desktop.
functional-help.js
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
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) | |
} | |
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
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