#Custom decorator not executing in an event handler (Socket)

41 messages · Page 1 of 1 (latest)

worthy marlin
#

Hello everyone. I'm trying to execute a custom decorator but to no avail. Am I doing something wrong here?

This is the gateway:

`import { UseGuards } from '@nestjs/common';
import {
MessageBody,
SubscribeMessage,
WebSocketGateway,
WebSocketServer,
OnGatewayConnection,
OnGatewayDisconnect,
OnGatewayInit,
} from '@nestjs/websockets';
import { GetAdmin } from 'src/auth/decorators/getAdmin';
import { SocketGuard } from 'src/auth/guard/socket.guard';

@WebSocketGateway({
cors: true,
})
@UseGuards(SocketGuard)
export class MyGateway
implements OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit
{
@WebSocketServer()
server: any;

@SubscribeMessage('getData')
handleInitConnect(@GetAdmin() client: any, @MessageBody() data: string) {
console.log('admin:', client, data);
}

handleConnection() {
console.log('connected');
}

handleDisconnect() {
console.log('disconnected');
}

afterInit() {
console.log('Socket is live');
}
}`

And this is the custom decorator:

`import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const GetAdmin = createParamDecorator(
async (data: unknown, context: ExecutionContext) => {
console.log('GetAdmin decorator executed');
const socket = context.switchToWs();
const client = socket.getClient();
return;
},
);`

I can't even get the console.log in the custom decorator to work.

paper berry
#

e.g

import { UseGuards } from '@nestjs/common';
import {
  MessageBody,
  SubscribeMessage,
  WebSocketGateway,
  WebSocketServer,
  OnGatewayConnection,
  OnGatewayDisconnect,
  OnGatewayInit,
} from '@nestjs/websockets';
import { GetAdmin } from 'src/auth/decorators/getAdmin';
import { SocketGuard } from 'src/auth/guard/socket.guard';

@WebSocketGateway({
  cors: true,
})
export class MyGateway
  implements OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit
{
  @WebSocketServer()
  server: any;

  @SubscribeMessage('getData')
  @UseGuards(SocketGuard)
  handleInitConnect(@GetAdmin() client: any, @MessageBody() data: string) {
    console.log('admin:', client, data);
  }

  handleConnection() {
    console.log('connected');
  }

  handleDisconnect() {
    console.log('disconnected');
  }

  afterInit() {
    console.log('Socket is live');
  }
}
#

if you want to create a global guard on your module for your websocket you can use

#
@Module({
  providers: [
    <list providers here>
    {
      provide: APP_GUARD,
      useClass: SocketGuard
    }
  ]
})
export class SampleModule { }
#

slight caveat to this approach is that this it'll smack all of your requests with that guard

#

unless you make a decorator that deflects what your guard does

worthy marlin
#

Thank you for the suggestions on creating a global guard

paper berry
#

oh wait

#

hold on

#

I read the entire post wrong

#

I'm so sorry lol I thought you were having issues with the socket guard

#
import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const GetUser = createParamDecorator(
  (data: undefined, ctx: ExecutionContext) => {
    const user = ctx.switchToWs().getClient();
    return data ? user.user[data] : user.user;
  },
);
paper berry
worthy marlin
paper berry
#

May I ask what are you trying to do with this @GetAdmin() decorator?

#

are you trying to extract something out of the user object?

worthy marlin
paper berry
#

could we possibly avoid this by adding roles to the user? and throwing those into the token?

#

i.g

req.user = {
  id: string;
  roles: ['admin' | 'basic']
}
#

simple example but I feel like it gets the point across

#

and checking for that admin role

worthy marlin
paper berry
#

you're not necessarily doing something wrong

#

but you could store your admin role or any type of identifier to tell your application what user is trying to access this endpoint/socket and when your SocketGuard parses the token it can read it and if it contains that identifier your GetAdmin can pick up that piece of data

#

and if they aren't an admin you can throw an error or handle it however

#

Cause these private/public keys seem much more on the lines of just having basic roles

#

where a user could be a basic, premium, or admin

#

and they all use the same keys but each user has a specific role attached to their user object that stays with them until they upgrade or get downgraded or however your role system works

paper berry
worthy marlin
paper berry
#

ohhhhh that makes a lot more sense

#

hmmm I honestly don't know if you can make a request like that in the param decorator like that

#

you can possibly just add a statement before the actual guts of your your process that checks who they stay they are and if they aren't you can throw an error

#

I think this is the best solution I can come up with

#

as you can't really inject a database call into a param decorator

worthy marlin
#

I've done that in the socket guard. I just want to understand why the custom decorator won't execute at all (removing everything inside, leaving only console.log). As for what I intended for the custom decorator, I'm doing that in the socket guard now by adding the result of the query to the socket context and accessing it from the @connectedSocket decorator

paper berry
#

ahhh I see

#

well I can't help you there as I don't know why your Param decorator won't fire that console.log

#

happy coding