Skip to content

Commit

Permalink
feature(security): add security module with acl implementation
Browse files Browse the repository at this point in the history
Closes #164
  • Loading branch information
nnixaa authored Feb 13, 2018
1 parent 6b93924 commit a4da289
Show file tree
Hide file tree
Showing 37 changed files with 1,705 additions and 56 deletions.
3 changes: 2 additions & 1 deletion .angular-cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@
"assets": [
"assets",
"favicon.ico",
"favicon.png"
"favicon.png",
"google46533d2e7a851062.html"
],
"index": "index.html",
"main": "main.ts",
Expand Down
2 changes: 2 additions & 0 deletions DEV_DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ We have to:
- theme - `@nebular/theme` npm package, main framework package
- auth - `@nebular/auth` npm package, auth package (login, register, etc)
- icons - `nebular-icons` npm package, cool icons font
- security - `@nebular/security` npm package, security framework package



## Auth // TODO
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ What is included:
- Authentication components (login/register/reset password/restore password).
- Multiple configurable providers (backend connectors).
- Helpers for token management (storing, passing with HTTP requests, etc).
3) [ ] @nebular/acl - module for roles and permissions management
3) [x] @nebular/security
- Roles and permissions management (ACL)
- `*nbIsGranted` conditional directive
4) [ ] @nebular/dashboard - module for draggable/resizable dashboards creation
5) [ ] @nebular/data - application data & state management
6) [x] Admin dashboard starter kit [ngx-admin](http://github.com/akveo/ngx-admin) - application based on Nebular modules with beautiful IOT components.
7) [ ] More great features!
7) [ ] More great features to come!

### Demo Application:

Expand All @@ -30,10 +32,10 @@ What is included:


### Use cases
Nebular is a great toolkit if you build a Rich UI application based on Angular, and don't want to spend your time on painful project setup. It provides you with a unified approach for managing styles for various components (3rd party including), pure components tightly connect to Angular and authentication layer easily configurable for your API.
Nebular is a great toolkit if you build a Rich UI web-application based on Angular, and don't want to spend your time on painful project setup. It provides you with a unified approach for managing styles of various components (3rd party including), pure components tightly connected to Angular and authentication layer easily configurable for your API.

### The purpose
There are a lot of awesome front-end frameworks out there these days. They provide a massive quantity of useful features making our lives more comfortable. Our intention is not to create a new one as we are pretty much aware of the complexity and amount of work developers put on their creations. But as developers, we feel that nowadays front-end development is disjointed. You have to search for libraries, go through the different installation process, everything looks different, and sometimes it's just annoying that you can't just sit and start going. That's why we are on a mission to assemble together the most usefule modules and libraries, join them with a unified application and graphical interface creating a great toolkit for easier setup.
There are a lot of awesome front-end frameworks and libraries out there these days. They provide a massive quantity of useful features making our lives more comfortable. Our intention is not to create a new one as we are pretty much aware of the complexity and amount of work developers put on their creations. But as developers, we feel that nowadays front-end development is disjointed. You have to search for libraries, go through the different installation process, everything looks different, and sometimes it's just annoying that you can't just sit and start going. That's why we are on a mission to assemble together the most usefule modules and libraries, join them with a unified application and graphical interface creating a great toolkit for easier setup.

### Documentation
Installation, customization and other useful articles: https://akveo.github.io/nebular
Expand Down
6 changes: 3 additions & 3 deletions docs/app/homepage/homepage.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<h1><span>Nebular</span></h1>
<div class="bigger">Set of essential modules for your next Angular application.</div>
<p>Nebular's primary goal is to assemble together and connect the most awesome features and libraries
creating an efficient ecosystem to speed up and simpify the development.</p>
creating an efficient ecosystem to speed up and simplify the development.</p>
<div class="btn-hero-wrap">
<a href="http://akveo.com/ngx-admin?utm_source=nebular_documentation&utm_medium=demo_button" target="_blank" class="btn btn-hero">Demo</a>
<a href="#/docs" class="docs">Documentation</a>
Expand Down Expand Up @@ -95,8 +95,8 @@ <h2><span>THEME SYSTEM</span></h2>
<div class="row">
<div class="col-md-7 txt">
<img src="assets/images/decor-img-auth-module.png" class="decor-img-auth-module">
<h2><span>Auth Module</span></h2>
<p>Now front-end authentication layer is just a matter of a configuration. <a href="#/docs/auth/conceptsinstall">Concepts.</a></p>
<h2><span>Auth & Security Module</span></h2>
<p>Now front-end authentication and authorization are just a matter of a configuration. <a href="#/docs/auth/introduction">Auth</a> & <a href="#/docs/security/introduction"> Security</a> Concepts.</p>
</div>
<div class="col-md-5 img">
<img src="assets/images/auth-img.png" alt="" class="auth-module-img">
Expand Down
2 changes: 1 addition & 1 deletion docs/app/homepage/homepage.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export class NgdHomepageComponent implements AfterViewInit, OnInit {
}

ngOnInit() {
this.titleService.setTitle('Nebular - full-featured framework based on Angular.');
this.titleService.setTitle('Nebular is a set of essential modules for your next Angular application.');
}

ngAfterViewInit() {
Expand Down
6 changes: 4 additions & 2 deletions docs/articles/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ In simpler words, Nebular is a set of modules (components, services & styles) he

## What's included

What is included:
Nebular modules are distributed as separated `npm` packages, here's a list of currently available:

- **@nebular/theme**
- Theme System - set of SCSS rules, which allow you to modify application looks & feel by changing style-variables, with fewer custom styles.
Expand All @@ -24,7 +24,9 @@ What is included:
- Authentication components (login/register/reset password/restore password).
- Multiple configurable providers (backend connectors).
- Helpers for token management (storing, passing with HTTP requests, etc).
- *@nebular/acl* - module for roles and permissions management. Coming soon.
- **@nebular/security** - module for roles and permissions management.


- *@nebular/dashboard* - module for draggable/resizable dashboards creation. Coming soon.
- *@nebular/data* - application data & state management. Coming soon.
- **Admin dashboard starter kit <a href="https://github.com/akveo/ngx-admin" target="_blank">ngx-admin</a>** - application based on Nebular modules with beautiful IOT components.
Expand Down
221 changes: 221 additions & 0 deletions docs/articles/security-acl-configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
## Abstract

Permissions control is a general task when it comes to development of more or less complex web application. Your application may have various roles and resources you need to protect.
ACL (access control list) provides a flexible way of configuring "who can do what against what resource".

In this article we configure a common setup when the app has three roles (`guest`, `user` and `moderator`), the roles have different permissions (`view`, `create`, `remove`)
and the application contains two type of resources that needs to be protected (`news`, `comments`).

## ACL Configuration

Nebular ACL has a simple way of setting it up. When registering a module you can specify a set of ACL rules by simply providing it as a module configuration.

Let's assume that our guest users can only `view` `news` and `comments`, users can do everything as guests, but also can `create` `comments`, and moderators can also `create` and `remove` `news` and `comments`.
Now, let's convert this into an ACL configuration object which Nebular can understand. Open your `app.module.ts` and change the `NbSecurityModule.forRoot()` call as follows:

```typescript

@NgModule({
imports: [
// ...

NbSecurityModule.forRoot({
accessControl: {
guest: {
view: ['news', 'comments'],
},
user: {
parent: 'guest',
create: 'comments',
},
moderator: {
parent: 'user',
create: 'news',
remove: '*',
},
},
}),

],

```
As you can see the configuration is pretty much straightforward, each role can have a list of permissions (view, create, remove) and resources that are allowed for those permissions. We can also specify a `*` resource,
which means that we have a permission againts any resource (like moderators can remove both news and comments).
<hr class="section-end">
## Role Configuration
So far we told Nebular Security what roles-permissions-resources our application has. Now we need to specify how Nebular can determine a role of currently authenticated user.
To do so we need to create a `RoleProvider` with one simple method `getRole`, which returns an `Observable<string>` of a role.
In a simplest form we can provide this service directly in the main module:
```typescript
// ...

import { of as observableOf } from 'rxjs/observable/of';
import { NbSecurityModule, NbRoleProvider } from '@nebular/security';


@NgModule({
imports: [
// ...

NbSecurityModule.forRoot({
// ...
}),

],
providers: [
// ...
{
provide: NbRoleProvider,
useValue: {
getRole: () => {
return observableOf('guest');
},
},
},
],
```
That's easy we have just provided a role, so that Nebular can determine which user is currently accessing the app.
The good thing about this configuration is that it's not tightly coupled with the rest of your authentication flow, which gives you a lot of flexibility over it.
But, in our example the role is "hardcoded", which in the real world app would be dynamic and depend on the current user.
Assuming that you already have `Nebular Auth` module fully configured and functioning based on `JWT` we will adjust the example to retrieve a role from the user token.
Let's create a separate `role.provider.ts` service in order not to put a lot of logic into the module itself:
```typescript
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { map } from 'rxjs/operators/map';

import { NbAuthService, NbAuthJWTToken } from '@nebular/auth';
import { NbRoleProvider } from '@nebular/security';


@Injectable()
export class RoleProvider implements NbRoleProvider {

constructor(private authService: NbAuthService) {
}

getRole(): Observable<string> {
// ...
}
}

```
Now, let's complete the `getRole` method to extract the role from the token:
```typescript
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { map } from 'rxjs/operators/map';

import { NbAuthService, NbAuthJWTToken } from '@nebular/auth';
import { NbRoleProvider } from '@nebular/security';

@Injectable()
export class RoleProvider implements NbRoleProvider {

constructor(private authService: NbAuthService) {
}

getRole(): Observable<string> {
return this.authService.onTokenChange()
.pipe(
map((token: NbAuthJWTToken) => {
return token ? token.getPayload()['role'] : 'guest';
}),
);
}
}
```
So we subscribe to the `tokenChange` observable, which will produce a new token each time authentication change occurres.
Then we simply get a role from a token (for example simplicity, we assume that token payload always has a role value) or return default `guest` value.
Don't worry if your setup does not use Nebular Auth. You can adjust this code to retrieve a user role from any service of your own.
And let's provide the service in the app module:
```typescript
// ...

import { RoleProvider } from './role.provider';
import { NbSecurityModule, NbRoleProvider } from '@nebular/security';


@NgModule({
imports: [
// ...

NbSecurityModule.forRoot({
// ...
}),

],
providers: [
// ...
{ provide: NbRoleProvider, useClass: RoleProvider }, // provide the class
],
```
## Usage
Finally, we can move on to the part where we start putting security rules in our app. Let's assume that we have that `Post Comment` button, that should only be shown to authenticated users (with a role `user`).
So we need to hide the button for guests.
Nebular Security provides us with a simple `*nbIsGranted` conditional directive, which under the hood works as `*ngIf`, showing or hiding a template block based on a user role:
```typescript
@Component({
// ...
template: `
<button *nbIsGranted="['create', 'comments']" >Post Comment</button>
`,
})
export class CommentFormComponent {
// ...
```
We just need to pass a `permission` and some `resource` in order to control the button visibility.
For more advanced use cases, we can directly use the `NbAccessChecker` service. It provides you with `isGranted` method , which returns an `Observable<boolean>` of the ACL check result.
We can adjust our example to utilize it. In your `comment-form.component.ts`, import the `NbAccessChecker` service.
```typescript
import { Component } from '@angular/core';
import { NbAccessChecker } from '@nebular/security';

@Component({
// ...
})
export class CommentFormComponent {

constructor(public accessChecker: NbAccessChecker) { }
}
```
And let's add an `if` statement to the `Post Comment` button, so that it is only shown when permitted:
```typescript
@Component({
// ...
template: `
<button *ngIf="accessChecker.isGranted('create', 'comments') | async" >Post Comment</button>
`,
})
export class CommentFormComponent {
// ...
```
We call `isGranted` method, which listens to the currently provided role and checks it permissions against specified in the ACL configuration.
Moreover, as it listens to the *role change*, it hides the button if authentication gets changed during the app usage.
Same way we can call the `isGranted` method from any part of the app, including router guards and services, which gives us a transparent and flexibly configurable way to manage user access to various resources.
44 changes: 44 additions & 0 deletions docs/articles/security-install.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<div class="note note-info section-end">
<div class="note-title">Note</div>
<div class="note-body">
If you use our [ngx-admin starter kit](#/docs/installation/based-on-starter-kit-ngxadmin-ngxadmin) then you already have the Security module in place.
</div>
</div>

## Installation steps

1) First, let's install the module as it's distributed as an npm package. Security module doesn't have a dependency on Auth or Theme modules, but it is recommended to use them in conjunction.


```bash

npm i @nebular/security
```

2) Import the module:

```typescript

import { NbSecurityModule } from '@nebular/security

```

3) Now, let's register the module in the root module:

```typescript

@NgModule({
imports: [
// ...

NbSecurityModule.forRoot(),

```
Great, at this stage we have installed Nebular Security and ready to configure it.
<hr class="section-end">
## Where to next
- Roles & Permissions [Configuration & Usage](#/docs/security/acl-configuration--usage)
27 changes: 27 additions & 0 deletions docs/articles/security-intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Security is an important part of any adult web application. It is a common task to manage a user access to particular resources.
Unlike the `Nebular Auth`, which provides a way to `authenticate` a user, `Nebular Security` helps you to `authorize` a user to access some of the application resources.

<div class="note note-warning">
<div class="note-title">Warning</div>
<div class="note-body">
Front-end ACL won't resolve all of the security issues and just provides a better user expiriece for your application.
It is essential to duplicate security rules on the back-end side.
</div>
</div>
<hr class="section-end">

## What's included

- ACL roles/permissions/resources configuration
- `RoleProvider` - user role determination, authentication agnostic
- `NbAccessChecker` - a service that checks whether access is granted or not
- `*nbIsGranted` - conditional directive to manager your content visibility


- *Security Decorator* - decorator that manages access to a particular method, coming soon.

<hr class="section-end">

## Where to next

- Security Module [Installation](#/docs/security/installation)
1 change: 1 addition & 0 deletions docs/google46533d2e7a851062.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
google-site-verification: google46533d2e7a851062.html
Loading

0 comments on commit a4da289

Please sign in to comment.