在edit内调用edit函数导致node.js无限循环

时间:2020-10-31 13:30:42

标签: node.js mongodb typescript mongoose mongoose-schema

//src/users/users.service.ts
import { Injectable, BadRequestException } from "@nestjs/common";
import { InjectModel } from "@nestjs/mongoose";
import { Model } from "mongoose";
import { plainToClass } from "class-transformer";
import { BaseService } from "../common/base/base.service";
import { IUser, User } from "./objects/user.schema";
import { EmailService } from "../email/email.service";
import {
  HasPostCreate,
  HasPreCreate,
  HasPostUpdate,
  HasPreUpdate,
} from "../common/base/pre.post.action";
import { EmailDto } from "../email/objects/email.dto";
import {
  UserRegisteredEmailForSponsor,
  UserRegisteredEmailForSme,
  LoginCredentialEmail,
  KycApprovedforSme,
  KycApprovedforSponsor,
  KycRejectedforSme,
  KycRejectedforSponsor,
  KycPendingEmail,
} from "./objects/user.registered.email";
import { JwtService } from "@nestjs/jwt";
import {
  JWT_EXPIRY,
  CRM_URL_HEADERS,
  BIGCHAINDB_API_PATH,
} from "../common/constants/config";
import { EntityDetailsService } from "../entity-details/entity-details.service";
import {
  CreateEntityDetailsDto,
  EntityDetailsDto,
} from "../entity-details/objects/entity-details.dto";
import { IEntityDetails } from "../entity-details/objects/entity-details.schema";
import { UserDto, CreateUserDto } from "./objects/create-user.dto";
import { crmDto } from "./objects/userCrm.dto";
import {
  USER_TYPES,
  ACTIVITY_FEED_EVENTS_SPONSOR,
  ACTIVITY_FEED_EVENTS_SME,
  KYC_VERIFICATION_STATUS,
  USER_STATUS,
  SME,
  INVESTOR,
  BIGCHAINDB_TRANSACTION_TYPE,
  ROLES_ACCESS_ACTION,
} from "../common/constants/enum";
import { SetFormattedId } from "../common/base/set.formattedId";
import { OtpService } from "../auth/otp/otp.service";
import * as request from "request-promise-native";
import * as cloneDeep from "lodash.clonedeep";
import { AnyFilesInterceptor } from "@nestjs/platform-express";
import { CanLoadVirtual } from "../common/interfaces/can.load.virtual";
import { IsBoolean } from "class-validator";
import { json } from "express";
import { IamUser } from "aws-sdk/clients/macie2";
import { IamUserArn } from "aws-sdk/clients/codedeploy";
import { CRM_URL_HEADERS_UPDATE } from "../common/constants/config";
import { CrmService } from "./crm/crm.service";
import { EmailNotificationService } from "./email-notification/email-notification.service";
import { result } from "lodash";
import { ActivityFeedService } from "../activity-feed/activity-feed.service";
import { UpdateBlogDTO } from "../blog/objects/blog.dto";
import { SmeActivityFeedService } from "../sme-activity-feed/sme-activity-feed.service";
import {
  KYC_PENDING_STATUS_CHANGE_ERROR,
  KYC_PENDING_STATUS_CHANGE_ERROR_WITH_ONBOARDING_FALSE,
  KYC_APPROVED_STATUS_CHANGE_ERROR,
  KYC_REJECTED_STATUS_CHANGE_ERROR,
  USER_KYC_INCOMPLETE_STATUS_CHANGE_ERROR,
  USER_CLOSED_STATUS_CHANGE_ERROR,
  USER_IN_REVIEW_STATUS_CHANGE_ERROR,
  USER_ACTIVE_STATUS_CHANGE_ERROR,
} from "../common/constants/string";

import { generateKeyPair } from "crypto";
import { BigchainDbService } from "../bigchain-db/bigchain-db.service";
import { type } from "os";
import { RolesService } from "../roles/roles.service";

export function delay(ms: number) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}


@Injectable()
export class UsersService extends BaseService<IUser>
  implements
    HasPreCreate,
    HasPostCreate,
    HasPreUpdate,
    HasPostUpdate,
    CanLoadVirtual {
  constructor(
    @InjectModel("User") private readonly userModel: Model<User>,
    private emailService: EmailService,
    private jwtService: JwtService,
    private entityDetailsService: EntityDetailsService,
    private otpService: OtpService,
    private crmService: CrmService,
    private emailnotificationService: EmailNotificationService,
    private activityFeedService: ActivityFeedService,
    private smeactivityFeedService: SmeActivityFeedService,
    private bigchaindbService: BigchainDbService,
    private rolesservice: RolesService
  ) {
    super(userModel);
  }






 async doPostCreate(user: IUser): Promise<void> {
  let update = { forcePasswordChange: true };
    await this.edit(user.code, {
      verification: update,
    });
 }

 async doPostUpdate(idOrCode, model) {
  /*
  let update = { forcePasswordChange: true };
    await this.edit(user.code, {
      verification: update,
    });
    */
  let result = await this.emailnotificationService.edit(notify.code, {
        isKycApproved: false,
        isKycRejected: false,
        isKycPending: true,
      });
 }
//src/users/objects/user.schema.ts
  export const UserSchema: Schema = createModel("Users", {
       verification: {
    mobile: {
      type: Boolean,
      default: true,
    },
    email: {
      type: Boolean,
      default: true,
    },
    isProfileCompleted: {
      type: Number,
      enum: Object.values({ ...KYC_VERIFICATION_STATUS }),
      default: KYC_VERIFICATION_STATUS.PENDING,
    },
    isOnboardingComplete: {
      type: Boolean,
      default: false,
    },
    forcePasswordChange: {
      type: Boolean,
      default: false,
    },
  }
  });
//src/users/email-notification/email-notification.schema.ts
export const EmailNotificationSchema: Schema = createModel(
  "EmailNotification",
  {
    isOnboardingInitiated: { type: Boolean, default: false },
    isKycApproved: { type: Boolean, default: false },
    isKycRejected: { type: Boolean, default: false },
    isKycPending: { type: Boolean, default: false },
    isDocumentsSubmitted: { type: Boolean, default: false },
    project: {
      isProjectCreated: { type: Boolean, default: false },
      isProjectPending: { type: Boolean, default: false },
      isProjectApproved: { type: Boolean, default: false },
      isProjectRejected: { type: Boolean, default: false },
    },
    creator: { type: String },
  }
);
// src/common/base/base.controller.ts
import {
  Body,
  Delete,
  Get,
  Post,
  Put,
  Request,
  UseInterceptors,
  NotFoundException,
  Query,
} from "@nestjs/common";
import { AbstractControllerOptions } from "./base.interface";
import { AbstractClassTransformerPipe } from "../pipes/class-transformer.pipe";
import { plainToClass } from "class-transformer";
import { ApplicationExceptionInterceptor } from "../application.interceptor";
import {
  IdOrCodeParser,
  LastUpdatedTime,
  RequestUser,
} from "../utils/controller.decorator";
import { BaseService } from "./base.service";
import { IEntity } from "./base.model";
import { success } from "./httpResponse.interface";
import { BASEROUTES, Status } from "../constants/enum";
import { createMongoSearchQuery } from "../utils/helper";
import {
  normalizePaginateResult,
  normalizePagination,
  Paginate,
} from "../interfaces/pagination";
import * as dot from "dot-object";

export function abstractBaseControllerFactory<T>(
  options?: AbstractControllerOptions<T>
): any {
  const { DTO, CreateDTO, UpdateDTO, DisabledRoutes } = options;

  const routeAvailability = (routeTag: number): void => {
    if (DisabledRoutes && DisabledRoutes.includes(routeTag)) {
      throw new NotFoundException();
    }
  };

  @UseInterceptors(ApplicationExceptionInterceptor)
  abstract class AbstractController {
    protected _service: BaseService<IEntity>;

    protected constructor(service: any) {
      this._service = service;
    }


    @Put(":idOrCode")
    public async update(
      @IdOrCodeParser("idOrCode") idOrCode: string,
      @LastUpdatedTime() lastUpdatedTime: number,
      @Body(AbstractClassTransformerPipe(UpdateDTO)) updateDto,
      @RequestUser() user
    ) {
      if (user) {
        updateDto.updatedBy = user.code;
      }
      routeAvailability(BASEROUTES.UPDATEONE);
      let data = await this._service.edit(
        idOrCode,
        updateDto,
        lastUpdatedTime,
        user
      );
      data = plainToClass(DTO, data, { excludeExtraneousValues: true });
      return success(data);
    }

    @Delete(":idOrCode")
    public async delete(@IdOrCodeParser("idOrCode") idOrCode: string) {
      routeAvailability(BASEROUTES.DETELEONE);
      let data = await this._service.remove(idOrCode);
      data = plainToClass(DTO, data, { excludeExtraneousValues: true });
      return success(data);
    }
  }
  return AbstractController;
}
//src/common/base/base.service.ts
import { NotFoundException } from "@nestjs/common";
import { Model } from "mongoose";
import * as moment from "moment";
import { APP_ENV, Status } from "../constants/enum";
import { NODE_ENV } from "../constants/config";
import { NOT_FOUND, NOT_SYNCED } from "../constants/string";
import { UniqueValidator } from "../validator/unique.validator";
import * as _ from "lodash";
import * as flatter from "flat";

import {
  HasPreCreate,
  HasPostCreate,
  HasPreUpdate,
  HasPostUpdate,
  HasPreDelete,
  HasPostDelete,
  HasPreGetAll,
} from "./pre.post.action";
import { SetFormattedId, getFormatedId } from "./set.formattedId";
import { CanLoadVirtual } from "../interfaces/can.load.virtual";
import { Paginate } from "../interfaces/pagination";
import { User } from "src/users/objects/user.schema";
export abstract class BaseService<T> extends UniqueValidator {
  private PreCreate = !!(<HasPreCreate>(<any>this)).doPreCreate
    ? <HasPreCreate>(<any>this)
    : null;
  private PreGetAll = !!(<HasPreGetAll>(<any>this)).doPreGetAll
    ? <HasPreGetAll>(<any>this)
    : null;
  private PostCreate = !!(<HasPostCreate>(<any>this)).doPostCreate
    ? <HasPostCreate>(<any>this)
    : null;
  private PreUpdate = !!(<HasPreUpdate>(<any>this)).doPreUpdate
    ? <HasPreUpdate>(<any>this)
    : null;
  private PostUpdate = !!(<HasPostUpdate>(<any>this)).doPostUpdate
    ? <HasPostUpdate>(<any>this)
    : null;
  private PreDelete = !!(<HasPreDelete>(<any>this)).doPreDelete
    ? <HasPreDelete>(<any>this)
    : null;
  private PostDelete = !!(<HasPostDelete>(<any>this)).doPostDelete
    ? <HasPostDelete>(<any>this)
    : null;
  private CanLoadVirtual = !!(<CanLoadVirtual>(<any>this)).getVirtualForItem
    ? <CanLoadVirtual>(<any>this)
    : null;
  private SetFormattedId = !!(<SetFormattedId>(<any>this)).getPrefixForId
    ? <SetFormattedId>(<any>this)
    : null;

  private readonly validVirtual = [];

  protected constructor(baseModel: Model) {
    // debugger;
    super(baseModel);

    this.setVirtual();
  }
 async edit(
    idOrCode: string,
    editDto: any,
    lastUpdatedTime?: number,
    user?: any
  ) {
    debugger;
    await this.validate(editDto, idOrCode);
    let model = await this.findOne(idOrCode);
    if (
      NODE_ENV !== APP_ENV.development &&
      !moment(model.updatedTime).isSame(moment(lastUpdatedTime))
    ) {
      // throw new Error(NOT_SYNCED);
    }

    if (this.PreUpdate) {
      debugger;
      await this.PreUpdate.doPreUpdate(idOrCode, editDto, model, user);
    }

    editDto = flatter.flatten(editDto);
    await this.baseModel.updateOne(
      {
        code: model.code,
      },
      {
        $set: {
          ...editDto,
        },
      }
    );
    model = await this.findOne(idOrCode);
    if (this.PostUpdate) {
      debugger;
      await this.PostUpdate.doPostUpdate(idOrCode, model, user);
    }
    return model;
  }
}

编辑功能包含在base.service.ts中,如上所示。 链接到源代码:(https://gitlab.com/adh.ranjan/nestjs) 就像在调用了edit函数的postCreate方法中一样,我也想在postUpdate方法中调用edit函数。我面临的问题是执行将导致无限循环。我想在同一UserSchema中添加“ isKycPending”。一种解决方案可能是创建一个新的架构,如EmailNotificationSchema并调用emailnotificationService,如上所示。可能有什么解决方案?

0 个答案:

没有答案