Is it possible for decorators to invoke services within an Angular application?

Recently, I've delved into exploring decorators for TypeScript. Angular showcases a wide array of decorators like Components, Injectables, Directives, and more. I find myself frequently repeating a logic block that checks if a user is logged in and authorized to perform a specific function. Here's an example:

@Component()
class MyClass {
    someMethod() {
         if(this.authService.isLogged() && this.authService.isAuth(...)) { 
             // implementation
         }
    }
}

While this approach works, it can be quite cumbersome to read and not very intuitive for my colleagues. My goal is to create a decorator that first validates if a user is logged in, then checks their authorization status. If both conditions are met, the function should execute; otherwise, it should bypass execution and return a default value. Here's what I came up with for the login verification function:

export function isLogged() {
    return (target, key, descriptor) {
        const original = descriptor.value;
        descriptor.value = function (...args: any[]) {
            // <- implement login validation here
            return original.apply(this, args);
        };
        return descriptor;
    }
}

The challenge I'm currently facing is how to access the context services within the function to verify the user's login status without explicitly passing the 'this' keyword. To illustrate, this is the usage scenario I want to achieve:

@Component()
class MyClass {
    @isAuth(...) // <- here without requiring 'this'
    @isLogged()
    someMethod() {
        // implementation
    }
}

I must stress that this decorator must rely on an authorization service for verification logic as it contains essential user login information and authorities required by the decorator. One possible solution to my query involves injecting services into designated functions. In the example decorator provided, there is a placeholder comment indicating where the call to the authorization service would fit in. While I believe there is a method to inject and invoke a service within a function, I haven't discovered any solutions online.

Answer №1

After receiving feedback on my question, it was brought to my attention that the this keyword actually contains the complete context of the class, including services defined in its constructor. This allows me to update my decorator in order to access the service:

export function checkAuthorization() {
    return (target, key, descriptor) {
        const original = descriptor.value;
        descriptor.value = function (...args: any[]) {
            if (this.authorizationService.isAuthorized()) {
                return original.apply(this, args);
            } else {
                return () => {};
            }
        };
        return descriptor;
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Following an Angular update, the npm installation process encounters issues due to conflicts related to peer dependencies

I am facing challenges with updating my Angular version. When I try to use the command ng update, the output I receive is as follows: Name Version Command to update ------------------------------ ...

What could possibly be causing routing issues in Angular 2?

Can anyone explain to me why the routing feature is not functioning properly in Angular 2? I am attempting to display a component when the URL path is empty. Below is the code snippet: http://plnkr.co/edit/Vgc2bB7Lc8h9XsuhIg6X?p=preview import { NgModul ...

Preserve data even after refreshing the browser in Angular

Is there a reliable method to preserve my data after refreshing my browser? I've experimented with rxjs behavior subject, but it hasn't worked for me. I prefer not to use local/session storage due to security concerns and best practices, especia ...

Leveraging external modules within Angular 2 to enhance component functionality

I have developed a custom module called ObDatePickerModule, which includes a directive. In addition, I have integrated the ObDatePickerModule into a project by including it in the dependencies section of the package.json. Now, I am importing Module A i ...

Guide on moving elements to a different list with the help of the Angular DragDrop CDK Service

I encountered a unique situation while working on my project where I needed to implement a drag and drop feature for multiple lists using Angular CDK's DragDrop service. While I was able to successfully move items within a single list, transferring an ...

Error: User authentication failed: username: `name` field is mandatory

While developing the backend of my app, I have integrated mongoose and Next.js. My current challenge is implementing a push function to add a new user to the database. As I am still relatively new to using mongoose, especially with typescript, I am followi ...

Deactivate user session in LoopBack 4 API

Can anyone provide a clear example of an API endpoint for logging out that allows for deleting the token stored during login instead of relying on the web browser? It seems there is no documentation available on how LoopBack generates a default user when ...

Developing front-end libraries using the jspm workflow

What is the best way to convert a library written in TypeScript to ES5? While JSPM documentation focuses on web apps (such as with jspm bundle-sfx), the information I've found on Google seems more suited for a web app workflow rather than a library w ...

TypeScript test framework for testing API calls in VS Code extensions

My VS Code extension in TypeScript uses the Axios library for API calls. I have written tests using the Mocha framework, which are run locally and through Github Actions. Recently, I integrated code coverage reporting with `c8` and I am looking to enhanc ...

Testing the unit with a customized header in the interceptor

I've been struggling to execute a unit test within an Angular 6 interceptor, but despite numerous attempts, I keep encountering the following error: Error: Expected one matching request for criteria "Match by function: ", found none. I'm rela ...

The nested fields in PayloadCMS GraphQL are appearing as null

When using the PayloadCMS GraphQL plugin, I encountered an issue with the type: "relationship" fields always returning null, no matter what I tried. My goal is to create a simple blog without any complexities. Despite reaching out for help in the ...

Angular 7: Resetting multiple dynamically generated checkboxes back to their original state with the click of a button

I have created a child component that contains 3 checkboxes, generated dynamically using ngFor, along with Apply and Cancel buttons. In the parent template, I include the selector tag for the child component. The parent component accesses this child compo ...

How to Retrieve Superclass Fields in Angular 5 Component

I have a superclass that provides common functionality for components. export class AbstractComponent implements OnInit { public user: User; constructor(public http: HttpClient) { } ngOnInit(): void { this.http.get<User>(& ...

Guide for implementing conditional fragment and its value into an anchor HTML tag using Angular 5

I am currently retrieving menus from a service and need to conditionally include a fragment in an anchor tag. The issue I am facing is that when the fragment is empty, it still adds a '#' to the URL which I want to avoid. Take a look at the HTML ...

What are the pros and cons of developing traditional node modules using ES6 in conjunction with a babel workflow?

When working on front-end code for web browsers, I often rely on the es2017 preset to transpile my code into a distribution bundle, taking advantage of the transformers included. For traditional modules, I typically follow the requirements specified by the ...

Can classes be encapsulated within a NgModule in Angular 2/4?

Looking to organize my classes by creating a module where I can easily import them like a separate package. Take a look at this example: human.ts (my class file) export class Human { private numOfLegs: Number; constructor() { this.numOfLegs = 2 ...

What could be causing the excessive number of connections in my MongoDB instance?

This code snippet is crucial for my initial connection setup let cachedDbConnection: Db export async function establishDatabaseConnection(): Promise<{ db: Db }> { if (cachedDbConnection) { return { db: cachedDbConnection } } const client ...

"Error encountered: Route class unable to reach local function in TypeScript Express application" #codingissues

Experiencing an 'undefined' error for the 'loglogMePleasePlease' function in the code snippet below. Requesting assistance to resolve this issue. TypeError: Cannot read property 'logMePleasePlease' of undefined This error ...

Encountering difficulty in retrieving value through the get method, resorting to interpolation. The value from the getTitle() method for 'this._title' is not being displayed

import { Component } from '@angular/core'; @Component({ selector: 'courses', template: '<h1>{{ getTitle() }}</h1>' ////issue with not displaying 'this._title' value??? }) export class CoursesCo ...

Using Google OAuth2Client with Angular 4

I am encountering an issue while trying to verify the ID token for my client using Google's example. You can find the example code here. const {OAuth2Client} = require('google-auth-library'); // <-- facing issues here const client = new ...