Is there a way to insert current user into fields in base entity before inserting data

Viewed 162

How to to insert current logged in user to createdBy & lastChangedBy fields after creating/updating entity?

In my BaseEntity i've tried

  @BeforeInsert()
  async insertUser(@GetAuthUserPayload() userPayload: User) {
    const user = await this.usersService.findOne({
      where: { username: userPayload.username },
    });
    this.createdBy = user;
    this.lastChangedBy = user;
  }

But i've found out decorators work only in controllers(in entity they return undefined). Is there any other way than updating DTO in controller or using session?

1 Answers

Since i am using @nestjsx/crud i haven't found any other method than updating DTO. I've managed to solve this issue by creating BaseService:

import { TypeOrmCrudService } from '@nestjsx/crud-typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { Inject, Injectable, Scope, Type } from '@nestjs/common';
import { CrudRequest, Override } from '@nestjsx/crud';
import { DeepPartial } from 'typeorm';
import { REQUEST } from '@nestjs/core';
import { User } from '../users/entities/user.entity';

export interface IBaseService<T> {}

type Constructor<I> = new (...args: any[]) => I;

export function BaseService<T>(entity: Constructor<T>): Type<IBaseService<T>> {
  @Injectable({
    scope: Scope.REQUEST,
  })
  class BaseServiceHost extends TypeOrmCrudService<T> implements IBaseService<T> {
    constructor(@InjectRepository(entity) repo, @Inject(REQUEST) readonly request: any) {
      super(repo);
    }

    @Override()
    createOne(req: CrudRequest, dto: DeepPartial<T>): Promise<T> {
      return super.createOne(req, this.addCreatedByToDTO(dto));
    }

    @Override()
    replaceOne(req: CrudRequest, dto: DeepPartial<T>): Promise<T> {
      return super.replaceOne(req, this.addLastChangedByToDTO(dto));
    }

    @Override()
    updateOne(req: CrudRequest, dto: DeepPartial<T>): Promise<T> {
      return super.updateOne(req, this.addLastChangedByToDTO(dto));
    }

    private addCreatedByToDTO(dto: DeepPartial<T>): DeepPartial<T> {
      const userUUID: Partial<User> = this.request.user.userUUID;
      return { ...dto, createdBy: userUUID };
    }

    private addLastChangedByToDTO(dto: DeepPartial<T>): DeepPartial<T> {
      const userUUID: Partial<User> = this.request.user.userUUID;
      return { ...dto, lastChangedBy: userUUID };
    }
  }

  return BaseServiceHost;
}

Later on i just extend my service like:

@Injectable()
export class ExampleService extends BaseService(ExampleEntity) {}
Related