Passed
Pull Request — master (#65)
by
unknown
02:01
created

RoleRbac.can   F

Complexity

Conditions 14

Size

Total Lines 54
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 39
dl 0
loc 54
rs 3.6
c 0
b 0
f 0
cc 14

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like RoleRbac.can often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import { Injectable } from '@nestjs/common';
2
import { IRoleRbac } from './interfaces/role.rbac.interface';
3
import { IFilterPermission } from '../permissions/interfaces/filter.permission.interface';
4
import { IParamsFilter } from '../params-filter/interfaces/params.filter.interface';
5
6
@Injectable()
7
export class RoleRbac implements IRoleRbac {
8
9
  constructor(
10
    private readonly role: string,
11
    private readonly grant: string[],
12
    private readonly filters: object,
13
    private readonly paramsFilter?: IParamsFilter,
14
  ) {
15
  }
16
17
  async can(...permissions: string[]): Promise<boolean> {
18
    if (!permissions.length) {
19
      return false;
20
    }
21
    // check grant
22
    for (const permission of permissions) {
23
      if (!this.grant.includes(permission)) {
24
        return false;
25
      }
26
    }
27
28
    // check custom filter
29
    for (const permission of permissions) {
30
      // check particular permission [permission@action]
31
      if (
32
        this.grant.includes(permission)
33
        && permission.includes('@')
34
      ) {
35
        const filter: string = permission.split('@')[1];
36
        const filterService: IFilterPermission = this.filters[filter];
37
        const isGranted = filterService ? await Promise.resolve(
38
          filterService.can(
39
            this.paramsFilter ? this.paramsFilter.getParam(filter) : null,
40
          )
41
        ) : false;
42
43
        if (filterService && !isGranted) {
44
          return false;
45
        }
46
      }
47
      // check particular permission [permission]
48
      if (this.grant.includes(permission)
49
        && !permission.includes('@')) {
50
51
        for (const filter in this.filters) {
52
          if (
53
            this.filters.hasOwnProperty(filter) &&
54
            this.grant.includes(`${permission}@${filter}`)
55
          ) {
56
            const isGranted = await Promise.resolve(
57
              this.filters[filter].can(
58
                this.paramsFilter ? this.paramsFilter.getParam(filter) : null,
59
              )
60
            );
61
            if (!isGranted) {
62
              return false;
63
            }
64
          }
65
        }
66
      }
67
    }
68
69
    return true;
70
  }
71
}
72