Skip to content

Commit a4da289

Browse files
authored
feature(security): add security module with acl implementation
Closes #164
1 parent 6b93924 commit a4da289

37 files changed

+1705
-56
lines changed

.angular-cli.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@
8282
"assets": [
8383
"assets",
8484
"favicon.ico",
85-
"favicon.png"
85+
"favicon.png",
86+
"google46533d2e7a851062.html"
8687
],
8788
"index": "index.html",
8889
"main": "main.ts",

DEV_DOCS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ We have to:
4545
- theme - `@nebular/theme` npm package, main framework package
4646
- auth - `@nebular/auth` npm package, auth package (login, register, etc)
4747
- icons - `nebular-icons` npm package, cool icons font
48+
- security - `@nebular/security` npm package, security framework package
49+
4850

4951

5052
## Auth // TODO

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ What is included:
1717
- Authentication components (login/register/reset password/restore password).
1818
- Multiple configurable providers (backend connectors).
1919
- Helpers for token management (storing, passing with HTTP requests, etc).
20-
3) [ ] @nebular/acl - module for roles and permissions management
20+
3) [x] @nebular/security
21+
- Roles and permissions management (ACL)
22+
- `*nbIsGranted` conditional directive
2123
4) [ ] @nebular/dashboard - module for draggable/resizable dashboards creation
2224
5) [ ] @nebular/data - application data & state management
2325
6) [x] Admin dashboard starter kit [ngx-admin](http://github.com/akveo/ngx-admin) - application based on Nebular modules with beautiful IOT components.
24-
7) [ ] More great features!
26+
7) [ ] More great features to come!
2527

2628
### Demo Application:
2729

@@ -30,10 +32,10 @@ What is included:
3032

3133

3234
### Use cases
33-
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.
35+
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.
3436

3537
### The purpose
36-
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.
38+
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.
3739

3840
### Documentation
3941
Installation, customization and other useful articles: https://akveo.github.io/nebular

docs/app/homepage/homepage.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
<h1><span>Nebular</span></h1>
4242
<div class="bigger">Set of essential modules for your next Angular application.</div>
4343
<p>Nebular's primary goal is to assemble together and connect the most awesome features and libraries
44-
creating an efficient ecosystem to speed up and simpify the development.</p>
44+
creating an efficient ecosystem to speed up and simplify the development.</p>
4545
<div class="btn-hero-wrap">
4646
<a href="http://akveo.com/ngx-admin?utm_source=nebular_documentation&utm_medium=demo_button" target="_blank" class="btn btn-hero">Demo</a>
4747
<a href="#/docs" class="docs">Documentation</a>
@@ -95,8 +95,8 @@ <h2><span>THEME SYSTEM</span></h2>
9595
<div class="row">
9696
<div class="col-md-7 txt">
9797
<img src="assets/images/decor-img-auth-module.png" class="decor-img-auth-module">
98-
<h2><span>Auth Module</span></h2>
99-
<p>Now front-end authentication layer is just a matter of a configuration. <a href="#/docs/auth/conceptsinstall">Concepts.</a></p>
98+
<h2><span>Auth & Security Module</span></h2>
99+
<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>
100100
</div>
101101
<div class="col-md-5 img">
102102
<img src="assets/images/auth-img.png" alt="" class="auth-module-img">

docs/app/homepage/homepage.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export class NgdHomepageComponent implements AfterViewInit, OnInit {
117117
}
118118

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

123123
ngAfterViewInit() {

docs/articles/index.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ In simpler words, Nebular is a set of modules (components, services & styles) he
1414

1515
## What's included
1616

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

1919
- **@nebular/theme**
2020
- Theme System - set of SCSS rules, which allow you to modify application looks & feel by changing style-variables, with fewer custom styles.
@@ -24,7 +24,9 @@ What is included:
2424
- Authentication components (login/register/reset password/restore password).
2525
- Multiple configurable providers (backend connectors).
2626
- Helpers for token management (storing, passing with HTTP requests, etc).
27-
- *@nebular/acl* - module for roles and permissions management. Coming soon.
27+
- **@nebular/security** - module for roles and permissions management.
28+
29+
2830
- *@nebular/dashboard* - module for draggable/resizable dashboards creation. Coming soon.
2931
- *@nebular/data* - application data & state management. Coming soon.
3032
- **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.
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
## Abstract
2+
3+
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.
4+
ACL (access control list) provides a flexible way of configuring "who can do what against what resource".
5+
6+
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`)
7+
and the application contains two type of resources that needs to be protected (`news`, `comments`).
8+
9+
## ACL Configuration
10+
11+
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.
12+
13+
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`.
14+
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:
15+
16+
```typescript
17+
18+
@NgModule({
19+
imports: [
20+
// ...
21+
22+
NbSecurityModule.forRoot({
23+
accessControl: {
24+
guest: {
25+
view: ['news', 'comments'],
26+
},
27+
user: {
28+
parent: 'guest',
29+
create: 'comments',
30+
},
31+
moderator: {
32+
parent: 'user',
33+
create: 'news',
34+
remove: '*',
35+
},
36+
},
37+
}),
38+
39+
],
40+
41+
```
42+
43+
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,
44+
which means that we have a permission againts any resource (like moderators can remove both news and comments).
45+
<hr class="section-end">
46+
47+
## Role Configuration
48+
49+
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.
50+
To do so we need to create a `RoleProvider` with one simple method `getRole`, which returns an `Observable<string>` of a role.
51+
In a simplest form we can provide this service directly in the main module:
52+
53+
54+
```typescript
55+
// ...
56+
57+
import { of as observableOf } from 'rxjs/observable/of';
58+
import { NbSecurityModule, NbRoleProvider } from '@nebular/security';
59+
60+
61+
@NgModule({
62+
imports: [
63+
// ...
64+
65+
NbSecurityModule.forRoot({
66+
// ...
67+
}),
68+
69+
],
70+
providers: [
71+
// ...
72+
{
73+
provide: NbRoleProvider,
74+
useValue: {
75+
getRole: () => {
76+
return observableOf('guest');
77+
},
78+
},
79+
},
80+
],
81+
```
82+
That's easy we have just provided a role, so that Nebular can determine which user is currently accessing the app.
83+
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.
84+
85+
But, in our example the role is "hardcoded", which in the real world app would be dynamic and depend on the current user.
86+
87+
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.
88+
89+
Let's create a separate `role.provider.ts` service in order not to put a lot of logic into the module itself:
90+
91+
```typescript
92+
import { Injectable } from '@angular/core';
93+
import { Observable } from 'rxjs/Observable';
94+
import { map } from 'rxjs/operators/map';
95+
96+
import { NbAuthService, NbAuthJWTToken } from '@nebular/auth';
97+
import { NbRoleProvider } from '@nebular/security';
98+
99+
100+
@Injectable()
101+
export class RoleProvider implements NbRoleProvider {
102+
103+
constructor(private authService: NbAuthService) {
104+
}
105+
106+
getRole(): Observable<string> {
107+
// ...
108+
}
109+
}
110+
111+
```
112+
113+
Now, let's complete the `getRole` method to extract the role from the token:
114+
115+
```typescript
116+
import { Injectable } from '@angular/core';
117+
import { Observable } from 'rxjs/Observable';
118+
import { map } from 'rxjs/operators/map';
119+
120+
import { NbAuthService, NbAuthJWTToken } from '@nebular/auth';
121+
import { NbRoleProvider } from '@nebular/security';
122+
123+
@Injectable()
124+
export class RoleProvider implements NbRoleProvider {
125+
126+
constructor(private authService: NbAuthService) {
127+
}
128+
129+
getRole(): Observable<string> {
130+
return this.authService.onTokenChange()
131+
.pipe(
132+
map((token: NbAuthJWTToken) => {
133+
return token ? token.getPayload()['role'] : 'guest';
134+
}),
135+
);
136+
}
137+
}
138+
```
139+
140+
So we subscribe to the `tokenChange` observable, which will produce a new token each time authentication change occurres.
141+
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.
142+
143+
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.
144+
145+
146+
And let's provide the service in the app module:
147+
148+
```typescript
149+
// ...
150+
151+
import { RoleProvider } from './role.provider';
152+
import { NbSecurityModule, NbRoleProvider } from '@nebular/security';
153+
154+
155+
@NgModule({
156+
imports: [
157+
// ...
158+
159+
NbSecurityModule.forRoot({
160+
// ...
161+
}),
162+
163+
],
164+
providers: [
165+
// ...
166+
{ provide: NbRoleProvider, useClass: RoleProvider }, // provide the class
167+
],
168+
```
169+
170+
171+
## Usage
172+
173+
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`).
174+
So we need to hide the button for guests.
175+
176+
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:
177+
178+
```typescript
179+
@Component({
180+
// ...
181+
template: `
182+
<button *nbIsGranted="['create', 'comments']" >Post Comment</button>
183+
`,
184+
})
185+
export class CommentFormComponent {
186+
// ...
187+
```
188+
We just need to pass a `permission` and some `resource` in order to control the button visibility.
189+
190+
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.
191+
We can adjust our example to utilize it. In your `comment-form.component.ts`, import the `NbAccessChecker` service.
192+
193+
```typescript
194+
import { Component } from '@angular/core';
195+
import { NbAccessChecker } from '@nebular/security';
196+
197+
@Component({
198+
// ...
199+
})
200+
export class CommentFormComponent {
201+
202+
constructor(public accessChecker: NbAccessChecker) { }
203+
}
204+
```
205+
206+
And let's add an `if` statement to the `Post Comment` button, so that it is only shown when permitted:
207+
208+
```typescript
209+
@Component({
210+
// ...
211+
template: `
212+
<button *ngIf="accessChecker.isGranted('create', 'comments') | async" >Post Comment</button>
213+
`,
214+
})
215+
export class CommentFormComponent {
216+
// ...
217+
```
218+
We call `isGranted` method, which listens to the currently provided role and checks it permissions against specified in the ACL configuration.
219+
Moreover, as it listens to the *role change*, it hides the button if authentication gets changed during the app usage.
220+
221+
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.

docs/articles/security-install.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<div class="note note-info section-end">
2+
<div class="note-title">Note</div>
3+
<div class="note-body">
4+
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.
5+
</div>
6+
</div>
7+
8+
## Installation steps
9+
10+
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.
11+
12+
13+
```bash
14+
15+
npm i @nebular/security
16+
```
17+
18+
2) Import the module:
19+
20+
```typescript
21+
22+
import { NbSecurityModule } from '@nebular/security
23+
24+
```
25+
26+
3) Now, let's register the module in the root module:
27+
28+
```typescript
29+
30+
@NgModule({
31+
imports: [
32+
// ...
33+
34+
NbSecurityModule.forRoot(),
35+
36+
```
37+
38+
Great, at this stage we have installed Nebular Security and ready to configure it.
39+
40+
<hr class="section-end">
41+
42+
## Where to next
43+
44+
- Roles & Permissions [Configuration & Usage](#/docs/security/acl-configuration--usage)

docs/articles/security-intro.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Security is an important part of any adult web application. It is a common task to manage a user access to particular resources.
2+
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.
3+
4+
<div class="note note-warning">
5+
<div class="note-title">Warning</div>
6+
<div class="note-body">
7+
Front-end ACL won't resolve all of the security issues and just provides a better user expiriece for your application.
8+
It is essential to duplicate security rules on the back-end side.
9+
</div>
10+
</div>
11+
<hr class="section-end">
12+
13+
## What's included
14+
15+
- ACL roles/permissions/resources configuration
16+
- `RoleProvider` - user role determination, authentication agnostic
17+
- `NbAccessChecker` - a service that checks whether access is granted or not
18+
- `*nbIsGranted` - conditional directive to manager your content visibility
19+
20+
21+
- *Security Decorator* - decorator that manages access to a particular method, coming soon.
22+
23+
<hr class="section-end">
24+
25+
## Where to next
26+
27+
- Security Module [Installation](#/docs/security/installation)

docs/google46533d2e7a851062.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
google-site-verification: google46533d2e7a851062.html

0 commit comments

Comments
 (0)