在 TypeScript / Angular 中注入依赖项到原型

Inject dependencies in TypeScript / Angular to prototype

我是 TypeScript 和 Angular 7 的新手,我正在努力实现菜单的某些组件显示用户是否已被授予对它们的权限(JWT 令牌包含一个角色)。

我的想法是重用我拥有的 GuardServices 并在过滤器循环中调用方法 canActivate,以便返回的菜单是根据用户角色显示的菜单。

@Component({
    selector: 'app-root',
    templateUrl: 'app.component.html',
    styleUrls: ['./app.component.scss']
})
export class AppComponent {
    public appPages = [
        {
            title: 'Dashboard',
            url: '/app/dashboard',
            icon: 'home'
        },
        {...},
        
        {
            title: 'Employees',
            url: '/app/employees',
            icon: 'contacts',
            guard: AdminGuardService
        },
        {
            title: 'Logout',
            url: '/app/logout',
            icon: 'log-out'
        }
    ];

    public authenticated = false;
    public position = 'end';

    constructor(
        private platform: Platform,
        private splashScreen: SplashScreen,
        private statusBar: StatusBar,
        private router: Router,
        private auth: AuthenticationService
    ) {
        this.initializeApp();
    }

    initializeApp() {
        (...)
    }

    getAppPages(): any {
        return this.appPages.filter(page => {
            if (page.guard != null) {
                page.guard.prototype.auth = this.auth;
                return page.guard.prototype.canActivate();
            }
            return true;
        });
    }
}

基本上我在这里手动注入 AdminGuardService 需要的 authService。将来我可能需要具有其他依赖项的其他服务,并且此方法根本不可扩展。所以我想将依赖项的注入委托给 Angular 并只调用 canActivate() 方法。

@Injectable({
    providedIn: 'root'
})
export class AdminGuardService implements CanActivate {

    constructor(public auth: AuthenticationService) {
    }

    canActivate(): boolean {
        return this.auth.isAuthenticated() && (this.auth.roles.includes('Admin') || this.auth.roles.includes('UserAdmin'));
    }
}

谢谢!

根据您的最终目标,有多种方法可以解决这个问题。

如果您想在您的身份验证更改时更新这些,那么您可以将其变成可观察对象,订阅它,并过滤用户有权访问的路径。如果您使用 observable,那么您的 html 可以异步项目并在适当的时候更新。 I love this site 几乎每次去都能学到新东西。这种方法是我在使用 Firebase 身份验证并具有 roles/teams/public/private 等

时对更改做出反应的方式

或者,如果您只关心应用初始化阶段,您可以创建一个可注入令牌(通过工厂 useFactory 提供),或者使用 APP_INITIALIZERs 并为提供者提供工厂方法你需要。 See more on useFactory.

我设法通过注入 Angular 的默认注入器并使用它获取 class 的实例来解决问题。:

import {Injector} from '@angular/core';

constructor(
    ...
    private injector: Injector
) {
    this.initializeApp();
}


getAppPages(): any {
    return this.appPages.filter(page => {
        if (page.guard != null) {
            return this.injector.get(page.guard).canActivate();
        }
        return true;
    });
}