Skip to content
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

WIP - Add react package #55

Open
wants to merge 53 commits into
base: master
Choose a base branch
from

Conversation

AlfredoGJ
Copy link

@AlfredoGJ AlfredoGJ commented Oct 25, 2021

What does this PR do?

Address #28

Provides an access-decision-manager binding for react with the next modules

<AccessDecisionManagerProvider user={} voters={}> component - Provides a component that binds the accessDecisionManager functioality with their respective arguments {user, voters, context?

useIsGranted() - hook- This hooks must be used in components that are under the AccessDecisionManagerProvider component to be able to use the voters and user

Why is this important?

Where should the reviewer start?

How should this be manually tested?

  1. Clone the repo
  2. Go to /packages/access-decision-manager-react/
  3. run npm install
  4. run npx jest --verbose all test should pass

Pending work

  • Create readme
  • Enable strategies
  • Verify usage of context
  • Write examples with tests

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • I have added necessary documentation (if appropriate)
  • I did review existing Pull Requests before submitting mine
  • I have added tests that prove my fix is effective or that my feature works

@AlfredoGJ AlfredoGJ changed the title Add react package WIP - Add react package Oct 25, 2021
@@ -1,24 +1,24 @@
{
"devDependencies": {
"@types/express": "^4.17.0",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I started merging some of the NPM package updates and now the package-lock.json file needs to be updated. I think it should be relatively easy to rebase this branch accepting their changes, and then running npm update to fix.

useEffect,
ReactElement,
ReactComponentElement,
ReactNode,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make sure to not import things we don't use.

Ideally we have an ESLint rule to check for this.

AccessDecisionManager
>(null);

interface IAccessDecisionManagerProviderProps {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not prefix our Interfaces with I. See typescript-eslint/typescript-eslint#374 (comment) for an explaination.

Ideally we should have that ESLint rule enabled to check this for us.

voters,
createContext: createContext,
}: IAccessDecisionManagerProviderProps) => {
const [accessDecisionManager, setAccessDecisionManager] = useState<
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussion: I could be wrong, but I think we might be better off using useRef here instead of useState. useState will always cause a rerender, where instead I think we want to only rerender the consumers of our context.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes me think a bit... Maybe accessDecisionManager could be just a var since the AccessDecisionManagerProvider component does not need to preserve its value across renders (that is done by AccessDecisionManagerContext.Provider component already) and we only need to change it when user, voters or createContext are updated

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: yeah it needs to be a ref, since a var will be re-created every time the component renders even if the user voters or createContext props keep the same

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left this as a useState cause with useRef creating a new accessDecisionManager on user voters or createContext properties update had no effect on AccessDecisionManagerContext.Provider's value


export const reducer = (state: any, action: any) => {
switch (action.type) {
case 'error':
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this approach. It reminds me of https://kentcdodds.com/blog/stop-using-isloading-booleans

};

default:
throw new Error('invalid action type');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can improve debugging if we also tell the action type:

      throw new Error(`Unhandled action type: ${action.type}`)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, will improve it

loading: true,
};

export const reducer = (state: any, action: any) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's improve the types here to not use any.


const useIsGranted = (attribute: any, subject?: any) => {
const accessDecisionManager = useContext(AccessDecisionManagerContext);
if (!accessDecisionManager) throw Error(errorMessage);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a preference and we should have an ESLint rule for it, but lets always use curly braces with our if statements:

https://eslint.org/docs/rules/curly


export const initialState = {
error: undefined,
isGranted: undefined,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can discuss this more later, but having multiple "empty values" (undefined, and null) can be confusing and so far I think we've been consistent on using undefined.

If possible, let's try to stick to only using undefined when a value is not set.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, i think in some cases null is a more descriptive value than undefined but im ok with keep using undefined for the sake of consistency

dependabot bot added 5 commits October 26, 2021 14:53
Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/daaku/nodejs-tmpl/releases)
- [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5)

---
updated-dependencies:
- dependency-name: tmpl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
AlfredoGJ and others added 25 commits October 26, 2021 14:55
The hook useIsGranted might use async logic that needs to be resolved before returnuing a result but
hooks doesn't work well with `async await` so a new local state management was introduce to handle
ot its logic that is watching `accessDecisionManager`, `attribute`, and `subject`
@AlfredoGJ AlfredoGJ requested a review from m14t October 26, 2021 23:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants