Repository: brainhubeu/react-permissible Branch: master Commit: f9122aa4c945 Files: 55 Total size: 79.7 KB Directory structure: gitextract_wgril_c7/ ├── .babelrc ├── .circleci/ │ └── config.yml ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmignore ├── .npmrc ├── LICENSE.md ├── README.md ├── docs/ │ ├── examples/ │ │ ├── callback.md │ │ ├── oneMatch.md │ │ ├── permissionsMatch.md │ │ └── renderOtherwise.md │ ├── getting-started/ │ │ ├── installation.md │ │ └── overview.md │ └── usage/ │ ├── basic.md │ └── hoc.md ├── docs-www/ │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── gatsby-config.js │ ├── gatsby-docs-kit.yml │ ├── package.json │ ├── src/ │ │ ├── globalReferences.js │ │ ├── layouts/ │ │ │ └── .gitkeep │ │ ├── pages/ │ │ │ ├── 404.js │ │ │ ├── landing.js │ │ │ ├── landing.module.scss │ │ │ └── variables.scss │ │ └── templates/ │ │ └── .gitkeep │ └── tools/ │ ├── deploy-github.sh │ ├── seed/ │ │ └── example.md │ └── seed.sh ├── lib/ │ └── react-permissible.js ├── package.json ├── renovate.json ├── src/ │ ├── components/ │ │ ├── permissible.js │ │ └── permissibleRender.js │ └── index.js ├── test/ │ ├── .eslintrc │ ├── accessible.component.js │ ├── permissible.test.js │ └── permissibleRender.test.js ├── tools/ │ ├── build.js │ └── testSetup.js ├── types/ │ ├── .eslintrc │ ├── react-permissible.d.ts │ └── tests/ │ ├── .gitignore │ ├── .npmrc │ ├── Permissible.test.tsx │ ├── PermissibleRender.test.tsx │ ├── package.json │ └── tsconfig.json └── webpack.config.prod.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .babelrc ================================================ { "presets": [ "env", "react", "stage-1" ], "plugins": [ "transform-decorators-legacy" ], "env": { "production": { "plugins": [ "transform-react-constant-elements", "transform-react-remove-prop-types" ] } } } ================================================ FILE: .circleci/config.yml ================================================ version: 2.1 executors: node-executor: docker: - image: circleci/node:14.4.0 working_directory: ~/app jobs: check_branch_name: docker: - image: circleci/node:14.4.0 working_directory: ~/app steps: - run: name: fail if the branch name does not start with a valid prefix command: | branch=$CIRCLE_BRANCH if [[ "$branch" =~ ^(dependabot|fix|feature|breaking)/ || "$branch" == 'master' ]] then echo $branch is a valid name else echo $branch is not valid because the branch name must match '^(dependabot|fix|feature|breaking)/' or be master exit 1 fi build: working_directory: ~/app docker: - image: circleci/node:14.4.0 steps: - checkout - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - run: name: Install npm dependencies command: npm install --production=false - save_cache: key: dependency-cache-{{ checksum "package.json" }} paths: - node_modules test: executor: node-executor steps: - checkout - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - run: name: Install npm dependencies command: npm install --production=false - save_cache: key: dependency-cache-{{ checksum "package.json" }} paths: - node_modules - run: name: Test command: npm run test:coverage:ci - persist_to_workspace: root: ~/app paths: - .git - node_modules - coverage lint: docker: - image: circleci/node:14.4.0 steps: - checkout - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - run: name: Install npm dependencies command: npm install --production=false - save_cache: key: dependency-cache-{{ checksum "package.json" }} paths: - node_modules - run: name: Lint command: npm run lint compile: docker: - image: circleci/node:14.4.0 steps: - checkout - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - run: name: Install npm dependencies command: npm install --production=false - save_cache: key: dependency-cache-{{ checksum "package.json" }} paths: - node_modules - run: name: Compile command: npm run build publish_package: executor: node-executor steps: - attach_workspace: at: ~/app - run: git checkout . - run: name: Generate coveralls config command: "echo repo_token: $REPO_TOKEN > ./.coveralls.yml" - run: name: Upload coverage to coveralls command: cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js - run: name: configure GitHub user command: | git config --global user.email "devops@brainhub.pl" git config --global user.name "DevOps Brainhub" git remote -v git remote remove origin git remote add origin https://$GIT_TOKEN@github.com/brainhubeu/react-permissible git remote -v - run: name: bump NPM version command: | branch=`git log --oneline | grep '[0-9a-f]\{6,40\} Merge pull request #[0-9]\+ from brainhubeu/' | head -1 | sed 's@.* from brainhubeu/@@g' || true` echo branch=$branch if [[ "$branch" =~ ^(dependabot)/ ]]; then npm version patch -m "%s [ci skip]" elif [[ "$branch" =~ ^(fix)/ ]]; then npm version patch -m "%s [ci skip]" elif [[ "$branch" =~ ^(feature)/ ]]; then npm version minor -m "%s [ci skip]" elif [[ "$branch" =~ ^(breaking)/ ]]; then npm version major -m "%s [ci skip]" else echo $branch is not valid because the branch name must match '^(dependabot|fix|feature|breaking)/' exit 1 fi - run: git pull --no-edit origin $CIRCLE_BRANCH - run: git push origin $CIRCLE_BRANCH - run: name: npm publish command: | echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc npm publish workflows: version: 2 build_and_test: jobs: - check_branch_name - build: requires: - check_branch_name - test: requires: - build - lint: requires: - build - compile: requires: - build - publish_package: requires: - test - lint - compile filters: branches: only: - master ================================================ FILE: .editorconfig ================================================ root = true [*] indent_style = space indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.md] trim_trailing_whitespace = false ================================================ FILE: .eslintignore ================================================ /lib/**/*.js ================================================ FILE: .eslintrc ================================================ { "root": true, "extends": [ "brainhub" ], "settings": { "import/resolve": { "moduleDirectory": ["node_modules", "src"] } } } ================================================ FILE: .gitignore ================================================ dist # Logs logs *.log* # Runtime data pids *.pid *.seed # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage reports # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # node-waf configuration .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directory # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git node_modules # IDEA/Webstorm project files .idea *.iml #VSCode metadata .vscode # Mac files .DS_Store # Debug files selenium-debug.log .npm.debug # Merge conflicts *.orig ================================================ FILE: .npmignore ================================================ .babelrc .circleci/ .coveralls.yml .dockerignore .editorconfig .eslintignore .eslintrc .git/ .github/ .gitignore .istanbul.yml .npmignore .npmrc .nvmrc Dockerfile.e2e coverage/ cypress.json docker-compose.e2e.yml docs-www/ docs/ jest.config.js jest.setup.js renovate.json test/ tools/ types/ webpack.config.prod.js ================================================ FILE: .npmrc ================================================ engine-strict=true ================================================ FILE: LICENSE.md ================================================ The MIT License (MIT) Copyright (c) 2017-2020 [Brainhub](https://brainhub.eu/?utm_source=github) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================

react-permissible

Making the permission management for React components easier.

Live code demo | Hire us

[![CircleCI](https://circleci.com/gh/brainhubeu/react-permissible.svg?style=svg)](https://circleci.com/gh/brainhubeu/react-permissible) [![Last commit](https://img.shields.io/github/last-commit/brainhubeu/react-permissible.svg)](https://github.com/brainhubeu/react-permissible/commits/master) [![license](https://img.shields.io/npm/l/@brainhubeu/react-permissible.svg)](https://github.com/brainhubeu/react-permissible/blob/master/LICENSE.md) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) [![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com/) [![Coveralls github](https://img.shields.io/coveralls/github/brainhubeu/react-permissible.svg)](https://coveralls.io/github/brainhubeu/react-permissible?branch=master) [![Downloads](https://img.shields.io/npm/dm/@brainhubeu/react-permissible?color=blue)](https://www.npmjs.com/package/@brainhubeu/react-permissible) [![Minified](https://img.shields.io/bundlephobia/min/@brainhubeu/react-permissible?label=minified)](https://www.npmjs.com/package/@brainhubeu/react-permissible) [![npm](https://img.shields.io/npm/v/@brainhubeu/react-permissible.svg)](https://www.npmjs.com/package/@brainhubeu/react-permissible) [![Contributors](https://img.shields.io/github/contributors/brainhubeu/react-permissible?color=blue)](https://github.com/brainhubeu/react-permissible/graphs/contributors)
`react-permissible` is a React Component allowing to: * manage visibility of particular components depending on users permissions * replace particular component when the user isn't permitted to see it * manage accessability to particular view depending on users permissions * fire a callback when the user isn't allowed to go to access the component/route ## Why? Currently there's no permission management in React. The existing components are either over-engineered (full ACL support etc.), or limited to role-based management. `react-permissible` is simple at its core and solves only one problem. Access the Component if the permissions match, do something otherwise. ## Live demo/ docs You can access live demo/ docs at https://brainhubeu.github.io/react-permissible/. ## Installation ``` npm i @brainhubeu/react-permissible ``` ## Usage ```javascript import { PermissibleRender } from '@brainhubeu/react-permissible'; ... render() { return ( ); } ``` Where: * `userPermissions` is an **array** of permissions set for current user * `requiredPermissions` is an **array** of required permissions More detailed documentation with several use cases covered is available [here](http://brainhubeu.github.io/react-permissible). ## Running tests ``` npm test ``` ## Roadmap * Passing a callback function as a prop for `PermissibleRender` component ## License React-permissible is copyright © 2017-2020 [Brainhub](https://brainhub.eu/?utm_source=github) It is free software, and may be redistributed under the terms specified in the [license](LICENSE.md). ## About `react-permissible` is maintained by [@kkoscielniak](https://github.com/kkoscielniak), [@adam-golab](https://github.com/adam-golab), [@Lukasz-pluszczewski](https://github.com/Lukasz-pluszczewski/) and the Brainhub development team. It is funded by Brainhub and the names and logos for Brainhub are trademarks of Brainhub Sp. z o.o.. You can check other open-source projects supported/developed by our teammates [here](https://brainhub.eu/?utm_source=github). [![Brainhub](https://brainhub.eu/brainhub.svg)](https://brainhub.eu/?utm_source=github) We love open-source JavaScript software! See our other projects or hire us to build your next web, desktop and mobile application with JavaScript. ================================================ FILE: docs/examples/callback.md ================================================ # Callback function Callback function passed to a `Permissible` Higher Order Component will be called whenever the permissions do not match. This might be combined with the `oneperm` parameter. **Open the Console** to see a callback message. ```javascript import { Permissible } from '@brainhubeu/react-permissible'; const callbackFunction = ({ userPermissions, requiredPermissions }) => { console.log(` react-permissible: Access Denied userPermissions: ${userPermissions} requiredPermissions: ${requiredPermissions} `); }; const CallbackComponent = Permissible( AccessGranted, ['ACCESS_DASHBOARD'], // userPermissions ['ACCESS_ADMIN'], // requiredPermissions callbackFunction, ); ``` ```jsx render ``` ================================================ FILE: docs/examples/oneMatch.md ================================================ # Render a component when one of the permissions matches If at least one permission from the `userPermissions` array exists in the `requiredPermissions` array, the component is rendered. ```jsx render ``` ================================================ FILE: docs/examples/permissionsMatch.md ================================================ # Render a component when all the permissions match If all the permissions in the `userPermissions` array match the `requiredPermissions`, the component is rendered. ```jsx render ``` ================================================ FILE: docs/examples/renderOtherwise.md ================================================ # Render another component if the permissions do not match If permissions in the `userPermissions` do not match the `requiredPermissions`, the component is not rendered, and another one is rendered instead. ```jsx render } > ``` ================================================ FILE: docs/getting-started/installation.md ================================================ # Installation **react-permissible** is designed as an npm package. Installation is as simple as with every package out there: `npm i @brainhubeu/react-permissible` or if you use Yarn: `yarn add @brainhubeu/react-permissible`. ================================================ FILE: docs/getting-started/overview.md ================================================ # react-permissible #### Making the permission management for components easier. **react-permissible** is a React Component allowing you to: * manage visibility of particular components depending on user's permissions. * replacing a particular component when the user isn't permitted to see it. * manage access to particular view depending on user's permissions. * firing a callback when the user isn't allowed to access the component/route. ## Why Currently there's a lack of simple permission management components for React. The existing components are either over-engineered (full ACL support etc.), or limited to role-based management. **react-permissible** is simple at it's core and solves only one problem - accessing the particular component if the necessary permissions are met, hide or render another component otherwise. ================================================ FILE: docs/usage/basic.md ================================================ # Usage You can use react-permissible in two ways: as an ordinary component or as a Higher Order Component. Each approach allows you to solve the permission-based rendering a little bit differently. ## Use as an ordinary component with props: ```javascript import { PermissibleRender } from '@brainhubeu/react-permissible'; ... render() { return ( ); } ``` Where: * `userPermissions`: array of permissions set for current user * `requiredPermissions`: array of required permissions * `RestrictedComponent`: component to render There are also optional props available: * `oneperm`: boolean determining that only one of required permissions will be necessary (boolean) * `renderOtherwise`: another component to be rendered if the permissions do not match (the user isn't permitted). ================================================ FILE: docs/usage/hoc.md ================================================ # Usage You can use react-permissible in two ways: as an ordinary component or as a Higher Order Component. Each approach allows you to solve the permission-based rendering a little bit differently. ## Usage as a Higher Order Component: ```javascript import { Permissible } from '@brainhubeu/react-permissible'; ... function callbackFunction({ userPermissions, requiredPermissions }) { // do something } const RestrictedComponent = (

Restricted component

); const PermissibleComponent = Permissible( RestrictedComponent, userPermissions, requiredPermissions, callbackFunction, oneperm, ); render() { } ``` Where: * `RestrictedComponent`: a component to render * `userPermissions`: an array of permissions set for current user * `requiredPermissions`: an array of required permissions * `oneperm`: boolean determining that only one of required permissions will be necessary instead of requiring all passed permissions (optional) ================================================ FILE: docs-www/.gitignore ================================================ # Logs logs *.log* # node-waf configuration .lock-wscript # Dependency directory node_modules # IDEA/Webstorm project files .idea *.iml #VSCode metadata .vscode # Mac files .DS_Store # Gatsby .cache public ================================================ FILE: docs-www/LICENSE ================================================ The MIT License (MIT) Copyright (c) 2017-2020 Brainhub Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: docs-www/README.md ================================================ # Gatsby Docs Kit Starter The default Brainhub static docs starter. ## Try it out Ensure you have the latest version of [Node](https://nodejs.org/en/download/) installed. We also recommend you install [Yarn](https://yarnpkg.com/en/docs/install) as well. Then run: ```bash yarn install ``` Seed documentation (if you don't have any yet): ```bash yarn seed ``` Run the local webserver via `yarn develop`; The example site is available at http://localhost:8000. You should see the example site loaded in your web browser. Also visit http://localhost:8000/___graphql to explore your site's GraphiQL data and schema. Then go to `../docs` to edit and write awesome docs!. ## Deploy Ready to go? Want to deploy documentation to github pages? Run: ```bash yarn deploy:gh ``` ================================================ FILE: docs-www/gatsby-config.js ================================================ 'use strict'; const path = require('path'); const pluginConfigFactory = require('@brainhubeu/gatsby-docs-kit/plugins'); module.exports = { siteMetadata: { title: 'react-permissible Docs', description: 'Making the permission management for React components easier', image: 'https://cdn-images-1.medium.com/max/1200/1*CLUFZFaXF6NG27NA3d_JkQ.jpeg', url: 'https://brainhubeu.github.io/react-permissible', type: 'article', siteName: 'react-permissible Docs', githubUrl: 'https://github.com/brainhubeu', }, // URL prefix on production environment. For more info see https://www.gatsbyjs.org/docs/path-prefix/ pathPrefix: process.env.PATH_PREFIX || ' ', plugins: [ ...pluginConfigFactory({ config: `${__dirname}/gatsby-docs-kit.yml`, resources: path.resolve(__dirname, '../docs'), }), { resolve: `gatsby-plugin-google-analytics`, options: { trackingId: 'UA-62818184-6', head: false, anonymize: true, respectDNT: true, pageTransitionDelay: 0, cookieDomain: 'brainhubeu.github.io', }, ], }; ================================================ FILE: docs-www/gatsby-docs-kit.yml ================================================ - title: Home dir: ./src url: / file: pages/landing.js - title: Docs dir: ../docs url: docs sidemenu: - title: Getting Started dir: getting-started items: - title: Overview file: overview.md - title: Installation file: installation.md - title: Usage dir: usage items: - title: As an ordinary component file: basic.md - title: As Higher Order Component file: hoc.md - title: Examples dir: examples items: - title: Render component when all the permissions match file: permissionsMatch.md - title: Render component when one of the permissions match file: oneMatch.md - title: Render another component if the permissions do not match file: renderOtherwise.md - title: Callback function file: callback.md ================================================ FILE: docs-www/package.json ================================================ { "name": "@brainhubeu/gatsby-docs-kit-start", "description": "Gatsby-Docs-Kit starter repository", "version": "0.0.32", "author": "Brainhub", "license": "MIT", "scripts": { "build": "rm -rf .cache && rm -rf public && gatsby build --prefix-paths", "deploy:gh": "bash tools/deploy-github.sh", "develop": "rm -rf .cache && gatsby develop", "seed": "bash tools/seed.sh", "serve": "gatsby serve", "lint": "eslint --ext .jsx,.js .", "lint:autofix": "eslint --ext .jsx,.js . --fix" }, "dependencies": { "@brainhubeu/gatsby-docs-kit": "1.0.10", "@brainhubeu/react-permissible": "^1.9.13", "gatsby": "1.9.279" }, "devDependencies": { "eslint": "^7.3.1", "eslint-config-brainhub": "^1.13.0", "gh-pages": "^3.1.0", "react": "^16.13.1", "react-dom": "^16.13.1" } } ================================================ FILE: docs-www/src/globalReferences.js ================================================ import React from 'react'; import { Permissible, PermissibleRender } from '@brainhubeu/react-permissible'; const boxStyle = { height: 130, width: 130, display: 'flex', margin: '0 auto', textAlign: 'center', backgroundColor: '#b5ffb5', justifyContent: 'center', flexDirection: 'column', }; const notAllowedBoxStyle = { ...boxStyle, backgroundColor: '#ffb5b5', }; const AccessGranted = () => (
Access Granted
); const AccessDenied = () => (
Access Denied
); const callbackFunction = ({ userPermissions, requiredPermissions }) => { console.log(` react-permissible: Access Denied; userPermissions: ${userPermissions} requiredPermissions: ${requiredPermissions} `); }; const CallbackComponent = Permissible( AccessGranted, ['ACCESS_DASHBOARD'], // userPermissions ['ACCESS_ADMIN'], // requiredPermissions callbackFunction, // no callback false, // all permissions have to match ); export { Permissible, PermissibleRender, AccessGranted, AccessDenied, CallbackComponent, }; ================================================ FILE: docs-www/src/layouts/.gitkeep ================================================ ================================================ FILE: docs-www/src/pages/404.js ================================================ import React from 'react'; const NotFoundPage = () => (

NOT FOUND

You just hit a route that doesn't exist... the sadness.

); export default NotFoundPage; ================================================ FILE: docs-www/src/pages/landing.js ================================================ import React from 'react'; import Link from 'gatsby-link'; import styles from './landing.module.scss'; const LandingPage = () => (

react-permissible

Making the permission management for components easier.

Get started!
); export default LandingPage; ================================================ FILE: docs-www/src/pages/landing.module.scss ================================================ @import './variables.scss'; .landing { text-align: center; display: flex; align-items: center; justify-content: center; min-height: calc(100vh - 2*#{$mainNavHeight} - 64px); } .landing__header { text-transform: uppercase; font-size: 3rem; letter-spacing: 2px; margin-bottom: 1rem; margin-top: 0; } .btn__wrapper { display: flex; justify-content: center; } .landing__btn { display: inline-block; background-color: $colorBHBg; text-decoration: none; color: $white; padding: 1rem 2rem; margin: 2rem; position: relative; overflow: hidden; span { position: relative; z-index: 1; } &:after, &:before { content: ''; position: absolute; top: 0; bottom: 0; width: 50%; background-color: $colorBHMain; transition: width .3s ease-out; } &:after { left: 0; } &:before { right: 0; } &:hover { color: $white; &:after, &:before { width: 0; } } } .landing__btn--alt { composes: landing__btn; background-color: transparent; color: rgba($colorBHBg, .7); transition: color .3s; &:after, &:before { background-color: transparent; border-style: solid; border-color: $colorBHMain; } &:after { border-width: 1px 0 1px 1px; } &:before { border-width: 1px 1px 1px 0; } &:hover { color: $colorBHMain; } } ================================================ FILE: docs-www/src/pages/variables.scss ================================================ $colorBHBg: #150940; $colorBHMain: #7b59ff; $white: #ffffff; $mainNavHeight: 80px; ================================================ FILE: docs-www/src/templates/.gitkeep ================================================ ================================================ FILE: docs-www/tools/deploy-github.sh ================================================ #!/bin/bash GITHUB_REPO_NAME=$(basename -s .git `git config --get remote.origin.url`); PATH_PREFIX="/$GITHUB_REPO_NAME" npm run build # deploy to github pags node ./node_modules/.bin/gh-pages -d public ================================================ FILE: docs-www/tools/seed/example.md ================================================ # CLI Commands ### Running an app 1. running an application on locally ```bash npm run develop # or yarn develop ``` Gatsby will start a hot-reloading development environment accessible at [http://localhost:8000](http://localhost:8000) 2. preparing optimized production build ```bash npm run build ``` 3. serving locally production build ```bash npm run serve ``` > Note that your site by default will be available on [http://localhost:9000](http://localhost:9000) 4. deploying to github pages ```bash npm run deploy:gh ``` > See more [HERE](../getting-started/publishing.md) ================================================ FILE: docs-www/tools/seed.sh ================================================ #!/bin/bash CONFIG_FILE="gatsby-docs-kit.yml" DIR_NAME="docs" # Create docs directory if [ -d "../${DIR_NAME}" ]; then echo '"docs" directory already exists. Can not seed it. Remove it and try again.' exit 1; fi mkdir -p "../${DIR_NAME}" # Create gastsby docs kit config file if do not exists if [ ! -f "./${CONFIG_FILE}" ]; then echo "" > $CONFIG_FILE; fi # Create example Mk cp ./tools/seed/example.md ../${DIR_NAME}/example.md # Seeding gastsby docs kit config file echo "- title: Home dir: ../docs url: docs file: example.md" >> $CONFIG_FILE; # Done echo "Done!" ================================================ FILE: lib/react-permissible.js ================================================ !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("react")):"function"==typeof define&&define.amd?define("react-permissible",["react"],e):"object"==typeof exports?exports["react-permissible"]=e(require("react")):t["react-permissible"]=e(t.React)}("undefined"!=typeof self?self:this,function(t){return function(t){function e(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var r={};return e.m=t,e.c=r,e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=8)}([function(t,e){function r(){throw new Error("setTimeout has not been defined")}function n(){throw new Error("clearTimeout has not been defined")}function o(t){if(s===setTimeout)return setTimeout(t,0);if((s===r||!s)&&setTimeout)return s=setTimeout,setTimeout(t,0);try{return s(t,0)}catch(e){try{return s.call(null,t,0)}catch(e){return s.call(this,t,0)}}}function i(t){if(l===clearTimeout)return clearTimeout(t);if((l===n||!l)&&clearTimeout)return l=clearTimeout,clearTimeout(t);try{return l(t)}catch(e){try{return l.call(null,t)}catch(e){return l.call(this,t)}}}function u(){h&&y&&(h=!1,y.length?d=y.concat(d):v=-1,d.length&&a())}function a(){if(!h){var t=o(u);h=!0;for(var e=d.length;e;){for(y=d,d=[];++v1)for(var r=1;r-1}function o(t,e,r){for(var n=-1,o=t?t.length:0;++n-1}function P(t,e){var r=this.__data__,n=M(r,t);return n<0?r.push([t,e]):r[n][1]=e,this}function E(t){var e=-1,r=t?t.length:0;for(this.clear();++e=120&&h.length>=120)?new C(l&&h):void 0}h=t[0];var v=-1,b=p[0];t:for(;++v-1&&t%1==0&&t<=Q}function G(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function H(t){return!!t&&"object"==typeof t}var K="__lodash_hash_undefined__",Q=9007199254740991,X="[object Function]",Z="[object GeneratorFunction]",tt=/[\\^$.*+?()[\]{}|]/g,et=/^\[object .+?Constructor\]$/,rt="object"==typeof e&&e&&e.Object===Object&&e,nt="object"==typeof self&&self&&self.Object===Object&&self,ot=rt||nt||Function("return this")(),it=Array.prototype,ut=Function.prototype,at=Object.prototype,ct=ot["__core-js_shared__"],ft=function(){var t=/[^.]+$/.exec(ct&&ct.keys&&ct.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}(),st=ut.toString,lt=at.hasOwnProperty,pt=at.toString,yt=RegExp("^"+st.call(lt).replace(tt,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),dt=it.splice,ht=Math.max,vt=Math.min,bt=D(ot,"Map"),_t=D(Object,"create");y.prototype.clear=d,y.prototype.delete=h,y.prototype.get=v,y.prototype.has=b,y.prototype.set=_,m.prototype.clear=g,m.prototype.delete=w,m.prototype.get=O,m.prototype.has=j,m.prototype.set=P,E.prototype.clear=S,E.prototype.delete=x,E.prototype.get=T,E.prototype.has=$,E.prototype.set=k,C.prototype.add=C.prototype.push=A,C.prototype.has=R;var mt=function(t,e){return e=ht(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,i=ht(n.length-e,0),u=Array(i);++o-1}function o(t,e,r){for(var n=-1,o=t?t.length:0;++n-1}function E(t,e){var r=this.__data__,n=I(r,t);return n<0?r.push([t,e]):r[n][1]=e,this}function S(t){var e=-1,r=t?t.length:0;for(this.clear();++e=Z&&(c=l,f=!1,e=new A(e));t:for(;++a0&&r(c)?e>1?F(c,e-1,r,n,o):u(o,c):n||(o[o.length]=c)}return o}function V(t){return!(!Q(t)||z(t))&&(H(t)||y(t)?_t:ut).test(U(t))}function D(t,e){var r=t.__data__;return W(e)?r["string"==typeof e?"string":"hash"]:r.map}function q(t,e){var r=p(t,e);return V(r)?r:void 0}function L(t){return xt(t)||J(t)||!!(Ot&&t&&t[Ot])}function W(t){var e=typeof t;return"string"==e||"number"==e||"symbol"==e||"boolean"==e?"__proto__"!==t:null===t}function z(t){return!!dt&&dt in t}function U(t){if(null!=t){try{return ht.call(t)}catch(t){}try{return t+""}catch(t){}}return""}function Y(t,e){return t===e||t!==t&&e!==e}function J(t){return G(t)&&vt.call(t,"callee")&&(!gt.call(t,"callee")||bt.call(t)==rt)}function B(t){return null!=t&&K(t.length)&&!H(t)}function G(t){return X(t)&&B(t)}function H(t){var e=Q(t)?bt.call(t):"";return e==nt||e==ot}function K(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=et}function Q(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function X(t){return!!t&&"object"==typeof t}var Z=200,tt="__lodash_hash_undefined__",et=9007199254740991,rt="[object Arguments]",nt="[object Function]",ot="[object GeneratorFunction]",it=/[\\^$.*+?()[\]{}|]/g,ut=/^\[object .+?Constructor\]$/,at="object"==typeof e&&e&&e.Object===Object&&e,ct="object"==typeof self&&self&&self.Object===Object&&self,ft=at||ct||Function("return this")(),st=Array.prototype,lt=Function.prototype,pt=Object.prototype,yt=ft["__core-js_shared__"],dt=function(){var t=/[^.]+$/.exec(yt&&yt.keys&&yt.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}(),ht=lt.toString,vt=pt.hasOwnProperty,bt=pt.toString,_t=RegExp("^"+ht.call(vt).replace(it,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),mt=ft.Symbol,gt=pt.propertyIsEnumerable,wt=st.splice,Ot=mt?mt.isConcatSpreadable:void 0,jt=Math.max,Pt=q(ft,"Map"),Et=q(Object,"create");d.prototype.clear=h,d.prototype.delete=v,d.prototype.get=b,d.prototype.has=_,d.prototype.set=m,g.prototype.clear=w,g.prototype.delete=O,g.prototype.get=j,g.prototype.has=P,g.prototype.set=E,S.prototype.clear=x,S.prototype.delete=T,S.prototype.get=$,S.prototype.has=k,S.prototype.set=C,A.prototype.add=A.prototype.push=R,A.prototype.has=M;var St=function(t,e){return e=jt(void 0===e?t.length-1:e,0),function(){for(var n=arguments,o=-1,i=jt(n.length-e,0),u=Array(i);++o1?e-1:0),n=1;n2?r-2:0),o=2;o1?"Invalid arguments supplied to oneOf, expected an array, got "+arguments.length+" arguments. A common mistake is to write oneOf(x, y, z) instead of oneOf([x, y, z]).":"Invalid argument supplied to oneOf, expected an array."),n)}function _(t){function e(e,r,n,o,i){if("function"!=typeof t)return new p("Property `"+i+"` of component `"+n+"` has invalid PropType notation inside objectOf.");var a=e[r],f=P(a);if("object"!==f)return new p("Invalid "+o+" `"+i+"` of type `"+f+"` supplied to `"+n+"`, expected an object.");for(var s in a)if(c(a,s)){var l=t(a,s,n,o,i+"."+s,u);if(l instanceof Error)return l}return null}return y(e)}function m(t){function r(e,r,n,o,i){for(var a=0;a=6.14.5" }, "scripts": { "lint": "esw webpack.config.* src tools test --color", "lint:types": "esw 'types/*.{ts,tsx}' 'types/tests/*.{ts,tsx}' --ext ts,tsx --color --format codeframe --config ./types/.eslintrc", "lint:types:watch": "npm run --silent lint:types -- --watch", "lint:types:fix": "npm run --silent lint:types -- --fix", "clean-dist": "rm -rf ./lib && mkdir lib", "prebuild": "npm run clean-dist", "build": "node tools/build.js", "test": "mocha tools/testSetup.js \"./test/**/*.js\"", "test:coverage": "NODE_PATH=example babel-node ./node_modules/.bin/isparta cover _mocha -- --require ./tools/testSetup.js \"./test/**/*.js\" && open coverage/lcov-report/index.html", "test:coverage:ci": "NODE_PATH=example babel-node ./node_modules/.bin/isparta cover _mocha --report lcovonly -- --require ./tools/testSetup.js \"./test/**/*.js\"", "test:typescript": "cd ./types/tests && npm install-test --no-audit", "precommit": "npm run lint && npm run lint:types" }, "author": "Krystian Kościelniak", "license": "MIT", "dependencies": { "gatsby-plugin-google-analytics": "2.3.2", "lodash.difference": "^4.5.0", "lodash.intersection": "^4.4.0" }, "devDependencies": { "autoprefixer": "^9.8.4", "babel-cli": "^6.26.0", "babel-core": "^6.26.3", "babel-eslint": "^10.1.0", "babel-loader": "^8.1.0", "babel-plugin-react-display-name": "^2.0.0", "babel-plugin-transform-decorators-legacy": "^1.3.5", "babel-plugin-transform-react-constant-elements": "^6.23.0", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "babel-polyfill": "^6.26.0", "babel-preset-env": "^1.7.0", "babel-preset-es2015": "^6.24.1", "babel-preset-latest": "^6.24.1", "babel-preset-react": "^6.24.1", "babel-preset-react-hmre": "^1.1.1", "babel-preset-stage-1": "^6.24.1", "babel-register": "^6.26.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "chai-enzyme": "^1.0.0-beta.1", "chalk": "^4.1.0", "coveralls": "^3.1.0", "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.2", "eslint": "^7.3.1", "eslint-config-brainhub": "^1.13.0", "eslint-plugin-typescript": "^0.14.0", "eslint-watch": "^7.0.0", "html-webpack-plugin": "^4.3.0", "husky": "^4.2.5", "isparta": "^4.1.1", "jsdom": "^16.2.2", "mocha": "^8.0.1", "prop-types": "^15.7.2", "react": "^16.13.1", "react-dom": "^16.13.1", "react-test-renderer": "^16.13.1", "sinon": "^9.0.2", "sinon-chai": "^3.5.0", "typescript": "^3.9.6", "typescript-eslint-parser": "^21.0.2", "uglifyjs-webpack-plugin": "^2.2.0", "webpack": "^4.43.0" }, "peerDependencies": { "react": ">0.14.0 || >15.0.0", "react-dom": ">0.14.0 || >15.0.0" }, "keywords": [ "react", "react-permissions", "permissions", "permission-manager", "props", "callback", "users", "authentication", "optional-props", "authorization", "access-control" ], "repository": { "type": "git", "url": "https://github.com/brainhubeu/react-permissible" }, "main": "./lib/react-permissible.js", "types": "./types/react-permissible.d.ts" } ================================================ FILE: renovate.json ================================================ { "bumpVersion": "patch", "commitMessagePrefix": "[renovate] ", "groupName": "NPM dependencies", "labels": ["renovate"], "rangeStrategy": "bump", "branchPrefix": "fix/renovate/", "docker": { "major": { "enabled": true } }, "packageRules": [ { "groupName": "Docker dependencies", "managers": [ "circleci" ] }, { "groupName": "gatsby", "managerBranchPrefix": "gatsby", "packagePatterns": [ "gatsby" ], "rangeStrategy": "pin" } ], "schedule": [ "before 3am on the first day of the month" ] } ================================================ FILE: src/components/permissible.js ================================================ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import intersection from 'lodash.intersection'; import difference from 'lodash.difference'; export function Permissible( RestrictedComponent, userPermissions, requiredPermissions, callbackFunction, oneperm, ) { const permissionsStatus = oneperm ? intersection(userPermissions, requiredPermissions).length : difference(requiredPermissions, userPermissions).length === 0; class PermissibleHOC extends Component { static propTypes = { oneperm: PropTypes.bool, history: PropTypes.object, // eslint-disable-line react/forbid-prop-types }; constructor(props) { super(props); if (!permissionsStatus) { this.runCallback(); } } runCallback() { if (callbackFunction) { return callbackFunction({ userPermissions, requiredPermissions, }, this.props.history); } return; } render() { if (permissionsStatus) { return ; } return null; } } return PermissibleHOC; } ================================================ FILE: src/components/permissibleRender.js ================================================ import { Component } from 'react'; import PropTypes from 'prop-types'; import intersection from 'lodash.intersection'; import difference from 'lodash.difference'; export class PermissibleRender extends Component { static propTypes = { oneperm: PropTypes.bool, userPermissions: PropTypes.arrayOf(PropTypes.string).isRequired, requiredPermissions: PropTypes.arrayOf(PropTypes.string).isRequired, children: PropTypes.element.isRequired, renderOtherwise: PropTypes.element, }; checkPermissions() { const { userPermissions, requiredPermissions, oneperm } = this.props; if (oneperm) { return intersection(userPermissions, requiredPermissions).length; } return difference(requiredPermissions, userPermissions).length === 0; } render() { const { children, userPermissions, requiredPermissions, renderOtherwise } = this.props; if (!children || !userPermissions || !requiredPermissions) { return null; } if (this.checkPermissions()) { return children; } else if (renderOtherwise) { return renderOtherwise; } return null; } } ================================================ FILE: src/index.js ================================================ import { Permissible } from './components/permissible'; import { PermissibleRender } from './components/permissibleRender'; export { Permissible, PermissibleRender, }; ================================================ FILE: test/.eslintrc ================================================ { env: { es6: true, browser: true, node: true, mocha: true, }, } ================================================ FILE: test/accessible.component.js ================================================ import React from 'react'; import PropTypes from 'prop-types'; const Accessible = ({ permission, oneperm }) => (

{oneperm ? 'One of' : 'Whole set of'} {permission} is necessary to see this component.

); Accessible.propTypes = { permission: PropTypes.string, oneperm: PropTypes.bool, }; export default Accessible; ================================================ FILE: test/permissible.test.js ================================================ import React from 'react'; import { shallow } from 'enzyme'; import chai from 'chai'; import chaiEnzyme from 'chai-enzyme'; import { JSDOM } from 'jsdom'; import { Permissible } from '../src/components/permissible'; import AccessedComponent from './accessible.component'; const { document } = (new JSDOM('')).window; global.document = document; global.window = document.defaultView; chai.use(chaiEnzyme()); chai.should(); describe('Permissible HOC', () => { it('doesn\'t run a callback function if the permissions are right', done => { let err = null; const AccessibleRoute = Permissible( () => , ['MATCHING_PERMISSIONS'], ['MATCHING_PERMISSIONS'], () => { err = new Error('Callback function called.'); }, ); shallow( , ); done(err); }); it('doesn\'t run a callback function if `requiredPermissions` and `userPermissions` are both empty', done => { let err = null; const AccessibleRoute = Permissible( () => , [], [], () => { err = new Error('Callback function called.'); }, ); shallow( , ); done(err); }); it('doesn\'t run a callback function if only `requiredPermissions` are empty', done => { let err = null; const AccessibleRoute = Permissible( () => , ['SOME_PERMISSION'], [], () => { err = new Error('Callback function called.'); }, ); shallow( , ); done(err); }); it('runs a callback function if the permissions don\'t match', done => { const AccessibleRoute = Permissible( () => , ['MATCHING_PERMISSIONS'], ['UNMATCHING_PERMISSIONS'], () => { done(); }, ); shallow( , ); }); it('doesn\'t run a callback function if the user has one of necessary permissions and `oneperm` is `true`', done => { let err = null; const AccessibleRoute = Permissible( () => , ['REQUIRED_PERMISSION'], ['REQUIRED_PERMISSION', 'ANOTHER_PERMISSION'], () => { err = new Error('Callback function called.'); }, true, ); shallow( , ); done(err); }); it('runs a callback function if the user has one of necessary permissions and `oneperm` is `false`', done => { const AccessibleRoute = Permissible( () => , ['REQUIRED_PERMISSION'], ['REQUIRED_PERMISSION', 'ANOTHER_PERMISSION'], () => { done(); }, false, ); shallow( , ); }); it('doesn\'t run a callback function if it is not defined', done => { const AccessibleRoute = Permissible( () => , ['REQUIRED_PERMISSION'], ['REQUIRED_PERMISSION', 'ANOTHER_PERMISSION'], null, false, ); shallow( , ); done(); }); }); ================================================ FILE: test/permissibleRender.test.js ================================================ import React from 'react'; import { mount } from 'enzyme'; import chai from 'chai'; import chaiEnzyme from 'chai-enzyme'; import { JSDOM } from 'jsdom'; import { PermissibleRender } from '../src/components/permissibleRender'; const should = chai.should(); const { document } = (new JSDOM('')).window; global.document = document; global.window = document.defaultView; chai.use(chaiEnzyme()); chai.should(); describe('PermissibleRender', () => { const ChildComponent = () => (
Child component
); const NotAllowedComponent = () => (
Not allowed component
); it('doesn\'t render a if `userPermissions` prop is not set', () => { const props = { requiredPermissions: [], }; const mountedComponent = mount( , ); const searchedElement = mountedComponent.find('ChildComponent'); searchedElement.length.should.be.equal(0); }); it('doesn\'t render a if `requiredPermissions` prop is not set', () => { const props = { userPermissions: [], }; const mountedComponent = mount( , ); const searchedElement = mountedComponent.find('ChildComponent'); searchedElement.length.should.be.equal(0); }); it('renders nothing if `children` prop is not set', () => { const props = { userPermissions: [], }; const mountedComponent = mount( , ); should.not.exist(mountedComponent.find('PermissibleRender').html()); }); it('renders a if user permissions and required permissions are both empty', () => { const props = { userPermissions: [], requiredPermissions: [], }; const mountedComponent = mount( , ); const searchedElement = mountedComponent.find('ChildComponent'); searchedElement.length.should.be.equal(1); }); it('renders a if only required permissions are empty', () => { const props = { userPermissions: ['SOME_PERMISSION'], requiredPermissions: [], }; const mountedComponent = mount( , ); const searchedElement = mountedComponent.find('ChildComponent'); searchedElement.length.should.be.equal(1); }); it('doesn\'t render a if there is a permission mismatch', () => { const props = { userPermissions: ['REQUIRED_PERMISSION'], requiredPermissions: ['ANOTHER_PERMISSION'], }; const mountedComponent = mount( , ); const searchedElement = mountedComponent.find('ChildComponent'); searchedElement.length.should.be.equal(0); }); it('renders a if the user has required permission', () => { const props = { userPermissions: ['REQUIRED_PERMISSION'], requiredPermissions: ['REQUIRED_PERMISSION'], }; const mountedComponent = mount( , ); const searchedElement = mountedComponent.find('ChildComponent'); searchedElement.length.should.be.greaterThan(0); }); it('renders a if the user doesn\'t have required permissions and renderOtherwise is given', () => { const props = { userPermissions: ['REQUIRED_PERMISSION'], requiredPermissions: ['NOT_REQUIRED_PERMISSION'], renderOtherwise: , }; const mountedComponent = mount( , ); const searchedElement = mountedComponent.find('NotAllowedComponent'); searchedElement.length.should.be.greaterThan(0); }); it('renders a if the user has one of necessary conditions when `oneperm` prop is defined', () => { const props = { userPermissions: ['ANOTHER_PERMISSION'], requiredPermissions: ['REQUIRED_PERMISSION', 'ANOTHER_PERMISSION'], oneperm: true, }; const mountedComponent = mount( , ); const searchedElement = mountedComponent.find('ChildComponent'); searchedElement.length.should.be.greaterThan(0); }); it('doesn\'t render a if the user doesn\'t have all of necessary permissions when `oneperm` prop is explicitly set to false', () => { const props = { userPermissions: ['REQUIRED_PERMISSION'], requiredPermissions: ['REQUIRED_PERMISSION', 'ANOTHER_PERMISSION'], oneperm: false, }; const mountedComponent = mount( , ); const searchedElement = mountedComponent.find('ChildComponent'); searchedElement.length.should.be.equal(0); }); }); ================================================ FILE: tools/build.js ================================================ // More info on Webpack's Node API here: https://webpack.github.io/docs/node.js-api.html // Allowing console calls below since this is a build file. /* eslint-disable no-console */ const chalk = require('chalk'); const webpack = require('webpack'); const config = require('../webpack.config.prod'); const chalkConfig = { chalkError: chalk.red, chalkSuccess: chalk.green, chalkWarning: chalk.yellow, chalkProcessing: chalk.blue, }; const { chalkError, chalkSuccess, chalkWarning, chalkProcessing } = chalkConfig; process.env.NODE_ENV = 'production'; // this assures React is built in prod mode and that the Babel dev config doesn't apply. console.log(chalkProcessing('Generating minified bundle. This will take a moment...')); webpack(config).run((error, stats) => { if (error) { // so a fatal error occurred. Stop here. console.log(chalkError(error)); return 1; } const jsonStats = stats.toJson(); if (jsonStats.hasErrors) { return jsonStats.errors.map(error => console.log(chalkError(error))); } if (jsonStats.hasWarnings) { console.log(chalkWarning('Webpack generated the following warnings: ')); jsonStats.warnings.map(warning => console.log(chalkWarning(warning))); } console.log(`Webpack stats: ${stats}`); // if we got this far, the build succeeded. console.log(chalkSuccess('Your app is compiled in production mode in /dist. It\'s ready to roll!')); return 0; }); ================================================ FILE: tools/testSetup.js ================================================ process.env.NODE_ENV = 'test'; // Disable webpack-specific features for tests since // Mocha doesn't know what to do with them. /* istanbul ignore next */ ['.css', '.scss', '.png', '.jpg'].forEach(ext => { require.extensions[ext] = () => null; }); // add required globals /* eslint-disable no-empty-function */ /* istanbul ignore next */ global.logger = function() {}; /* istanbul ignore next */ global.logger.info = function() {}; /* istanbul ignore next */ global.logger.apiSuccess = function() {}; /* istanbul ignore next */ global.logger.apiError = function() {}; /* istanbul ignore next */ global.logger.warn = function() {}; /* eslint-enable */ // Register babel so that it will transpile ES6 to ES5 // before our tests run. require('babel-register')(); require('babel-polyfill'); const chai = require('chai'); const sinonChai = require('sinon-chai'); const chaiAsPromised = require('chai-as-promised'); const enzyme = require('enzyme'); const Adapter = require('enzyme-adapter-react-16'); enzyme.configure({ adapter: new Adapter() }); chai.use(sinonChai); chai.use(chaiAsPromised); ================================================ FILE: types/.eslintrc ================================================ { "parser": "typescript-eslint-parser", "plugins": ["eslint-plugin-typescript"], "extends": "../.eslintrc", "rules": { "comma-dangle":"off", "no-unused-vars": "off", "import/no-namespace": "off", "typescript/no-unused-vars": "error" } } ================================================ FILE: types/react-permissible.d.ts ================================================ import { Component, ComponentState, ComponentType, ReactNode, ReactNodeArray, StaticLifecycle, ValidationMap, } from 'react'; declare module '@brainhubeu/react-permissible' { type Permissions = string[]; type Children = ReactNode | ReactNodeArray; export interface UserAndRequiredPermissions { userPermissions: Permissions requiredPermissions: Permissions } export interface PermissibleRenderProps extends UserAndRequiredPermissions { oneperm?: boolean children: Children renderOtherwise?: Children } export class PermissibleRender extends Component { checkPermissions(): boolean } export function Permissible( RestrictedComponent: ComponentType, userPermissions: Permissions, requiredPermissions: Permissions, callbackFunction?: ({ userPermissions, requiredPermissions, }: UserAndRequiredPermissions) => void, oneperm?: boolean, ): PermissibleHOC interface PermissibleHOC extends StaticLifecycle { new (props: Props, context?: any): Component & TE propTypes?: ValidationMap contextTypes?: ValidationMap childContextTypes?: ValidationMap defaultProps?: Partial displayName?: string } } ================================================ FILE: types/tests/.gitignore ================================================ brainhubeu-react-permissible-*.tgz node_modules/ ================================================ FILE: types/tests/.npmrc ================================================ update-notifier=false audit=false prefer-offline=true ================================================ FILE: types/tests/Permissible.test.tsx ================================================ import * as React from 'react'; import { render } from 'react-dom'; // eslint-disable-next-line import/no-unresolved, import/no-extraneous-dependencies, /* this is what we're testing */ import { Permissible, UserAndRequiredPermissions } from '@brainhubeu/react-permissible'; function callbackFunction({ userPermissions, requiredPermissions }: UserAndRequiredPermissions) { // eslint-disable-next-line no-console console.info(` react-permissible: Access Denied userPermissions: ${userPermissions} requiredPermissions: ${requiredPermissions} `); } const AccessGranted = ({ message }: { message: string, }) => <>AccessGranted {message}; const RestrictedComponentWithCallback = Permissible( AccessGranted, ['ACCESS_DASHBOARD'], // userPermissions ['ACCESS_ADMIN'], // requiredPermissions callbackFunction, ); render(, document.createElement('div')); ================================================ FILE: types/tests/PermissibleRender.test.tsx ================================================ import * as React from 'react'; import { render } from 'react-dom'; // eslint-disable-next-line import/no-unresolved, import/no-extraneous-dependencies, /* this is what we're testing */ import { PermissibleRender, PermissibleRenderProps } from '@brainhubeu/react-permissible'; const VIEW_PERMISSION = 'VIEW'; const permissibleRenderTestProps: PermissibleRenderProps = { oneperm: false, children: 'restricted content', userPermissions: [VIEW_PERMISSION], requiredPermissions: [VIEW_PERMISSION], renderOtherwise: 'ACCESS DENIED', }; render(, document.createElement('div')); ================================================ FILE: types/tests/package.json ================================================ { "name": "react-permissible-typescript-tests", "version": "1.0.27", "description": "Test publishing the typings of react-permissible package", "scripts": { "clean:packed-package": "rm ./brainhubeu-react-permissible-*.tgz", "clean:node-modules": "rm -rf ./node_modules/", "preinstall": "npm run clean:packed-package && npm run clean:node-modules", "pack-parent-package-get-filename": "npm pack ../.. | grep \\.tgz", "postinstall": "npm install --no-save --no-audit `npm run --silent pack-parent-package-get-filename`", "test": "tsc --project .", "posttest": "echo 'TypeScript typings successfuly compiled!'" }, "repository": { "type": "git", "url": "https://github.com/brainhubeu/react-permissible" }, "author": "Nick Ribal (https://about.me/nickribal)", "license": "MIT", "dependencies": { "@types/react": "^16.9.41", "@types/react-dom": "^16.9.8", "react": "^16.13.1", "react-dom": "^16.13.1", "typescript": "^3.9.6" } } ================================================ FILE: types/tests/tsconfig.json ================================================ { "compilerOptions": { "target": "es6", "module": "es2015", "noEmit": true, "jsx": "react", "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "node" } } ================================================ FILE: webpack.config.prod.js ================================================ const path = require('path'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); module.exports = { externals: [ { 'react-dom': { root: 'ReactDOM', commonjs2: 'react-dom', commonjs: 'react-dom', amd: 'react-dom', }, }, { react: { root: 'React', commonjs2: 'react', commonjs: 'react', amd: 'react', }, }, ], resolve: { extensions: ['.js', '.jsx', '.json'], modules: [ 'node_modules', path.join(__dirname, 'src'), ], }, devtool: 'source-map', entry: './src/index.js', output: { filename: 'react-permissible.js', library: 'react-permissible', libraryTarget: 'umd', path: path.resolve(__dirname, 'lib'), umdNamedDefine: true, }, optimization: { minimizer: [ new UglifyJsPlugin({ sourceMap: false, }), ], }, module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, use: ['babel-loader'], }, ], }, };