type-graphql#createMethodDecorator TypeScript Examples

The following examples show how to use type-graphql#createMethodDecorator. 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: authorizations.ts    From backend with MIT License 6 votes vote down vote up
/* Inside mutations, determining Ownership is hard because the actual value is retrieved by it's primary key during
   mutation execution. Thus with AuthorizedDeferred one can move the access check into the mutation, and call
   hasAccess once the value is ready, like:

   @AuthorizedDeferred(Role.OWNER)
   courseCancel(@Ctx() context, @Arg() courseId: number) {
       const course = await getCourse(courseId);
       await hasAccess(context, "Course", course);
       // ...
   }

   Note that this leaks the information whether an entity exists, though as we use artificial primary keys this should not reveal
    anything of value
*/
export function AuthorizedDeferred(...requiredRoles: Role[]) {
    assert(requiredRoles.length, "Roles must be passed to AUTHORIZED");

    return createMethodDecorator<GraphQLContext>(({ args, root, info, context }, next) => {
        context.deferredRequiredRoles = requiredRoles;
        return next();
    });
}
Example #2
Source File: cache.ts    From backend with MIT License 6 votes vote down vote up
/* If a Query is annotated with @PublicCache AND all the entities involved in the query are marked with "cacheAllFields" in the enhancement map below,
    then further requests with exactly the same query are served from cache for (duration) seconds */
export function PublicCache(duration: number = 60 /*s*/) {
    return createMethodDecorator<GraphQLContext>(({ info }, next) => {
        info.cacheControl.setCacheHint({
            maxAge: duration,
            scope: CacheScope.Public
        });

        return next();
    });
}
Example #3
Source File: complexity.ts    From backend with MIT License 6 votes vote down vote up
export function LimitedQuery(limit = 100) {
    return createMethodDecorator<LimitedQueryContext>(({ args, root, info, context }, next) => {
        // mutations are always fine, we only worry about queries
        if (info.operation.operation === "mutation") {
            return next();
        }


        const numberLimited = !!args.take;
        const numberLimitedLow = args.take <= limit;
        const isIDQuery = !!args.where?.id;

        if (numberLimited && !numberLimitedLow) {
            throw new ValidationError(`Overcomplex Query: Please reduce the TAKE arg to less than ${limit} entries`);
        }

        if (!isIDQuery && !numberLimitedLow) {
            throw new ValidationError(`Overcomplex Query: Please implement pagination with TAKE and SKIP`);
        }

        const cardinality = isIDQuery ? 1 : args.take;
        enforceAccumulatedLimit(info, context, cardinality);

        return next();

    });
}
Example #4
Source File: rate-limit.ts    From backend with MIT License 6 votes vote down vote up
export function RateLimit(name: string, max: number, interval: number /* in ms */) {
    const countPerIP = new Map<string, number>();

    setInterval(() => {
        countPerIP.clear();
        log.info(`Cleared Rate Limit ${name} counters`);
    }, interval);

    return createMethodDecorator<GraphQLContext>(({ args, root, info, context }, next) => {
        // Trusted users are generally power-users and perform a lot of API requests,
        //  for those we do not enforce rate limits (as we trust them)
        if ((context as GraphQLContext).user?.roles.includes(Role.ADMIN) ||
            (context as GraphQLContext).user?.roles.includes(Role.SCREENER)) {
            return next();
        }

        if (!countPerIP.has(context.ip)) {
            log.debug(`First request from ${context.ip}`);
            countPerIP.set(context.ip, 1);
            return next();
        }

        const count = countPerIP.get(context.ip);
        countPerIP.set(context.ip, count + 1);

        if (count > max) {
            log.warn(`Blocked ${context.ip} from accessing ${name} as maximum of ${max} was reached`);
            throw new Error(`RateLimit Enforcement`);
        }

        log.debug(`${context.ip} requested ${name} for the ${count}th time`);
        return next();
    });
}
Example #5
Source File: complexity.ts    From backend with MIT License 5 votes vote down vote up
/* For nested field resolvers one can still give a brief estimation about the entries expected */
export function LimitEstimated(cardinality: number) {
    return createMethodDecorator(({ info, context }, next) => {
        enforceAccumulatedLimit(info, context, cardinality);

        return next();
    });
}