2017-08-04 69 views
0

根据这一tutorial我尝试实现定制的装饰在让我们限制访问用户角色组件类基础失败。否则重定向到其他组件(我知道它有其他策略来存档,但它不适合我们的用例)。角注射时添加自定义类装饰

它作为我方面,,但只有当我在本地机器上运行而不是在部署服务器。错误就像它不能在每个组件的构造函数中注入任何服务或类使用这个装饰器?

角色required.decorator.ts

export function RoleRequired(roles: string[], redirectUrl = '/forbidden') { 

    return function<T extends {new(...args:any[]):{}}> (constructor:T) { 

     // save a reference to the original constructor 
     const original = constructor; 

     // a utility function to generate instances of a class 
     function construct(constructor, args) { 
      const c : any = function() { 
       return constructor.apply(this, args); 
      }; 
      c.prototype = constructor.prototype; 
      return new c(); 
     } 

     // the new constructor behaviour 
     const f : any = function(router: Router, ...args) { 
      console.log("Class: " + original.name); 
      this.__verifyRole = JSON.parse(localStorage.getItem("roles")) || []; 

      const that = this; 
      const isGrant = roles.every((item, index) => { 
       return that.__verifyRole.indexOf(item) != -1 
      }); 

      if (!isGrant) { 
       router.navigate([redirectUrl]); 
      } 

      return construct(original, args); 
     }; 

     // copy prototype so intanceof operator still works 
     f.prototype = original.prototype; 

     // copy metadata to new constructor 
     let metadatakeys = Reflect.getMetadataKeys(constructor); 
     metadatakeys.forEach(function (key) { 
      Reflect.defineMetadata(key, Reflect.getOwnMetadata(key, constructor), f) 
     }); 

     // read dependencies list from 'cls', add our own dependency, and write list to 'newCls' 
     let dependencies = Reflect.getOwnMetadata('design:paramtypes', constructor); 
     dependencies = [Router].concat(dependencies); 
     Reflect.defineMetadata('design:paramtypes', dependencies, f); 

     // return new constructor (will override original) 
     return f; 
    } 
} 

PREREQUISITE

进口该类在app.module.ts 进口 '反映的元数据';

USAGE

@RoleRequired(['role.user.chat']) 
export class ChatRoomComponent {} 

错误消息是注入的类时启动组件的所有属性。

ERROR TypeError: Cannot read property 'informSoundSettingChange' of undefined

的package.json

{ 
    "name": "alpha-love-chat-ng", 
    "version": "1.0.0", 
    "license": "MIT", 
    "angular-cli": {}, 
    "scripts": { 
    "ng": "ng", 
    "start": "ng serve --deploy/--proxy-config proxy.conf.json", 
    "build": "ng build --prod --aot output-hashing none --deploy /", 
    "test": "ng test", 
    "lint": "ng lint", 
    "e2e": "ng e2e" 
    }, 
    "private": true, 
    "dependencies": { 
    "@angular/animations": "^4.2.6", 
    "@angular/cdk": "^2.0.0-beta.8", 
    "@angular/common": "^4.2.6", 
    "@angular/compiler": "^4.2.6", 
    "@angular/core": "^4.2.6", 
    "@angular/forms": "^4.2.6", 
    "@angular/http": "^4.2.6", 
    "@angular/material": "^2.0.0-beta.8", 
    "@angular/platform-browser": "^4.2.6", 
    "@angular/platform-browser-dynamic": "^4.2.6", 
    "@angular/router": "^4.2.6", 
    "angular-datatables": "^4.1.1", 
    "angular2-notifications": "^0.7.4", 
    "angular2-uuid": "^1.1.1", 
    "bootstrap": "^3.3.7", 
    "core-js": "^2.4.1", 
    "datatables.net": "^1.10.15", 
    "datatables.net-dt": "^1.10.15", 
    "howler": "^2.0.4", 
    "jquery": "^3.2.1", 
    "lz-string": "^1.4.4", 
    "malihu-custom-scrollbar-plugin": "^3.1.5", 
    "moment": "^2.18.1", 
    "moment-timezone": "^0.5.13", 
    "ng2-modal": "0.0.25", 
    "ngx-facebook": "^2.4.0", 
    "ngx-infinite-scroll": "^0.5.1", 
    "reflect-metadata": "^0.1.10", 
    "rxjs": "^5.4.2", 
    "rxjs-extra": "^0.1.1", 
    "signalr": "^2.2.2", 
    "underscore": "^1.8.3", 
    "zone.js": "^0.8.4" 
    }, 
    "devDependencies": { 
    "@angular/cli": "^1.2.0", 
    "@angular/compiler-cli": "^4.2.6", 
    "@angular/language-service": "^4.2.6", 
    "@types/bootstrap": "^3.3.34", 
    "@types/datatables.net": "^1.10.4", 
    "@types/howler": "^2.0.2", 
    "@types/jasmine": "2.5.45", 
    "@types/jquery": "^3.2.6", 
    "@types/lz-string": "^1.3.32", 
    "@types/moment": "^2.13.0", 
    "@types/moment-timezone": "^0.2.34", 
    "@types/node": "^6.0.80", 
    "codelyzer": "~3.0.1", 
    "jasmine-core": "~2.6.2", 
    "jasmine-spec-reporter": "~4.1.0", 
    "karma": "~1.7.0", 
    "karma-chrome-launcher": "~2.1.1", 
    "karma-cli": "~1.0.1", 
    "karma-coverage-istanbul-reporter": "^1.2.1", 
    "karma-jasmine": "~1.1.0", 
    "karma-jasmine-html-reporter": "^0.2.2", 
    "protractor": "~5.1.2", 
    "ts-node": "~3.0.4", 
    "tslint": "~5.3.2", 
    "typescript": "~2.3.3" 
    } 
} 
+0

什么是错误?你在使用AOT吗? – n00dl3

+0

是的,我使用AOT,错误是它的属性未定义在每个服务类。 –

+1

认真我担心这是一个AOT限制......我猜它创建在构建时注入逻辑,所以你不能使用你的装饰启用AOT ... – n00dl3

回答

0

据@ n00dl3建议在评论..

Seriously I fear this is an AOT limitation... I guess it creates the injection logic at build time so you can't use your decorator with AOT enabled..

不过,我尝试,它不是在第一个工作,因为..

"ng build --prod --aot output-hashing none --deploy /"

我只是删除--aot,但我仍然有这个标志--prod左,默认情况下它将使--aot true所以我修复由--aot falsegithub.com/angular/angular-cli/wiki/build

最终版本

"ng build --prod --aot false output-hashing none --deploy /"

,而不是

"ng build --prod output-hashing none --deploy /"

总结删除 - 无标志解决我的问题,防止它删除我的自定义装饰。