npm package: @ikonintegration/mod-fine-auth
Description: Fine authorization module
Author: Ikon Integration
Latest version: 0.0.8

# mod-fine-auth ![Node.js Package](https://github.com/ikon-integration/mod-fine-auth/workflows/Node.js%20Package/badge.svg)

Fine Auth Module

### Overall

- ![npm](https://img.shields.io/npm/dy/@ikonintegration/mod-fine-auth) ![npm](https://img.shields.io/npm/v/@ikonintegration/mod-fine-auth) ![npm (tag)](https://img.shields.io/npm/v/@ikonintegration/mod-fine-auth/latest) ![Libraries.io dependency status for latest release, scoped npm package](https://img.shields.io/librariesio/release/npm/@ikonintegration/mod-fine-auth)
- ![GitHub commit activity](http://expoblvd2.redirectme.net:8555/github/commit-activity/m/ikon-integration/mod-fine-auth)
- ![GitHub last commit](http://expoblvd2.redirectme.net:8555/github/last-commit/ikon-integration/mod-fine-auth)

### Initializing ACL

```js
import { ACL } from '@ikonintegration/mod-fine-auth';

// Create an ACL instance with user permissions
// * There's no rules to what "level" should be, you can use any string
const acl = new ALC([
    { componentID: 'users', level: 'WRITE' },
    { componentID: 'admins', level: 'READ' },
    { componentID: 'settings', level: 'READWRITE' },
]);
```

### Checking user permissions
We have two ways to validate user permissions, let's start using `hasPermission` method.

### hasPermission
Method signature: `hasPermission(componentID: string, level: string | string[]): boolean`
```js
// Checking for a single level
if (acl.hasPermission('users', 'WRITE')) {
    console.log('Authorized!');
} else {
    console.log('Unauthorized!');
}

// Checking for multiple levels
if (acl.hasPermission('users', ['READ', 'WRITE'])) {
    console.log('Authorized!');
} else {
    console.log('Unauthorized!');
}
```

##### 🚨 Attention
When checking for multiple levels we are not saying that user must have both levels ("AND" conditional), instead, we're using an "OR" condition, this means that in the previous example `hasPermission` will return `true` if user have the "READ" or "WRITE" levels on "users" component.

### Can
Method signature: `Can({ componentID: string, accessLevel: string | string[], acl: ACL, children: Function | any })`

Can is a basic JavaScript function that can be used in pure JavaScript and as a React Component.

**Using with Pure JavaScript:**
```js
import { Can } from '@ikonintegration/mod-fine-auth';

const isAuthorized = Can({
    componentID: 'users',
    accessLevel: 'READ',
    acl: new ACL([...]),
    children: true, // value that will be returned if is authorized
}); // returns "null" if is not authorized

Can({
    componentID: 'users',
    accessLevel: 'READ',
    acl: new ACL([...]),
    children: (hasPermission) => {
        if (hasPermission) {
            console.log('Authorized');
        } else {
            console.log('Unauthorized');
        }
    },
});
```

You can also use the `validationMode` flag as `any` to check if user have any roles in an array of componentIDs:
```js
Can({
    validationMode: 'any',
    componentID: ['users', 'profile'],
    accessLevel: 'READ',
    acl: new ACL([...]),
    children: (hasPermission) => {
        if (hasPermission) {
            console.log('Authorized if user has READ level in users OR Profile');
        } else {
            console.log('Unauthorized');
        }
    },
});
```

**Using with React Components:**
```jsx
import { Can } from '@ikonintegration/mod-fine-auth';

const acl = new ACL([...]);

function App() {
    return (
        <>
            <Can componentID="users" accessLevel="WRITE" acl={acl}>
                <Button>Create</Button>
            </Can>
            
            <Can componentID="users" accessLevel={['WRITE', 'READWRITE']} acl={acl}>
                <Button>Create</Button>
            </Can>
            
            <Can componentID={['users', 'profile']} accessLevel={['WRITE', 'READWRITE']} validationMode="any" acl={acl}>
                <Button>Create</Button>
            </Can>
            
            <Can componentID="users" accessLevel="WRITE" acl={acl}>
                {(hasPermission) => (
                    if (hasPermission) {
                        return <AuthorizedComponent />;
                    } else {
                        return <UnauthorizedComponent />;
                    }
                )}
            </Can>
        </>
    );
}
```