type-graphql#UseMiddleware TypeScript Examples

The following examples show how to use type-graphql#UseMiddleware. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: image-resolver.ts    From convoychat with GNU General Public License v3.0 6 votes vote down vote up
@UseMiddleware(RateLimit({ limit: 10 }))
  @Mutation(() => UploadImageOutput)
  async uploadImage(
    @Arg("file", () => GraphQLUpload) file: Promise<IUpload>
  ): Promise<UploadImageOutput> {
    const { createReadStream } = await file;
    const fileStream = createReadStream();

    return new Promise((resolve, reject) => {
      const cloudStream = cloudinary.uploader.upload_stream(
        {
          unique_filename: true,
          folder: process.env.MEDIA_FOLDER,
        },
        (err, fileUploaded) => {
          if (err) reject(false);

          resolve({
            url: fileUploaded.secure_url,
            public_id: fileUploaded.public_id,
          });
        }
      );

      fileStream.pipe(cloudStream);
    });
  }
Example #2
Source File: message-resolver.ts    From convoychat with GNU General Public License v3.0 6 votes vote down vote up
@Authorized()
  @UseMiddleware(RateLimit({ limit: 1000 }))
  @Mutation(() => Message)
  async deleteMessage(
    @Arg("messageId") messageId: ObjectID,
    @Ctx() context: Context,
    @PubSub() pubsub: PubSubEngine
  ) {
    try {
      const message = await MessageModel.findOneAndDelete({
        _id: messageId,
        author: context.currentUser.id,
      });

      if (!message) throw new ApolloError("Cannot find message with ID");

      await message.populate("author").execPopulate();
      pubsub.publish(CONSTANTS.DELETE_MESSAGE, message.toObject());

      return message;
    } catch (err) {
      throw new ApolloError(err);
    }
  }
Example #3
Source File: message-resolver.ts    From convoychat with GNU General Public License v3.0 6 votes vote down vote up
@Authorized()
  @UseMiddleware(RateLimit({ limit: 2000 }))
  @Mutation(() => Message)
  async editMessage(
    @Args() { messageId, content }: editMessageArgs,
    @Ctx() context: Context,
    @PubSub() pubsub: PubSubEngine
  ) {
    try {
      const message = await MessageModel.findOneAndUpdate(
        {
          _id: messageId,
          author: context.currentUser.id,
        },
        { content: content },
        { new: true }
      );
      if (!message) throw new ApolloError("Cannot find message with ID");

      await message.populate("author").execPopulate();
      pubsub.publish(CONSTANTS.UPDATE_MESSAGE, message.toObject());

      return message;
    } catch (err) {
      throw new ApolloError(err);
    }
  }
Example #4
Source File: room-resolver.ts    From convoychat with GNU General Public License v3.0 6 votes vote down vote up
@Authorized()
  @UseMiddleware(RateLimit({ limit: 20 }))
  @Mutation(() => Room)
  async createRoom(@Args() { name }: createRoomArgs, @Ctx() context: Context) {
    try {
      const room = new RoomModel({
        name: name,
        messages: [],
        members: [context.currentUser.id],
        owner: context.currentUser.id,
      });
      await room.populate("members").execPopulate();

      await UserModel.findByIdAndUpdate(
        context.currentUser.id,
        { $addToSet: { rooms: room._id } },
        { new: true }
      );
      const savedRoom = await room.save();

      return savedRoom;
    } catch (err) {
      throw new ApolloError(err);
    }
  }
Example #5
Source File: room-resolver.ts    From convoychat with GNU General Public License v3.0 6 votes vote down vote up
@Authorized()
  @UseMiddleware(RateLimit())
  @Mutation(() => Member, { nullable: true })
  async removeMemberFromRoom(
    @Args() { roomId, memberId }: removeMembersArgs,
    @Ctx() context: Context
  ): Promise<Member> {
    try {
      if (memberId.equals(context.currentUser.id)) {
        throw new ApolloError("You cannot not remove yourself from room");
      }

      const room = await RoomModel.findOneAndUpdate(
        {
          _id: roomId,
          owner: context.currentUser.id,
        },
        { $pull: { members: memberId } },
        { new: true }
      );

      const removedMember = await UserModel.findOneAndUpdate(
        { _id: memberId },
        { $pull: { rooms: roomId } },
        { new: true }
      );

      if (!removedMember || !room) {
        throw new ApolloError("Could not remove member from room");
      }

      return removedMember;
    } catch (err) {
      throw new ApolloError(err);
    }
  }
Example #6
Source File: user-resolver.ts    From convoychat with GNU General Public License v3.0 6 votes vote down vote up
@Authorized()
  @UseMiddleware(RateLimit({ limit: 500 }))
  @Mutation(returns => Member)
  async setColor(@Args() { color }: setColorArgs, @Ctx() context: Context) {
    try {
      const user = await UserModel.findOneAndUpdate(
        { _id: context.currentUser.id },
        { color: color },
        { new: true }
      );
      if (!user) throw new ApolloError("User not found with id");
      return user;
    } catch (err) {
      throw new ApolloError(err);
    }
  }
Example #7
Source File: user-resolver.ts    From convoychat with GNU General Public License v3.0 6 votes vote down vote up
@Authorized()
  @UseMiddleware(RateLimit({ limit: 500 }))
  @Mutation(returns => Member)
  async setUserLinks(@Args() links: setUserLinksArgs, @Ctx() context: Context) {
    try {
      const foundUser = await UserModel.findOne({
        _id: context.currentUser.id,
      });
      if (!foundUser) throw new ApolloError("User not found with id");

      const linksToBeUpdated = { ...foundUser.toObject().links, ...links };

      const user = await UserModel.findOneAndUpdate(
        { _id: context.currentUser.id },
        {
          $set: { links: linksToBeUpdated },
        },
        { new: true }
      );
      return user;
    } catch (err) {
      throw new ApolloError(err);
    }
  }
Example #8
Source File: post.ts    From lireddit with MIT License 6 votes vote down vote up
@Mutation(() => Post)
  @UseMiddleware(isAuth)
  async createPost(
    @Arg("input") input: PostInput,
    @Ctx() { req }: MyContext
  ): Promise<Post> {
    return Post.create({
      ...input,
      creatorId: req.session.userId,
    }).save();
  }
Example #9
Source File: post.ts    From lireddit with MIT License 6 votes vote down vote up
@Mutation(() => Post, { nullable: true })
  @UseMiddleware(isAuth)
  async updatePost(
    @Arg("id", () => Int) id: number,
    @Arg("title") title: string,
    @Arg("text") text: string,
    @Ctx() { req }: MyContext
  ): Promise<Post | null> {
    const result = await getConnection()
      .createQueryBuilder()
      .update(Post)
      .set({ title, text })
      .where('id = :id and "creatorId" = :creatorId', {
        id,
        creatorId: req.session.userId,
      })
      .returning("*")
      .execute();

    return result.raw[0];
  }
Example #10
Source File: post.ts    From lireddit with MIT License 6 votes vote down vote up
@Mutation(() => Boolean)
  @UseMiddleware(isAuth)
  async deletePost(
    @Arg("id", () => Int) id: number,
    @Ctx() { req }: MyContext
  ): Promise<boolean> {
    // not cascade way
    // const post = await Post.findOne(id);
    // if (!post) {
    //   return false;
    // }
    // if (post.creatorId !== req.session.userId) {
    //   throw new Error("not authorized");
    // }

    // await Updoot.delete({ postId: id });
    // await Post.delete({ id });

    await Post.delete({ id, creatorId: req.session.userId });
    return true;
  }
Example #11
Source File: Loader.ts    From type-graphql-dataloader with MIT License 6 votes vote down vote up
export function Loader<K, V, C = K>(
  batchLoadFn: BatchLoadFn<K, V>,
  options?: DataLoader.Options<K, V, C>
): MethodAndPropDecorator {
  return (
    target: Object,
    propertyKey: string | symbol,
    descriptor?: TypedPropertyDescriptor<any>
  ) => {
    UseMiddleware(async ({ context }, next) => {
      const serviceId = `tgd#${
        target.constructor.name
      }#${propertyKey.toString()}`;
      const { requestId } = context._tgdContext as TgdContext;
      const container = Container.of(requestId);
      if (!container.has(serviceId)) {
        container.set(
          serviceId,
          new DataLoader((keys) => batchLoadFn(keys, { context }), options)
        );
      }
      const dataloader = container.get(serviceId);
      return await (
        await next()
      )(dataloader);
    })(target, propertyKey);
  };
}
Example #12
Source File: ImplicitLoaderImpl.ts    From type-graphql-dataloader with MIT License 6 votes vote down vote up
export function ImplicitLoaderImpl<V>(): PropertyDecorator {
  return (target: Object, propertyKey: string | symbol) => {
    UseMiddleware(async ({ root, context }, next) => {
      const tgdContext = context._tgdContext as TgdContext;
      if (tgdContext.typeormGetConnection == null) {
        throw Error("typeormGetConnection is not set");
      }
      const relation = tgdContext
        .typeormGetConnection()
        .getMetadata(target.constructor)
        .findRelationWithPropertyPath(propertyKey.toString());

      if (relation == null) {
        return await next();
      }
      if (relation.inverseRelation == null) {
        throw Error(`inverseRelation is required: ${String(propertyKey)}`);
      }

      const dataloaderCls =
        relation.isOneToOneOwner || relation.isManyToOne
          ? ToOneOwnerDataloader
          : relation.isOneToOneNotOwner
          ? ToOneNotOwnerDataloader
          : relation.isOneToMany
          ? OneToManyDataloader
          : relation.isManyToMany
          ? ManyToManyDataloader
          : null;
      if (dataloaderCls == null) {
        return await next();
      }
      return await handler<V>(root, tgdContext, relation, dataloaderCls);
    })(target, propertyKey);
  };
}
Example #13
Source File: invitation-resolver.ts    From convoychat with GNU General Public License v3.0 5 votes vote down vote up
@Authorized()
  @UseMiddleware(RateLimit({ limit: 15 }))
  @Mutation(() => [Invitation])
  async inviteMembers(
    @Args() { roomId, members }: inviteMembersArgs,
    @Ctx() context: Context
  ) {
    try {
      // check if user is a memeber of the specified room
      const user = await UserModel.findOne({
        _id: context.currentUser.id,
        rooms: { $in: [roomId] },
      });

      if (!user) {
        throw new ApolloError(
          "You are not a member of room, Cannot invite members"
        );
      }

      let token = null;

      // create invitations
      const invitations = members.map(memberId => {
        token = crypto.randomBytes(16).toString("hex");
        const invite = new InvitationModel({
          roomId: roomId,
          userId: memberId,
          invitedBy: context.currentUser.id,
          token: token,
        });

        return invite.save();
      });

      // @ts-ignore
      const savedInvites: Invitation[] = await Promise.all(invitations);

      const foundRoom = await RoomModel.findOne({ _id: roomId });

      // send notification
      const notifications = members.map(async (id, index) => {
        return sendNotification({
          context: context,
          sender: context.currentUser.id,
          receiver: id,
          type: NOTIFICATION_TYPE.INVITATION,
          payload: {
            userId: id,
            roomName: foundRoom.name,
            roomId: roomId,
            invitedBy: context.currentUser.id,
            token: savedInvites[index].token,
          },
        });
      });

      await Promise.all(notifications);

      // TODO: Send Email invitations

      return savedInvites;
    } catch (err) {
      console.log(err);
      throw new ApolloError(err);
    }
  }
Example #14
Source File: message-resolver.ts    From convoychat with GNU General Public License v3.0 5 votes vote down vote up
@Authorized()
  @UseMiddleware(RateLimit({ limit: 1000 }))
  @Mutation(() => Message)
  async sendMessage(
    @Args() { roomId, content }: sendMessageArgs,
    @Ctx() context: Context,
    @PubSub() pubsub: PubSubEngine
  ) {
    try {
      const room = await RoomModel.findOne({
        _id: roomId,
        members: { $in: [context.currentUser.id] },
      }).populate("members");

      if (!room) {
        throw new ApolloError(
          "Room not found or you are not a member of this room"
        );
      }

      // parse mentions
      const mentions = parseMentions(content);

      // check if mentioned users are member of the room
      const mentioned_users = mentions
        .map(m => {
          const found = room?.members.find((i: Member) => i.username === m);
          if (found) {
            return (found as any)._id;
          }
          return null;
        })
        // remove null values & current user if mentioned
        .filter(userId => {
          if (!userId) return false;
          return `${userId}` !== `${context.currentUser.id}`;
        });

      const message = new MessageModel({
        content: content,
        roomId: roomId,
        author: context.currentUser.id,
        mentions: mentioned_users,
      });
      message.populate("author").execPopulate();

      // filter out the current User id to prevent self notification sending
      const mentionNotifications = message.mentions.map(async id => {
        return sendNotification({
          context: context,
          sender: context.currentUser.id,
          receiver: id as any,
          type: NOTIFICATION_TYPE.MENTION,
          payload: {
            roomName: room?.name,
            message: message.content,
            messageId: message._id,
            roomId: room?._id,
          },
        });
      });

      await Promise.all(mentionNotifications);

      (message as any).$roomId = roomId;
      const savedMessage = await message.save();
      pubsub.publish(CONSTANTS.NEW_MESSAGE, savedMessage.toObject());

      return savedMessage;
    } catch (err) {
      throw new ApolloError(err);
    }
  }
Example #15
Source File: post.ts    From lireddit with MIT License 5 votes vote down vote up
@Mutation(() => Boolean)
  @UseMiddleware(isAuth)
  async vote(
    @Arg("postId", () => Int) postId: number,
    @Arg("value", () => Int) value: number,
    @Ctx() { req }: MyContext
  ) {
    const isUpdoot = value !== -1;
    const realValue = isUpdoot ? 1 : -1;
    const { userId } = req.session;

    const updoot = await Updoot.findOne({ where: { postId, userId } });

    // the user has voted on the post before
    // and they are changing their vote
    if (updoot && updoot.value !== realValue) {
      await getConnection().transaction(async (tm) => {
        await tm.query(
          `
    update updoot
    set value = $1
    where "postId" = $2 and "userId" = $3
        `,
          [realValue, postId, userId]
        );

        await tm.query(
          `
          update post
          set points = points + $1
          where id = $2
        `,
          [2 * realValue, postId]
        );
      });
    } else if (!updoot) {
      // has never voted before
      await getConnection().transaction(async (tm) => {
        await tm.query(
          `
    insert into updoot ("userId", "postId", value)
    values ($1, $2, $3)
        `,
          [userId, postId, realValue]
        );

        await tm.query(
          `
    update post
    set points = points + $1
    where id = $2
      `,
          [realValue, postId]
        );
      });
    }
    return true;
  }
Example #16
Source File: ExplicitLoaderImpl.ts    From type-graphql-dataloader with MIT License 5 votes vote down vote up
export function ExplicitLoaderImpl<V>(
  keyFunc: KeyFunc,
  option?: TypeormLoaderOption
): PropertyDecorator {
  return (target: Object, propertyKey: string | symbol) => {
    UseMiddleware(async ({ root, context }, next) => {
      const tgdContext = context._tgdContext as TgdContext;
      if (tgdContext.typeormGetConnection == null) {
        throw Error("typeormGetConnection is not set");
      }
      const relation = tgdContext
        .typeormGetConnection()
        .getMetadata(target.constructor)
        .findRelationWithPropertyPath(propertyKey.toString());

      if (relation == null) {
        return await next();
      }
      if (
        option?.selfKey &&
        !(relation.isOneToMany || relation.isOneToOneNotOwner)
      ) {
        throw Error(
          "selfKey option is available only for OneToMany or OneToOneNotOwner"
        );
      }

      // prettier-ignore
      const handle =
        relation.isManyToOne || relation.isOneToOneOwner ?
          handleToOne :
        relation.isOneToMany ?
          option?.selfKey ?
            handleOneToManyWithSelfKey :
          handleToMany :
        relation.isOneToOneNotOwner ?
          option?.selfKey ?
            handleOneToOneNotOwnerWithSelfKey :
          handleToOne :
        relation.isManyToMany ?
          handleToMany :
        () => next();
      return await handle<V>(keyFunc, root, tgdContext, relation);
    })(target, propertyKey);
  };
}