{"_id":"@555platform/protektor.ts","_rev":"8-6be24e52940e564efd0a3bcb149ac9f6","name":"@555platform/protektor.ts","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@555platform/protektor.ts","version":"1.0.0","keywords":[],"author":"","license":"MIT","_id":"@555platform/protektor.ts@1.0.0","maintainers":[{"name":"colinroberts","email":"colinroberts96@gmail.com"},{"name":"igor-kasriel","email":"Igor_Kasriel@cable.comcast.com"},{"name":"johnmcg5","email":"john_mcguinness2@comcast.com"},{"name":"kdriadon","email":"kevindriadon@outlook.com"},{"name":"robjsliwa","email":"robjsliwa@gmail.com"}],"dist":{"shasum":"a32073cb29755497523d1c98693ec857c096eac7","tarball":"https://registry.npmjs.org/@555platform/protektor.ts/-/protektor.ts-1.0.0.tgz","fileCount":59,"integrity":"sha512-3hPFHQNQSYdEhaf6D5uU/rmq/OTZtNtRsjuD9qOI9tx77yUx53aUZ6mf7PWXh1XJq5L1gNlNl5k3+R3Gq8MkSw==","signatures":[{"sig":"MEUCIEUqfj8+yNG+NBvb5ko4fCtH+2f2fk9C2leqes2vV8RKAiEA8Oi/ZJ+9ONG6mjVWvsBm/N3gq3FWK8SCPSFxcU0bLhc=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":5243893,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJecoopCRA9TVsSAnZWagAAmo8P/iUagvIcaGrrZTM5mbCm\ndmuJvDwvxFmX6LmlxIZQmfts820viu8EFOUmzisrPQr7dbyyF0Al/Sn6AeXm\nsRyUMmzaGlCdZIu2f+Bx/H8OA7PS3RLGjT3M1SRUDvYOQUNQ4W7gPN5P4NzT\nTL+ZiQKXv6jo3OyoXMknZmEZqC9MD92d8oOSn2pyA3n6IAvg9lMey6Y7Ud22\nGHDo0wQwGwbZ5kdaQigB7DOgAmVYW0ajltQsaw7rA+CBqQ0Hil64D8y8EDxU\nbgvu1OIxOJwvX06NuS3FaTPynRMcZ5JlB+gym5NVuhB2g2kCxMpxn7urPVZt\nTBc8eJtiDcoEH5Itxk/JtIoxnPNyjvEbDWFmBBYaAH535BJrMcfvrDia+xPR\nOxTN2rG0VPH3ln3AnuHT5PVDJbK0gCroNyz8DClIwO71KLQn8QzqOWGp8XHP\ncsDL7bfFKRVGCaj8kWe9YJJQeSKwL6nIBKYwyzCluUFKL10PZ9rPupyKoYEI\n8ghWIerVkc02GdJ4DqnNBtcDixTBPMTqt66699dZpkwP1aD+7dGDubzHystx\nTY35ju/lNxZQeEz7h7+gv7suVE3GzxVTpmPn7SCsh2qfFEM7qPWDuunJXjYS\n9hDEO1f0TrMD2onLLB4+DMGNOMD7+rMn75mMAHWjqy4MTZprQkKYp6iQiCfH\nHd5A\r\n=EIt5\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"globals":{"ts-jest":{"tsConfig":{"emitDecoratorMetadata":true,"experimentalDecorators":true}}},"testRegex":"(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$","transform":{".(ts|tsx)":"ts-jest"},"testEnvironment":"node","coverageThreshold":{"global":{"lines":60,"branches":20,"functions":60,"statements":60}},"collectCoverageFrom":["src/**/*.{js,ts}"],"moduleFileExtensions":["ts","tsx","js"],"coveragePathIgnorePatterns":["/node_modules/","/spec/"]},"main":"index.js","gitHead":"e9964416ded5e063a87d0963687ffb0e358c5c50","scripts":{"lint":"tslint --project tsconfig.json -t codeFrame 'src/**/*.ts' 'spec/**/*/ts'","test":"jest --coverage","build":"tsc --module commonjs && typedoc --out docs --target es6 --theme minimal --mode file src","prebuild":"rimraf dist"},"_npmUser":{"name":"robjsliwa","email":"robjsliwa@gmail.com"},"prettier":{"singleQuote":true},"_npmVersion":"6.12.1","description":"[![Build][build-status-image]][build-status-url] [![License][license-image]][license-url]","directories":{},"_nodeVersion":"12.13.1","dependencies":{"ramda":"^0.27.0","react":"^16.13.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^25.1.0","rimraf":"^3.0.2","tslint":"^6.1.0","ts-jest":"^25.2.1","ts-node":"^8.6.2","typedoc":"^0.17.0","prettier":"^1.19.1","supertest":"^4.0.2","superagent":"^5.2.2","typescript":"^3.8.3","@types/jest":"^25.1.4","@types/node":"^13.9.1","@types/ramda":"^0.26.44","@types/react":"^16.9.23","concurrently":"^5.1.0","@types/supertest":"^2.0.8","@types/superagent":"^4.1.7","tslint-config-prettier":"^1.18.0","tslint-config-standard":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/protektor.ts_1.0.0_1584564777243_0.28253577584609046","host":"s3://npm-registry-packages"}}},"time":{"created":"2020-03-18T20:52:57.079Z","modified":"2024-09-16T22:08:01.328Z","1.0.0":"2020-03-18T20:52:57.446Z"},"license":"MIT","keywords":[],"description":"[![Build][build-status-image]][build-status-url] [![License][license-image]][license-url]","maintainers":[{"email":"nijagunamurthy_chandrashekarappa@comcast.com","name":"nijacomcast"},{"email":"nijagunared@gmail.com","name":"nija"}],"readme":"[![Build][build-status-image]][build-status-url] [![License][license-image]][license-url]\n\n# Protektor\n\nProtektor is an isomorphic role based permission library that protects both UI resources and data models.\n\n# Install\n\nFrom npm\n\n```\nnpm install @555platform/protektor.ts\n```\n\n# Defining Resource Data Model Mappings\n\nThe main feature of Protektor is enforcing permissions for both UI resources as well as related data models, therefore, defining resource data model mapping is the first step to initialize Proteckor. This step also gives Protektor list of all the resources to protect.\n\nTo define resource to data model name call:\n\n```\nimport Protektor from 'protektor';\n\nProtektor.resourceModels(resourceName, dataModel)\n```\n\nresourceName is a string identifying any resource you want to protect and typically this is some UI component or view. dataModel is a string or list of strings identifying data models needed to access information for the resource.\n\nTo retrieve data models for the resource call the same function but only with resourceName:\n\n```\nProtektor.resourceModels(resourceName)\n```\n\nThis will return data model(s) associated with the given resource.\n\n# Define Role Identifier\n\nRole identifier is an object that uniquely identifies the role. This object should contain all\nthe relevant information to uniquely identify the role. Simplest example would be Role Identifier\nwith just name:\n\n```\n{\n  name: 'admin'\n}\n```\n\nMore complex Role Identifier could also store information about role groups. For example, maybe you\nneed to have roles for your administrator team and default roles for other teams that are added\nautomatically upon team creation. You could handle this by creating `group` field to differentiate\nbetween two `admin` roles:\n\n```\nadmin role for administrator team:\n\n{\n  name: 'admin',\n  group: 'system_administrators`\n}\n```\n\nAnd for other teams:\n\n```\nUpon creation of each team the default admin role could be assigned:\n\n{\n  name: 'admin',\n  group: 'default_team_roles'\n}\n```\n\nProtektor needs to be able to search for the role identifier but it does not know what fields\nor combination of fields within role identifier makes it unique search criteria. In order\nto provide Protektor with this information you must register predicate that returns unique\nidentity for the role. The predicate is a function with that takes role identifier object\nand returns unique id based on whatever algorithm you choose.\n\nUsing the last example above we could write our predicate to return the slug of name and group\nfields:\n\n```\nfunction roleId(roleIdentifier) {\n  return slug(roleIdentifier.name + ' ' + roleIdentifier.group);\n}\n\nProtektor.registerRoleIdentifierPredicate(roleId)\n```\n\nNote that if you do not register role identifier predicate Protektor will scan role identifier\nobject and concatinate values of object's all top level keys. Depending on your application\nthis may be sufficient for you needs.\n\n# Define Permissions\n\nTo define access permissions within a `role` specify allowed action on the resource:\n\n```\nProtektor.allow({ action, resource, roleIdentifier })\n\nor to disallow action explicitly:\n\nProtektor.forbid({ action, resource, roleIdentifier })\n```\n\nYou can also remove specific permission with:\n\n```\nProtektor.removePermission({ action, resource, roleIdentifier })\n```\n\nIt is possible to call allow and then forbid on the same resource, action, role. The last call will overwrite permissions.\n\n# Remove Role\n\nTo remove entire role use `removeRole` API:\n\n```\nProtektor.removeRole(roleIdentifier)\n```\n\n# Checking Permissions On The Server\n\nProtektor library supports checking permissions for the given role on the server side via `hasPermission` API:\n\n```\nProtektor.hasPermission({ action, resource, roleIdentifier })\n\nReturns true if permitted, otherwise false\n```\n\nOn the server side you can also call `hasModel` API to verify that the given role has access to the data model you are trying to use:\n\n```\nProtektor.hasModel({ modelName, roleIdentifier })\n\nReturns true if the specified model is accessible by the role, otherwise false\n```\n\nSometimes it is useful to get the actual model object if the role permits the access. This can be accomplished with `getModel` API:\n\n```\nProtektor.getModel({ modelName, roleIdentifier, modelTransformCallback })\n```\n\nmodelTransformCallback is a function that is called with modelName as parameter if the access to model is permitted or undefined if not permitted.\n\n# Searching For Roles On The Server\n\nProtektor provides two APIs to search for roles. One to find a specific Role and second one to filter\nout roles based on some criteria.\n\nTo find specific role call `Protektor.roleToJSON(RoleIdentifier)`. This will return role as JSON object\nthat is ready to be marshalled to the client.\n\nTo find roles based on some criteria use `Protektor.filterRoles(filterComparator, roleIdentifier)`.\nThis function will return all roles that match criteria based on the `filterComparator` and value\nprovided in `roleIdentifier` object.\n\nFor example let's assume you have roles defined like this:\n\n```\n[\n  {\n    name: 'role1'\n  },\n  {\n    name: 'role2'\n  },\n  {\n    name: 'role1',\n    group: 'global'\n  },\n  {\n    name: 'role2',\n    group: 'global'\n  }\n]\n```\n\nand you want to just get the roles that belong to global group. You would call `filterRoles` as follows:\n\n```\nconst globalRoles = await Protektor.filterRoles(\n  roleIdentifier => roleIdentifier.group,\n  {\n    group: 'global'\n  }\n);\n```\n\nThis would return only roles with group global:\n\n```\n[\n  {\n    name: 'role1',\n    group: 'global'\n  },\n  {\n    name: 'role2',\n    group: 'global'\n  }\n]\n```\n\n# Marshalling Role To The Client\n\nTo send a role with its permissions to the client call server side API: `Protektor.roleToJSON(roleIdentifier)`.\n\n# Checking Permissions - ReactJS Client\n\nProtektor provides `hasPermission` render prop component that will check permissions for the role. If the role is allowed to access to the resource children components will be rendered.\n\n```\nimport { hasPermission, RoleBuilder } from 'protektor';\n\nconst currentRole = RoleBuilder.fromJSON(roleData);\n\n.\n.\n.\n\n<HasPermission to=\"read\" access=\"Home\" forRole={currentRole}>\n  <SideNavSection\n    to=\"/home\"\n    label=\"Home\"\n  />\n</HasPermission>\n```\n\nHere `RoleBuilder` creates current user role from JSON. You will need to marshal the role from the server to client first.\n\n# RoleBuilder\n\nRoleBuilder object is client side helper for unmarshalling JSON representation of Role that comes\nfrom the server. RoleBuilder returns client side representation of role described by `Role` object.\n\n# Client Role object\n\nClient Role object is representation of the role defined on the server and it is used with all client APIs. It has the following APIs:\n\n```\n* roleIdentifier() - returns RoleIdentifier object as defined by developer\n* hasPermission = ({ action, resource }) - returns true if action is allowed on resource, otherwise false\n```\n\n# Protektor Storage\n\nBy default Protektor uses default memory store. Protektor storage can persist role and permission data to anywhere you want. `protektor-data-adapter` package provides base adapter class that you can use to extend.\n\n```\nimport Protektor from 'protektor';\nimport { Adapter } from 'protektor-data-adapter';\n\nclass SomeNewAdapter extends Adapter {}\nconst someNewAdapter = new SomeNewAdapter();\n\n.\n.\n.\n\nProtektor.registerAdapter(someNewAdapter);\n```\n\n[build-status-url]: https://drone-server.555.systems/555platform/protektor.ts\n[build-status-image]: https://drone-server.555.systems/api/badges/555platform/protektor.ts/status.svg\n[license-url]: http://opensource.org/licenses/MIT\n[license-image]: https://img.shields.io/badge/License-MIT-blue.svg\n","readmeFilename":"README.md"}