| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- import { Injectable } from '@nestjs/common';
- import { Request } from 'express';
- import { LanguageCode, Permission } from 'shared/generated-types';
- import { idsAreEqual } from '../../common/utils';
- import { ConfigService } from '../../config/config.service';
- import { Channel } from '../../entity/channel/channel.entity';
- import { AuthenticatedSession } from '../../entity/session/authenticated-session.entity';
- import { Session } from '../../entity/session/session.entity';
- import { User } from '../../entity/user/user.entity';
- import { I18nError } from '../../i18n/i18n-error';
- import { ChannelService } from '../../service/providers/channel.service';
- import { RequestContext } from './request-context';
- export const REQUEST_CONTEXT_KEY = 'vendureRequestContext';
- /**
- * Creates new RequestContext instances.
- */
- @Injectable()
- export class RequestContextService {
- constructor(private channelService: ChannelService, private configService: ConfigService) {}
- /**
- * Creates a new RequestContext based on an Express request object.
- */
- async fromRequest(
- req: Request,
- requiredPermissions?: Permission[],
- session?: Session,
- ): Promise<RequestContext> {
- const channelToken = this.getChannelToken(req);
- const channel = this.channelService.getChannelFromToken(channelToken);
- const hasOwnerPermission = !!requiredPermissions && requiredPermissions.includes(Permission.Owner);
- const languageCode = this.getLanguageCode(req);
- const user = session && (session as AuthenticatedSession).user;
- const isAuthorized = this.userHasRequiredPermissionsOnChannel(requiredPermissions, channel, user);
- const authorizedAsOwnerOnly = !isAuthorized && hasOwnerPermission;
- return new RequestContext({
- channel,
- languageCode,
- session,
- isAuthorized,
- authorizedAsOwnerOnly,
- });
- }
- private getChannelToken(req: Request): string {
- const tokenKey = this.configService.channelTokenKey;
- let channelToken: string;
- if (req && req.query && req.query[tokenKey]) {
- channelToken = req.query[tokenKey];
- } else if (req && req.headers && req.headers[tokenKey]) {
- channelToken = req.headers[tokenKey] as string;
- } else {
- throw new I18nError('error.no-valid-channel-specified');
- }
- return channelToken;
- }
- private getLanguageCode(req: Request): LanguageCode | undefined {
- return req.body && req.body.variables && req.body.variables.languageCode;
- }
- private isAuthenticatedSession(session?: Session): session is AuthenticatedSession {
- return !!session && !!(session as AuthenticatedSession).user;
- }
- private userHasRequiredPermissionsOnChannel(
- permissions: Permission[] = [],
- channel?: Channel,
- user?: User,
- ): boolean {
- if (!user || !channel) {
- return false;
- }
- const permissionsOnChannel = user.roles
- .filter(role => role.channels.find(c => idsAreEqual(c.id, channel.id)))
- .reduce((output, role) => [...output, ...role.permissions], [] as Permission[]);
- return this.arraysIntersect(permissions, permissionsOnChannel);
- }
- /**
- * Returns true if any element of arr1 appears in arr2.
- */
- private arraysIntersect<T>(arr1: T[], arr2: T[]): boolean {
- return arr1.reduce((intersects, role) => {
- return intersects || arr2.includes(role);
- }, false);
- }
- }
|