chore: hoppscotch-backend code formatting, minor lint fixes, and refactoring (#5061)
* chore: prettier formatting applied * chore: added some lint fixed * fix: few lint errors * chore: prisma and pubsub are now global module * chore: add encapsulation consistency in service files * chore: made a cast function private * chore: cast function made private * refactor: module imports * refactor: posthog spelling
This commit is contained in:
parent
c28e4103a8
commit
46e5792965
66 changed files with 275 additions and 421 deletions
|
|
@ -4,7 +4,6 @@ import {
|
|||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
HttpStatus,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Post,
|
||||
|
|
|
|||
|
|
@ -1,18 +1,12 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { AccessTokenController } from './access-token.controller';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
import { AccessTokenService } from './access-token.service';
|
||||
import { TeamCollectionModule } from 'src/team-collection/team-collection.module';
|
||||
import { TeamEnvironmentsModule } from 'src/team-environments/team-environments.module';
|
||||
import { TeamModule } from 'src/team/team.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
PrismaModule,
|
||||
TeamCollectionModule,
|
||||
TeamEnvironmentsModule,
|
||||
TeamModule,
|
||||
],
|
||||
imports: [TeamCollectionModule, TeamEnvironmentsModule, TeamModule],
|
||||
controllers: [AccessTokenController],
|
||||
providers: [AccessTokenService],
|
||||
exports: [AccessTokenService],
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
import { CreateAccessTokenResponse } from './helper';
|
||||
import { PersonalAccessToken } from '@prisma/client';
|
||||
import { AccessToken } from 'src/types/AccessToken';
|
||||
|
||||
@Injectable()
|
||||
export class AccessTokenService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { AdminResolver } from './admin.resolver';
|
||||
import { AdminService } from './admin.service';
|
||||
import { PrismaModule } from '../prisma/prisma.module';
|
||||
import { PubSubModule } from '../pubsub/pubsub.module';
|
||||
import { UserModule } from '../user/user.module';
|
||||
import { TeamModule } from '../team/team.module';
|
||||
import { TeamInvitationModule } from '../team-invitation/team-invitation.module';
|
||||
|
|
@ -16,8 +14,6 @@ import { UserHistoryModule } from 'src/user-history/user-history.module';
|
|||
|
||||
@Module({
|
||||
imports: [
|
||||
PrismaModule,
|
||||
PubSubModule,
|
||||
UserModule,
|
||||
TeamModule,
|
||||
TeamInvitationModule,
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ import {
|
|||
Args,
|
||||
ID,
|
||||
Mutation,
|
||||
Parent,
|
||||
Query,
|
||||
ResolveField,
|
||||
Resolver,
|
||||
Subscription,
|
||||
} from '@nestjs/graphql';
|
||||
|
|
@ -33,7 +31,7 @@ import { UserDeletionResult } from 'src/user/user.model';
|
|||
@Resolver(() => Admin)
|
||||
export class AdminResolver {
|
||||
constructor(
|
||||
private adminService: AdminService,
|
||||
private readonly adminService: AdminService,
|
||||
private readonly pubsub: PubSubService,
|
||||
) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import {
|
|||
ONLY_ONE_ADMIN_ACCOUNT,
|
||||
USER_ALREADY_INVITED,
|
||||
USER_INVITATION_DELETION_FAILED,
|
||||
USER_NOT_FOUND,
|
||||
} from '../errors';
|
||||
import { ShortcodeService } from 'src/shortcode/shortcode.service';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
|
@ -44,8 +43,8 @@ const adminService = new AdminService(
|
|||
mockTeamRequestService,
|
||||
mockTeamEnvironmentsService,
|
||||
mockTeamInvitationService,
|
||||
mockPubSub as any,
|
||||
mockPrisma as any,
|
||||
mockPubSub,
|
||||
mockPrisma,
|
||||
mockMailerService,
|
||||
mockShortcodeService,
|
||||
mockConfigService,
|
||||
|
|
@ -99,14 +98,11 @@ const dbAdminUsers: DbUser[] = [
|
|||
describe('AdminService', () => {
|
||||
describe('fetchInvitedUsers', () => {
|
||||
test('should resolve right and apply pagination correctly', async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
mockPrisma.user.findMany.mockResolvedValue([dbAdminUsers[0]]);
|
||||
// @ts-ignore
|
||||
mockPrisma.invitedUsers.findMany.mockResolvedValue(invitedUsers);
|
||||
|
||||
const paginationArgs: OffsetPaginationArgs = { take: 5, skip: 2 };
|
||||
const results = await adminService.fetchInvitedUsers(paginationArgs);
|
||||
await adminService.fetchInvitedUsers(paginationArgs);
|
||||
|
||||
expect(mockPrisma.invitedUsers.findMany).toHaveBeenCalledWith({
|
||||
...paginationArgs,
|
||||
|
|
@ -126,10 +122,7 @@ describe('AdminService', () => {
|
|||
test('should resolve right and return an array of invited users', async () => {
|
||||
const paginationArgs: OffsetPaginationArgs = { take: 10, skip: 0 };
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
mockPrisma.user.findMany.mockResolvedValue([dbAdminUsers[0]]);
|
||||
// @ts-ignore
|
||||
mockPrisma.invitedUsers.findMany.mockResolvedValue(invitedUsers);
|
||||
|
||||
const results = await adminService.fetchInvitedUsers(paginationArgs);
|
||||
|
|
@ -217,7 +210,6 @@ describe('AdminService', () => {
|
|||
});
|
||||
|
||||
test('should resolve right and return deleted invitee email', async () => {
|
||||
const adminUid = 'adminUid';
|
||||
mockPrisma.invitedUsers.deleteMany.mockResolvedValueOnce({ count: 1 });
|
||||
|
||||
const result = await adminService.revokeUserInvitations([
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import {
|
|||
INVALID_EMAIL,
|
||||
ONLY_ONE_ADMIN_ACCOUNT,
|
||||
TEAM_INVITE_ALREADY_MEMBER,
|
||||
TEAM_INVITE_NO_INVITE_FOUND,
|
||||
USERS_NOT_FOUND,
|
||||
USER_ALREADY_INVITED,
|
||||
USER_INVITATION_DELETION_FAILED,
|
||||
|
|
@ -464,7 +463,7 @@ export class AdminService {
|
|||
});
|
||||
|
||||
const nonAdminUsers = allUsersList.filter((user) => !user.isAdmin);
|
||||
let deletedUserEmails: string[] = [];
|
||||
const deletedUserEmails: string[] = [];
|
||||
|
||||
// step 3: delete non-admin users
|
||||
const deletionPromises = nonAdminUsers.map((user) => {
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ import { ServiceStatus } from 'src/infra-config/helper';
|
|||
@Resolver(() => Infra)
|
||||
export class InfraResolver {
|
||||
constructor(
|
||||
private adminService: AdminService,
|
||||
private infraConfigService: InfraConfigService,
|
||||
private readonly adminService: AdminService,
|
||||
private readonly infraConfigService: InfraConfigService,
|
||||
) {}
|
||||
|
||||
@Query(() => Infra, {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ import { UserSettingsModule } from './user-settings/user-settings.module';
|
|||
import { UserEnvironmentsModule } from './user-environment/user-environments.module';
|
||||
import { UserRequestModule } from './user-request/user-request.module';
|
||||
import { UserHistoryModule } from './user-history/user-history.module';
|
||||
import { subscriptionContextCookieParser, extractAccessTokenFromAuthRecords } from './auth/helper';
|
||||
import {
|
||||
subscriptionContextCookieParser,
|
||||
extractAccessTokenFromAuthRecords,
|
||||
} from './auth/helper';
|
||||
import { TeamModule } from './team/team.module';
|
||||
import { TeamEnvironmentsModule } from './team-environments/team-environments.module';
|
||||
import { TeamCollectionModule } from './team-collection/team-collection.module';
|
||||
|
|
@ -24,12 +27,14 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
|
|||
import { InfraConfigModule } from './infra-config/infra-config.module';
|
||||
import { loadInfraConfiguration } from './infra-config/helper';
|
||||
import { MailerModule } from './mailer/mailer.module';
|
||||
import { PosthogModule } from './posthog/posthog.module';
|
||||
import { PostHogModule } from './posthog/posthog.module';
|
||||
import { ScheduleModule } from '@nestjs/schedule';
|
||||
import { HealthModule } from './health/health.module';
|
||||
import { AccessTokenModule } from './access-token/access-token.module';
|
||||
import { UserLastActiveOnInterceptor } from './interceptors/user-last-active-on.interceptor';
|
||||
import { InfraTokenModule } from './infra-token/infra-token.module';
|
||||
import { PrismaModule } from './prisma/prisma.module';
|
||||
import { PubSubModule } from './pubsub/pubsub.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -56,8 +61,9 @@ import { InfraTokenModule } from './infra-token/infra-token.module';
|
|||
const websocketHeaders = websocket?.upgradeReq?.headers;
|
||||
|
||||
try {
|
||||
const accessToken = extractAccessTokenFromAuthRecords(connectionParams);
|
||||
const authorization = `Bearer ${accessToken}`
|
||||
const accessToken =
|
||||
extractAccessTokenFromAuthRecords(connectionParams);
|
||||
const authorization = `Bearer ${accessToken}`;
|
||||
|
||||
return { headers: { ...websocketHeaders, authorization } };
|
||||
} catch (authError) {
|
||||
|
|
@ -74,7 +80,7 @@ import { InfraTokenModule } from './infra-token/infra-token.module';
|
|||
|
||||
return { headers: { ...websocketHeaders, cookies } };
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
context: ({ req, res, connection }) => ({
|
||||
|
|
@ -95,6 +101,8 @@ import { InfraTokenModule } from './infra-token/infra-token.module';
|
|||
},
|
||||
],
|
||||
}),
|
||||
PrismaModule,
|
||||
PubSubModule,
|
||||
MailerModule.register(),
|
||||
UserModule,
|
||||
AuthModule.register(),
|
||||
|
|
@ -111,7 +119,7 @@ import { InfraTokenModule } from './infra-token/infra-token.module';
|
|||
UserCollectionModule,
|
||||
ShortcodeModule,
|
||||
InfraConfigModule,
|
||||
PosthogModule,
|
||||
PostHogModule,
|
||||
ScheduleModule.forRoot(),
|
||||
HealthModule,
|
||||
AccessTokenModule,
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ export class AuthController {
|
|||
if (!redirectUri || !redirectUri.startsWith('http://localhost')) {
|
||||
throwHTTPErr({
|
||||
message: 'Invalid desktop callback URL',
|
||||
statusCode: 400
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { Module } from '@nestjs/common';
|
|||
import { AuthService } from './auth.service';
|
||||
import { AuthController } from './auth.controller';
|
||||
import { UserModule } from 'src/user/user.module';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { JwtStrategy } from './strategies/jwt.strategy';
|
||||
|
|
@ -20,7 +19,6 @@ import { InfraConfigModule } from 'src/infra-config/infra-config.module';
|
|||
|
||||
@Module({
|
||||
imports: [
|
||||
PrismaModule,
|
||||
UserModule,
|
||||
PassportModule,
|
||||
JwtModule.registerAsync({
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { HttpStatus } from '@nestjs/common';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { Account, VerificationToken } from '@prisma/client';
|
||||
import { mockDeep, mockFn } from 'jest-mock-extended';
|
||||
import { mockDeep } from 'jest-mock-extended';
|
||||
import {
|
||||
INVALID_EMAIL,
|
||||
INVALID_MAGIC_LINK_DATA,
|
||||
|
|
@ -82,9 +82,6 @@ let nowPlus30 = new Date();
|
|||
nowPlus30.setMinutes(nowPlus30.getMinutes() + 30000);
|
||||
nowPlus30 = new Date(nowPlus30);
|
||||
|
||||
const encodedRefreshToken =
|
||||
'$argon2id$v=19$m=65536,t=3,p=4$JTP8yZ8YXMHdafb5pB9Rfg$tdZrILUxMb9dQbu0uuyeReLgKxsgYnyUNbc5ZxQmy5I';
|
||||
|
||||
describe('signInMagicLink', () => {
|
||||
test('Should throw error if email is not in valid format', async () => {
|
||||
const result = await authService.signInMagicLink('bbbgmail.com', 'admin');
|
||||
|
|
|
|||
|
|
@ -34,12 +34,12 @@ import { InfraConfigService } from 'src/infra-config/infra-config.service';
|
|||
@Injectable()
|
||||
export class AuthService {
|
||||
constructor(
|
||||
private usersService: UserService,
|
||||
private prismaService: PrismaService,
|
||||
private jwtService: JwtService,
|
||||
private readonly usersService: UserService,
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly jwtService: JwtService,
|
||||
private readonly mailerService: MailerService,
|
||||
private readonly configService: ConfigService,
|
||||
private infraConfigService: InfraConfigService,
|
||||
private readonly infraConfigService: InfraConfigService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
|
|
@ -59,7 +59,7 @@ export class AuthService {
|
|||
.toISO()
|
||||
.toString();
|
||||
|
||||
const idToken = await this.prismaService.verificationToken.create({
|
||||
const idToken = await this.prisma.verificationToken.create({
|
||||
data: {
|
||||
deviceIdentifier: salt,
|
||||
userUid: user.uid,
|
||||
|
|
@ -78,15 +78,14 @@ export class AuthService {
|
|||
*/
|
||||
private async validatePasswordlessTokens(magicLinkTokens: VerifyMagicDto) {
|
||||
try {
|
||||
const tokens =
|
||||
await this.prismaService.verificationToken.findUniqueOrThrow({
|
||||
where: {
|
||||
passwordless_deviceIdentifier_tokens: {
|
||||
deviceIdentifier: magicLinkTokens.deviceIdentifier,
|
||||
token: magicLinkTokens.token,
|
||||
},
|
||||
const tokens = await this.prisma.verificationToken.findUniqueOrThrow({
|
||||
where: {
|
||||
passwordless_deviceIdentifier_tokens: {
|
||||
deviceIdentifier: magicLinkTokens.deviceIdentifier,
|
||||
token: magicLinkTokens.token,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
return O.some(tokens);
|
||||
} catch (error) {
|
||||
return O.none;
|
||||
|
|
@ -160,7 +159,7 @@ export class AuthService {
|
|||
) {
|
||||
try {
|
||||
const deletedPasswordlessToken =
|
||||
await this.prismaService.verificationToken.delete({
|
||||
await this.prisma.verificationToken.delete({
|
||||
where: {
|
||||
passwordless_deviceIdentifier_tokens: {
|
||||
deviceIdentifier: passwordlessTokens.deviceIdentifier,
|
||||
|
|
@ -182,7 +181,7 @@ export class AuthService {
|
|||
* @returns Either of existing user provider Account
|
||||
*/
|
||||
async checkIfProviderAccountExists(user: AuthUser, SSOUserData) {
|
||||
const provider = await this.prismaService.account.findUnique({
|
||||
const provider = await this.prisma.account.findUnique({
|
||||
where: {
|
||||
verifyProviderAccount: {
|
||||
provider: SSOUserData.provider,
|
||||
|
|
@ -256,9 +255,8 @@ export class AuthService {
|
|||
async verifyMagicLinkTokens(
|
||||
magicLinkIDTokens: VerifyMagicDto,
|
||||
): Promise<E.Right<AuthTokens> | E.Left<RESTError>> {
|
||||
const passwordlessTokens = await this.validatePasswordlessTokens(
|
||||
magicLinkIDTokens,
|
||||
);
|
||||
const passwordlessTokens =
|
||||
await this.validatePasswordlessTokens(magicLinkIDTokens);
|
||||
if (O.isNone(passwordlessTokens))
|
||||
return E.left({
|
||||
message: INVALID_MAGIC_LINK_DATA,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,12 @@ import { DateTime } from 'luxon';
|
|||
import { AuthTokens } from 'src/types/AuthTokens';
|
||||
import { Response } from 'express';
|
||||
import * as cookie from 'cookie';
|
||||
import { AUTH_HEADER_NOT_FOUND, AUTH_PROVIDER_NOT_SPECIFIED, COOKIES_NOT_FOUND, INVALID_AUTH_HEADER } from 'src/errors';
|
||||
import {
|
||||
AUTH_HEADER_NOT_FOUND,
|
||||
AUTH_PROVIDER_NOT_SPECIFIED,
|
||||
COOKIES_NOT_FOUND,
|
||||
INVALID_AUTH_HEADER,
|
||||
} from 'src/errors';
|
||||
import { throwErr } from 'src/utils';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { IncomingHttpHeaders } from 'http';
|
||||
|
|
@ -118,8 +123,8 @@ export function authProviderCheck(
|
|||
|
||||
const envVariables = VITE_ALLOWED_AUTH_PROVIDERS
|
||||
? VITE_ALLOWED_AUTH_PROVIDERS.split(',').map((provider) =>
|
||||
provider.trim().toUpperCase(),
|
||||
)
|
||||
provider.trim().toUpperCase(),
|
||||
)
|
||||
: [];
|
||||
|
||||
if (!envVariables.includes(provider.toUpperCase())) return false;
|
||||
|
|
@ -132,8 +137,11 @@ export function authProviderCheck(
|
|||
* @param headers HTTP request headers containing auth tokens
|
||||
* @returns Cookie's key-value pairs
|
||||
*/
|
||||
export const extractCookieAsKeyValuesFromHeaders = (headers: IncomingHttpHeaders) => {
|
||||
const cookieHeader = headers['cookie'] || headers['Cookie'] || headers['COOKIE'];
|
||||
export const extractCookieAsKeyValuesFromHeaders = (
|
||||
headers: IncomingHttpHeaders,
|
||||
) => {
|
||||
const cookieHeader =
|
||||
headers['cookie'] || headers['Cookie'] || headers['COOKIE'];
|
||||
|
||||
if (!cookieHeader) {
|
||||
throw new HttpException(COOKIES_NOT_FOUND, 400, {
|
||||
|
|
@ -141,15 +149,21 @@ export const extractCookieAsKeyValuesFromHeaders = (headers: IncomingHttpHeaders
|
|||
});
|
||||
}
|
||||
|
||||
const cookieStr = Array.isArray(cookieHeader) ? cookieHeader[0] : cookieHeader;
|
||||
const cookieStr = Array.isArray(cookieHeader)
|
||||
? cookieHeader[0]
|
||||
: cookieHeader;
|
||||
|
||||
const kv = cookieStr.split(';')
|
||||
.map(cookie => cookie.trim())
|
||||
.reduce((acc, curr) => {
|
||||
const [key, value] = curr.split('=');
|
||||
acc[key] = value;
|
||||
return acc;
|
||||
}, {} as Record<string, string>);
|
||||
const kv = cookieStr
|
||||
.split(';')
|
||||
.map((cookie) => cookie.trim())
|
||||
.reduce(
|
||||
(acc, curr) => {
|
||||
const [key, value] = curr.split('=');
|
||||
acc[key] = value;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, string>,
|
||||
);
|
||||
|
||||
return kv;
|
||||
};
|
||||
|
|
@ -159,10 +173,15 @@ export const extractCookieAsKeyValuesFromHeaders = (headers: IncomingHttpHeaders
|
|||
* @param headers HTTP request headers containing auth tokens
|
||||
* @returns AuthTokens for JWT strategy to use
|
||||
*/
|
||||
export const extractAuthTokensFromCookieHeaders = (headers: IncomingHttpHeaders) => {
|
||||
export const extractAuthTokensFromCookieHeaders = (
|
||||
headers: IncomingHttpHeaders,
|
||||
) => {
|
||||
const cookieKV = extractCookieAsKeyValuesFromHeaders(headers);
|
||||
|
||||
if (!cookieKV[AuthTokenType.ACCESS_TOKEN] || !cookieKV[AuthTokenType.REFRESH_TOKEN]) {
|
||||
if (
|
||||
!cookieKV[AuthTokenType.ACCESS_TOKEN] ||
|
||||
!cookieKV[AuthTokenType.REFRESH_TOKEN]
|
||||
) {
|
||||
throw new HttpException(COOKIES_NOT_FOUND, 400, {
|
||||
cause: new Error(COOKIES_NOT_FOUND),
|
||||
});
|
||||
|
|
@ -179,7 +198,9 @@ export const extractAuthTokensFromCookieHeaders = (headers: IncomingHttpHeaders)
|
|||
* @param headers HTTP request headers containing access tokens
|
||||
* @returns AccessTokens for JWT strategy to use
|
||||
*/
|
||||
export const extractAccessTokensFromCookieHeaders = (headers: IncomingHttpHeaders) => {
|
||||
export const extractAccessTokensFromCookieHeaders = (
|
||||
headers: IncomingHttpHeaders,
|
||||
) => {
|
||||
const cookieKV = extractCookieAsKeyValuesFromHeaders(headers);
|
||||
|
||||
if (!cookieKV[AuthTokenType.ACCESS_TOKEN]) {
|
||||
|
|
@ -198,7 +219,9 @@ export const extractAccessTokensFromCookieHeaders = (headers: IncomingHttpHeader
|
|||
* @param headers HTTP request headers containing bearer token
|
||||
* @returns AccessTokens for JWT strategy
|
||||
*/
|
||||
export const extractAccessTokenFromAuthRecords = (headers: IncomingHttpHeaders) => {
|
||||
export const extractAccessTokenFromAuthRecords = (
|
||||
headers: IncomingHttpHeaders,
|
||||
) => {
|
||||
const authHeader = headers['authorization'] || headers['Authorization'];
|
||||
if (!authHeader) {
|
||||
throw new HttpException(AUTH_HEADER_NOT_FOUND, 400, {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Injectable, ForbiddenException, UnauthorizedException } from '@nestjs/common';
|
||||
import {
|
||||
Injectable,
|
||||
ForbiddenException,
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import { AccessTokenPayload } from 'src/types/AuthTokens';
|
||||
import { UserService } from 'src/user/user.service';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
|
@ -8,7 +12,11 @@ import { Request } from 'express';
|
|||
import * as O from 'fp-ts/Option';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import { pipe } from 'fp-ts/function';
|
||||
import { COOKIES_NOT_FOUND, INVALID_ACCESS_TOKEN, USER_NOT_FOUND } from 'src/errors';
|
||||
import {
|
||||
COOKIES_NOT_FOUND,
|
||||
INVALID_ACCESS_TOKEN,
|
||||
USER_NOT_FOUND,
|
||||
} from 'src/errors';
|
||||
|
||||
/**
|
||||
* Extracts an access token from a cookie in the request.
|
||||
|
|
@ -19,7 +27,7 @@ import { COOKIES_NOT_FOUND, INVALID_ACCESS_TOKEN, USER_NOT_FOUND } from 'src/err
|
|||
const extractFromCookie = (request: Request): O.Option<string> =>
|
||||
pipe(
|
||||
O.fromNullable(request.cookies),
|
||||
O.chain(cookies => O.fromNullable(cookies['access_token']))
|
||||
O.chain((cookies) => O.fromNullable(cookies['access_token'])),
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
@ -35,13 +43,15 @@ const extractFromAuthHeaders = (request: Request): O.Option<string> =>
|
|||
// see `gql-auth.guard` for more info.
|
||||
O.fromNullable(
|
||||
request?.headers?.authorization ||
|
||||
(request && 'authorization' in request ? request['authorization'] : undefined)
|
||||
(request && 'authorization' in request
|
||||
? request['authorization']
|
||||
: undefined),
|
||||
),
|
||||
O.chain(auth =>
|
||||
O.chain((auth) =>
|
||||
typeof auth === 'string' && auth.startsWith('Bearer ')
|
||||
? O.some(auth.slice(7))
|
||||
: O.none
|
||||
)
|
||||
: O.none,
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
@ -59,7 +69,7 @@ const extractToken = (request: Request): E.Either<Error, string> =>
|
|||
// `COOKIES_NOT_FOUND` for backwards compatibility.
|
||||
E.fromOption(() => {
|
||||
return new ForbiddenException(COOKIES_NOT_FOUND);
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -74,9 +84,13 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
|
|||
pipe(
|
||||
extractToken(request),
|
||||
E.fold(
|
||||
error => { throw error; },
|
||||
token => { return token }
|
||||
)
|
||||
(error) => {
|
||||
throw error;
|
||||
},
|
||||
(token) => {
|
||||
return token;
|
||||
},
|
||||
),
|
||||
),
|
||||
]),
|
||||
secretOrKey: configService.get('JWT_SECRET'),
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export class RTJwtStrategy extends PassportStrategy(Strategy, 'jwt-refresh') {
|
|||
(request: Request) => {
|
||||
const RTCookie = request.cookies['refresh_token'];
|
||||
if (!RTCookie) {
|
||||
console.error("`refresh_token` not found")
|
||||
console.error('`refresh_token` not found');
|
||||
throw new ForbiddenException(COOKIES_NOT_FOUND);
|
||||
}
|
||||
return RTCookie;
|
||||
|
|
|
|||
|
|
@ -36,9 +36,7 @@ export class PATAuthGuard implements CanActivate {
|
|||
const today = DateTime.now().toISO();
|
||||
if (accessToken.expiresOn.toISOString() > today) return true;
|
||||
|
||||
throw new BadRequestException(
|
||||
createCLIErrorResponse(ACCESS_TOKEN_EXPIRED),
|
||||
);
|
||||
throw new BadRequestException(createCLIErrorResponse(ACCESS_TOKEN_EXPIRED));
|
||||
}
|
||||
|
||||
private extractTokenFromHeader(request: Request): string | undefined {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { HealthController } from './health.controller';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
import { TerminusModule } from '@nestjs/terminus';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, TerminusModule],
|
||||
imports: [TerminusModule],
|
||||
controllers: [HealthController],
|
||||
})
|
||||
export class HealthModule {}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { AuthProvider } from 'src/auth/helper';
|
||||
import {
|
||||
AUTH_PROVIDER_NOT_CONFIGURED,
|
||||
DATABASE_TABLE_NOT_EXIST,
|
||||
ENV_INVALID_DATA_ENCRYPTION_KEY,
|
||||
} from 'src/errors';
|
||||
import { PrismaService } from 'src/prisma/prisma.service';
|
||||
|
|
@ -68,7 +67,7 @@ export async function loadInfraConfiguration() {
|
|||
|
||||
const infraConfigs = await prisma.infraConfig.findMany();
|
||||
|
||||
let environmentObject: Record<string, any> = {};
|
||||
const environmentObject: Record<string, any> = {};
|
||||
infraConfigs.forEach((infraConfig) => {
|
||||
if (infraConfig.isEncrypted) {
|
||||
environmentObject[infraConfig.name] = decrypt(infraConfig.value);
|
||||
|
|
@ -323,7 +322,7 @@ export async function syncInfraConfigWithEnvFile() {
|
|||
const updateRequiredObjs: (Partial<InfraConfig> & { id: string })[] = [];
|
||||
|
||||
for (const dbConfig of dbInfraConfigs) {
|
||||
let envValue = process.env[dbConfig.name];
|
||||
const envValue = process.env[dbConfig.name];
|
||||
|
||||
// lastSyncedEnvFileValue null check for backward compatibility from 2024.10.2 and below
|
||||
if (!dbConfig.lastSyncedEnvFileValue && envValue) {
|
||||
|
|
@ -398,7 +397,7 @@ export function stopApp() {
|
|||
export function getConfiguredSSOProvidersFromEnvFile() {
|
||||
const allowedAuthProviders: string[] =
|
||||
process.env.VITE_ALLOWED_AUTH_PROVIDERS.split(',');
|
||||
let configuredAuthProviders: string[] = [];
|
||||
const configuredAuthProviders: string[] = [];
|
||||
|
||||
const addProviderIfConfigured = (provider) => {
|
||||
const configParameters: string[] = AuthProviderConfigurations[provider];
|
||||
|
|
@ -439,7 +438,7 @@ export async function getConfiguredSSOProvidersFromInfraConfig() {
|
|||
|
||||
const allowedAuthProviders: string[] =
|
||||
env['INFRA'].VITE_ALLOWED_AUTH_PROVIDERS.split(',');
|
||||
let configuredAuthProviders: string[] = [];
|
||||
const configuredAuthProviders: string[] = [];
|
||||
|
||||
const addProviderIfConfigured = (provider) => {
|
||||
const configParameters: string[] = AuthProviderConfigurations[provider];
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { InfraConfigService } from './infra-config.service';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
import { SiteController } from './infra-config.controller';
|
||||
import { InfraConfigResolver } from './infra-config.resolver';
|
||||
import { PubSubModule } from 'src/pubsub/pubsub.module';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, PubSubModule],
|
||||
providers: [InfraConfigResolver, InfraConfigService],
|
||||
exports: [InfraConfigService],
|
||||
controllers: [SiteController],
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ const mockPrisma = mockDeep<PrismaService>();
|
|||
const mockConfigService = mockDeep<ConfigService>();
|
||||
const mockPubsub = mockDeep<PubSubService>();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const infraConfigService = new InfraConfigService(
|
||||
mockPrisma,
|
||||
mockConfigService,
|
||||
|
|
@ -66,90 +64,84 @@ beforeEach(() => {
|
|||
describe('InfraConfigService', () => {
|
||||
describe('update', () => {
|
||||
it('should update the infra config without backend server restart', async () => {
|
||||
const name = InfraConfigEnum.GOOGLE_CLIENT_ID;
|
||||
const value = 'true';
|
||||
const name = dbInfraConfigs[0].name;
|
||||
const value = 'newValue';
|
||||
|
||||
// @ts-ignore
|
||||
mockPrisma.infraConfig.findUnique.mockResolvedValueOnce({
|
||||
isEncrypted: false,
|
||||
});
|
||||
mockPrisma.infraConfig.findUnique.mockResolvedValueOnce(
|
||||
dbInfraConfigs[0],
|
||||
);
|
||||
mockPrisma.infraConfig.update.mockResolvedValueOnce({
|
||||
id: '',
|
||||
...dbInfraConfigs[0],
|
||||
name,
|
||||
value,
|
||||
lastSyncedEnvFileValue: value,
|
||||
isEncrypted: false,
|
||||
createdOn: new Date(),
|
||||
updatedOn: new Date(),
|
||||
});
|
||||
|
||||
jest.spyOn(helper, 'stopApp').mockReturnValueOnce();
|
||||
const result = await infraConfigService.update(name, value);
|
||||
const result = await infraConfigService.update(
|
||||
name as InfraConfigEnum,
|
||||
value,
|
||||
);
|
||||
|
||||
expect(helper.stopApp).not.toHaveBeenCalled();
|
||||
expect(result).toEqualRight({ name, value });
|
||||
});
|
||||
|
||||
it('should update the infra config with backend server restart', async () => {
|
||||
const name = InfraConfigEnum.GOOGLE_CLIENT_ID;
|
||||
const value = 'true';
|
||||
const name = dbInfraConfigs[0].name;
|
||||
const value = 'newValue';
|
||||
|
||||
// @ts-ignore
|
||||
mockPrisma.infraConfig.findUnique.mockResolvedValueOnce({
|
||||
isEncrypted: false,
|
||||
});
|
||||
mockPrisma.infraConfig.findUnique.mockResolvedValueOnce(
|
||||
dbInfraConfigs[0],
|
||||
);
|
||||
mockPrisma.infraConfig.update.mockResolvedValueOnce({
|
||||
id: '',
|
||||
...dbInfraConfigs[0],
|
||||
name,
|
||||
value,
|
||||
lastSyncedEnvFileValue: value,
|
||||
isEncrypted: false,
|
||||
createdOn: new Date(),
|
||||
updatedOn: new Date(),
|
||||
});
|
||||
jest.spyOn(helper, 'stopApp').mockReturnValueOnce();
|
||||
|
||||
const result = await infraConfigService.update(name, value, true);
|
||||
const result = await infraConfigService.update(
|
||||
name as InfraConfigEnum,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
|
||||
expect(helper.stopApp).toHaveBeenCalledTimes(1);
|
||||
expect(result).toEqualRight({ name, value });
|
||||
});
|
||||
|
||||
it('should update the infra config', async () => {
|
||||
const name = InfraConfigEnum.GOOGLE_CLIENT_ID;
|
||||
const value = 'true';
|
||||
const name = dbInfraConfigs[0].name;
|
||||
const value = 'newValue';
|
||||
|
||||
// @ts-ignore
|
||||
mockPrisma.infraConfig.findUnique.mockResolvedValueOnce({
|
||||
isEncrypted: false,
|
||||
});
|
||||
mockPrisma.infraConfig.findUnique.mockResolvedValueOnce(
|
||||
dbInfraConfigs[0],
|
||||
);
|
||||
mockPrisma.infraConfig.update.mockResolvedValueOnce({
|
||||
id: '',
|
||||
...dbInfraConfigs[0],
|
||||
name,
|
||||
value,
|
||||
lastSyncedEnvFileValue: value,
|
||||
isEncrypted: false,
|
||||
createdOn: new Date(),
|
||||
updatedOn: new Date(),
|
||||
});
|
||||
jest.spyOn(helper, 'stopApp').mockReturnValueOnce();
|
||||
|
||||
const result = await infraConfigService.update(name, value);
|
||||
const result = await infraConfigService.update(
|
||||
name as InfraConfigEnum,
|
||||
value,
|
||||
);
|
||||
expect(result).toEqualRight({ name, value });
|
||||
});
|
||||
|
||||
it('should pass correct params to prisma update', async () => {
|
||||
const name = InfraConfigEnum.GOOGLE_CLIENT_ID;
|
||||
const value = 'true';
|
||||
const name = dbInfraConfigs[0].name;
|
||||
const value = 'newValue';
|
||||
|
||||
// @ts-ignore
|
||||
mockPrisma.infraConfig.findUnique.mockResolvedValueOnce({
|
||||
isEncrypted: false,
|
||||
});
|
||||
mockPrisma.infraConfig.findUnique.mockResolvedValueOnce(
|
||||
dbInfraConfigs[0],
|
||||
);
|
||||
|
||||
jest.spyOn(helper, 'stopApp').mockReturnValueOnce();
|
||||
|
||||
await infraConfigService.update(name, value);
|
||||
await infraConfigService.update(name as InfraConfigEnum, value);
|
||||
|
||||
expect(mockPrisma.infraConfig.update).toHaveBeenCalledWith({
|
||||
where: { name },
|
||||
|
|
@ -171,19 +163,13 @@ describe('InfraConfigService', () => {
|
|||
|
||||
describe('get', () => {
|
||||
it('should get the infra config', async () => {
|
||||
const name = InfraConfigEnum.GOOGLE_CLIENT_ID;
|
||||
const value = 'true';
|
||||
const name = dbInfraConfigs[0].name;
|
||||
const value = dbInfraConfigs[0].value;
|
||||
|
||||
mockPrisma.infraConfig.findUniqueOrThrow.mockResolvedValueOnce({
|
||||
id: '',
|
||||
name,
|
||||
value,
|
||||
lastSyncedEnvFileValue: value,
|
||||
isEncrypted: false,
|
||||
createdOn: new Date(),
|
||||
updatedOn: new Date(),
|
||||
});
|
||||
const result = await infraConfigService.get(name);
|
||||
mockPrisma.infraConfig.findUniqueOrThrow.mockResolvedValueOnce(
|
||||
dbInfraConfigs[0],
|
||||
);
|
||||
const result = await infraConfigService.get(name as InfraConfigEnum);
|
||||
expect(result).toEqualRight({ name, value });
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ export class InfraConfigService implements OnModuleInit {
|
|||
* @param dbInfraConfig database InfraConfig
|
||||
* @returns InfraConfig model
|
||||
*/
|
||||
cast(dbInfraConfig: DBInfraConfig) {
|
||||
private cast(dbInfraConfig: DBInfraConfig) {
|
||||
switch (dbInfraConfig.name) {
|
||||
case InfraConfigEnum.USER_HISTORY_STORE_ENABLED:
|
||||
dbInfraConfig.value =
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
import { InfraTokenResolver } from './infra-token.resolver';
|
||||
import { InfraTokenService } from './infra-token.service';
|
||||
import { InfraTokensController } from './infra-token.controller';
|
||||
|
|
@ -7,7 +6,7 @@ import { AdminModule } from 'src/admin/admin.module';
|
|||
import { UserModule } from 'src/user/user.module';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, AdminModule, UserModule],
|
||||
imports: [AdminModule, UserModule],
|
||||
controllers: [InfraTokensController],
|
||||
providers: [InfraTokenResolver, InfraTokenService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import { Expose, Transform, Type } from 'class-transformer';
|
||||
import { Expose, Type } from 'class-transformer';
|
||||
import {
|
||||
ArrayMinSize,
|
||||
IsArray,
|
||||
IsBoolean,
|
||||
IsEmail,
|
||||
IsNotEmpty,
|
||||
IsOptional,
|
||||
IsString,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export class MailerModule {
|
|||
// If mailer is ENABLED, return the module with configuration (service, etc.)
|
||||
|
||||
// Determine transport configuration based on custom config flag
|
||||
let transportOption = getTransportOption(env, config);
|
||||
const transportOption = getTransportOption(env, config);
|
||||
// Get mailer address from environment or config
|
||||
const mailerAddressFrom = getMailerAddressFrom(env, config);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import { emitGQLSchemaFile } from './gql-schema';
|
|||
import { checkEnvironmentAuthProvider } from './utils';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||
import { InfraTokensController } from './infra-token/infra-token.controller';
|
||||
import { InfraTokenModule } from './infra-token/infra-token.module';
|
||||
|
||||
function setupSwagger(app) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { PosthogService } from './posthog.service';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
import { PostHogService } from './posthog.service';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule],
|
||||
providers: [PosthogService],
|
||||
providers: [PostHogService],
|
||||
})
|
||||
export class PosthogModule {}
|
||||
export class PostHogModule {}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,21 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { PostHog } from 'posthog-node';
|
||||
import { Cron, CronExpression, SchedulerRegistry } from '@nestjs/schedule';
|
||||
import { CronExpression, SchedulerRegistry } from '@nestjs/schedule';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { PrismaService } from 'src/prisma/prisma.service';
|
||||
import { CronJob } from 'cron';
|
||||
import { POSTHOG_CLIENT_NOT_INITIALIZED } from 'src/errors';
|
||||
import { throwErr } from 'src/utils';
|
||||
|
||||
@Injectable()
|
||||
export class PosthogService {
|
||||
export class PostHogService {
|
||||
private postHogClient: PostHog;
|
||||
private POSTHOG_API_KEY = 'phc_9CipPajQC22mSkk2wxe2TXsUA0Ysyupe8dt5KQQELqx';
|
||||
|
||||
constructor(
|
||||
private readonly configService: ConfigService,
|
||||
private readonly prismaService: PrismaService,
|
||||
private schedulerRegistry: SchedulerRegistry,
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly schedulerRegistry: SchedulerRegistry,
|
||||
) {}
|
||||
|
||||
async onModuleInit() {
|
||||
|
|
@ -48,8 +49,8 @@ export class PosthogService {
|
|||
event: 'sh_instance',
|
||||
properties: {
|
||||
type: 'COMMUNITY',
|
||||
total_user_count: await this.prismaService.user.count(),
|
||||
total_workspace_count: await this.prismaService.team.count(),
|
||||
total_user_count: await this.prisma.user.count(),
|
||||
total_workspace_count: await this.prisma.team.count(),
|
||||
version: this.configService.get('npm_package_version'),
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Module } from '@nestjs/common/decorators';
|
||||
import { Global, Module } from '@nestjs/common/decorators';
|
||||
import { PrismaService } from './prisma.service';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
providers: [PrismaService],
|
||||
exports: [PrismaService],
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { Global, Module } from '@nestjs/common';
|
||||
import { PubSubService } from './pubsub.service';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
providers: [PubSubService],
|
||||
exports: [PubSubService],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Field, ID, ObjectType } from '@nestjs/graphql';
|
||||
import { User } from 'src/user/user.model';
|
||||
|
||||
@ObjectType()
|
||||
export class Shortcode {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
import { PubSubModule } from 'src/pubsub/pubsub.module';
|
||||
import { UserModule } from 'src/user/user.module';
|
||||
import { ShortcodeResolver } from './shortcode.resolver';
|
||||
import { ShortcodeService } from './shortcode.service';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, UserModule, PubSubModule],
|
||||
imports: [UserModule],
|
||||
providers: [ShortcodeService, ShortcodeResolver],
|
||||
exports: [ShortcodeService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
} from '@nestjs/graphql';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import { UseGuards } from '@nestjs/common';
|
||||
import { Shortcode, ShortcodeWithUserEmail } from './shortcode.model';
|
||||
import { Shortcode } from './shortcode.model';
|
||||
import { ShortcodeService } from './shortcode.service';
|
||||
import { throwErr } from 'src/utils';
|
||||
import { GqlUser } from 'src/decorators/gql-user.decorator';
|
||||
|
|
@ -19,7 +19,6 @@ import { AuthUser } from '../types/AuthUser';
|
|||
import { PaginationArgs } from 'src/types/input-types.args';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
import { GqlAdminGuard } from 'src/admin/guards/gql-admin.guard';
|
||||
|
||||
@UseGuards(GqlThrottlerGuard)
|
||||
@Resolver(() => Shortcode)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { mockDeep, mockReset } from 'jest-mock-extended';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import {
|
||||
INVALID_EMAIL,
|
||||
SHORTCODE_INVALID_PROPERTIES_JSON,
|
||||
SHORTCODE_INVALID_REQUEST_JSON,
|
||||
SHORTCODE_NOT_FOUND,
|
||||
|
|
@ -11,27 +10,15 @@ import { Shortcode, ShortcodeWithUserEmail } from './shortcode.model';
|
|||
import { ShortcodeService } from './shortcode.service';
|
||||
import { UserService } from 'src/user/user.service';
|
||||
import { AuthUser } from 'src/types/AuthUser';
|
||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||
|
||||
const mockPrisma = mockDeep<PrismaService>();
|
||||
const mockPubSub = mockDeep<PubSubService>();
|
||||
const mockUserService = mockDeep<UserService>();
|
||||
|
||||
const mockPubSub = {
|
||||
publish: jest.fn().mockResolvedValue(null),
|
||||
};
|
||||
|
||||
const mockDocFunc = jest.fn();
|
||||
|
||||
const mockFB = {
|
||||
firestore: {
|
||||
doc: mockDocFunc,
|
||||
},
|
||||
};
|
||||
const mockUserService = new UserService(mockPrisma as any, mockPubSub as any);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const shortcodeService = new ShortcodeService(
|
||||
mockPrisma,
|
||||
mockPubSub as any,
|
||||
mockPubSub,
|
||||
mockUserService,
|
||||
);
|
||||
|
||||
|
|
@ -286,7 +273,7 @@ describe('ShortcodeService', () => {
|
|||
);
|
||||
mockPrisma.shortcode.create.mockResolvedValueOnce(mockShortcode);
|
||||
|
||||
const result = await shortcodeService.createShortcode('{}', null, user);
|
||||
await shortcodeService.createShortcode('{}', null, user);
|
||||
|
||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||
`shortcode/${mockShortcode.creatorUid}/created`,
|
||||
|
|
@ -306,7 +293,7 @@ describe('ShortcodeService', () => {
|
|||
);
|
||||
mockPrisma.shortcode.create.mockResolvedValueOnce(mockEmbed);
|
||||
|
||||
const result = await shortcodeService.createShortcode('{}', '{}', user);
|
||||
await shortcodeService.createShortcode('{}', '{}', user);
|
||||
|
||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||
`shortcode/${mockEmbed.creatorUid}/created`,
|
||||
|
|
@ -365,7 +352,7 @@ describe('ShortcodeService', () => {
|
|||
test('should send pubsub message to `shortcode/{uid}/revoked` on successful deletion of Shortcode', async () => {
|
||||
mockPrisma.shortcode.delete.mockResolvedValueOnce(mockEmbed);
|
||||
|
||||
const result = await shortcodeService.revokeShortCode(
|
||||
await shortcodeService.revokeShortCode(
|
||||
mockEmbed.id,
|
||||
mockEmbed.creatorUid,
|
||||
);
|
||||
|
|
@ -456,7 +443,7 @@ describe('ShortcodeService', () => {
|
|||
embedProperties: '{"foo":"bar"}',
|
||||
});
|
||||
|
||||
const result = await shortcodeService.updateEmbedProperties(
|
||||
await shortcodeService.updateEmbedProperties(
|
||||
mockEmbed.id,
|
||||
user.uid,
|
||||
'{"foo":"bar"}',
|
||||
|
|
|
|||
|
|
@ -36,9 +36,8 @@ export class GqlCollectionTeamMemberGuard implements CanActivate {
|
|||
const { collectionID } = gqlExecCtx.getArgs<{ collectionID: string }>();
|
||||
if (!collectionID) throw new Error(BUG_TEAM_COLL_NO_COLL_ID);
|
||||
|
||||
const collection = await this.teamCollectionService.getCollection(
|
||||
collectionID,
|
||||
);
|
||||
const collection =
|
||||
await this.teamCollectionService.getCollection(collectionID);
|
||||
if (E.isLeft(collection)) throw new Error(TEAM_INVALID_COLL_ID);
|
||||
|
||||
const member = await this.teamService.getTeamMember(
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { PrismaModule } from '../prisma/prisma.module';
|
||||
import { TeamCollectionService } from './team-collection.service';
|
||||
import { TeamCollectionResolver } from './team-collection.resolver';
|
||||
import { GqlCollectionTeamMemberGuard } from './guards/gql-collection-team-member.guard';
|
||||
import { TeamModule } from '../team/team.module';
|
||||
import { UserModule } from '../user/user.module';
|
||||
import { PubSubModule } from '../pubsub/pubsub.module';
|
||||
import { TeamCollectionController } from './team-collection.controller';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, TeamModule, UserModule, PubSubModule],
|
||||
imports: [TeamModule, UserModule],
|
||||
providers: [
|
||||
TeamCollectionService,
|
||||
TeamCollectionResolver,
|
||||
|
|
|
|||
|
|
@ -94,9 +94,8 @@ export class TeamCollectionResolver {
|
|||
@Args({ name: 'teamID', description: 'ID of the team', type: () => ID })
|
||||
teamID: string,
|
||||
) {
|
||||
const jsonString = await this.teamCollectionService.exportCollectionsToJSON(
|
||||
teamID,
|
||||
);
|
||||
const jsonString =
|
||||
await this.teamCollectionService.exportCollectionsToJSON(teamID);
|
||||
|
||||
if (E.isLeft(jsonString)) throwErr(jsonString.left as string);
|
||||
return jsonString.right;
|
||||
|
|
@ -167,9 +166,8 @@ export class TeamCollectionResolver {
|
|||
})
|
||||
collectionID: string,
|
||||
) {
|
||||
const teamCollections = await this.teamCollectionService.getCollection(
|
||||
collectionID,
|
||||
);
|
||||
const teamCollections =
|
||||
await this.teamCollectionService.getCollection(collectionID);
|
||||
|
||||
if (E.isLeft(teamCollections)) throwErr(teamCollections.left);
|
||||
return <TeamCollection>{
|
||||
|
|
@ -307,9 +305,8 @@ export class TeamCollectionResolver {
|
|||
})
|
||||
collectionID: string,
|
||||
) {
|
||||
const result = await this.teamCollectionService.deleteCollection(
|
||||
collectionID,
|
||||
);
|
||||
const result =
|
||||
await this.teamCollectionService.deleteCollection(collectionID);
|
||||
|
||||
if (E.isLeft(result)) throwErr(result.left);
|
||||
return result.right;
|
||||
|
|
|
|||
|
|
@ -84,13 +84,6 @@ const rootTeamCollection_2: DBTeamCollection = {
|
|||
updatedOn: currentTime,
|
||||
};
|
||||
|
||||
const rootTeamCollection_2Casted: TeamCollection = {
|
||||
id: 'erv',
|
||||
parentID: null,
|
||||
data: JSON.stringify(rootTeamCollection_2.data),
|
||||
title: 'Root Collection 1',
|
||||
};
|
||||
|
||||
const childTeamCollection: DBTeamCollection = {
|
||||
id: 'rfe',
|
||||
orderIndex: 1,
|
||||
|
|
@ -537,9 +530,8 @@ describe('getParentOfCollection', () => {
|
|||
test('should return null with invalid collectionID', async () => {
|
||||
mockPrisma.teamCollection.findUnique.mockResolvedValueOnce(null);
|
||||
|
||||
const result = await teamCollectionService.getParentOfCollection(
|
||||
'invalidID',
|
||||
);
|
||||
const result =
|
||||
await teamCollectionService.getParentOfCollection('invalidID');
|
||||
expect(result).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
|
@ -756,7 +748,7 @@ describe('createCollection', () => {
|
|||
mockPrisma.teamCollection.findMany.mockResolvedValueOnce([]);
|
||||
mockPrisma.teamCollection.create.mockResolvedValueOnce(childTeamCollection);
|
||||
|
||||
const result = await teamCollectionService.createCollection(
|
||||
await teamCollectionService.createCollection(
|
||||
childTeamCollection.teamID,
|
||||
childTeamCollection.title,
|
||||
JSON.stringify(rootTeamCollection.data),
|
||||
|
|
@ -779,7 +771,7 @@ describe('createCollection', () => {
|
|||
mockPrisma.teamCollection.findMany.mockResolvedValueOnce([]);
|
||||
mockPrisma.teamCollection.create.mockResolvedValueOnce(rootTeamCollection);
|
||||
|
||||
const result = await teamCollectionService.createCollection(
|
||||
await teamCollectionService.createCollection(
|
||||
rootTeamCollection.teamID,
|
||||
'abcdefg',
|
||||
JSON.stringify(rootTeamCollection.data),
|
||||
|
|
@ -849,7 +841,7 @@ describe('renameCollection', () => {
|
|||
title: 'NewTitle',
|
||||
});
|
||||
|
||||
const result = await teamCollectionService.renameCollection(
|
||||
await teamCollectionService.renameCollection(
|
||||
rootTeamCollection.id,
|
||||
'NewTitle',
|
||||
);
|
||||
|
|
@ -938,9 +930,7 @@ describe('deleteCollection', () => {
|
|||
// deleteCollectionData --> removeUserCollection
|
||||
mockPrisma.teamCollection.delete.mockResolvedValueOnce(rootTeamCollection);
|
||||
|
||||
const result = await teamCollectionService.deleteCollection(
|
||||
rootTeamCollection.id,
|
||||
);
|
||||
await teamCollectionService.deleteCollection(rootTeamCollection.id);
|
||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||
`team_coll/${rootTeamCollection.teamID}/coll_removed`,
|
||||
rootTeamCollection.id,
|
||||
|
|
@ -1113,10 +1103,7 @@ describe('moveCollection', () => {
|
|||
orderIndex: 2,
|
||||
});
|
||||
|
||||
const result = await teamCollectionService.moveCollection(
|
||||
childTeamCollection.id,
|
||||
null,
|
||||
);
|
||||
await teamCollectionService.moveCollection(childTeamCollection.id, null);
|
||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||
`team_coll/${childTeamCollection.teamID}/coll_moved`,
|
||||
{
|
||||
|
|
@ -1194,7 +1181,7 @@ describe('moveCollection', () => {
|
|||
orderIndex: 1,
|
||||
});
|
||||
|
||||
const result = await teamCollectionService.moveCollection(
|
||||
await teamCollectionService.moveCollection(
|
||||
rootTeamCollection.id,
|
||||
childTeamCollection_2.id,
|
||||
);
|
||||
|
|
@ -1275,7 +1262,7 @@ describe('moveCollection', () => {
|
|||
orderIndex: 1,
|
||||
});
|
||||
|
||||
const result = await teamCollectionService.moveCollection(
|
||||
await teamCollectionService.moveCollection(
|
||||
childTeamCollection.id,
|
||||
childTeamCollection_2.id,
|
||||
);
|
||||
|
|
@ -1372,7 +1359,7 @@ describe('updateCollectionOrder', () => {
|
|||
orderIndex: rootTeamCollectionList.length,
|
||||
});
|
||||
|
||||
const result = await teamCollectionService.updateCollectionOrder(
|
||||
await teamCollectionService.updateCollectionOrder(
|
||||
rootTeamCollectionList[4].id,
|
||||
null,
|
||||
);
|
||||
|
|
@ -1453,7 +1440,7 @@ describe('updateCollectionOrder', () => {
|
|||
.mockResolvedValueOnce(childTeamCollectionList[4])
|
||||
.mockResolvedValueOnce(childTeamCollectionList[2]);
|
||||
|
||||
const result = await teamCollectionService.updateCollectionOrder(
|
||||
await teamCollectionService.updateCollectionOrder(
|
||||
childTeamCollectionList[4].id,
|
||||
childTeamCollectionList[2].id,
|
||||
);
|
||||
|
|
@ -1520,7 +1507,7 @@ describe('importCollectionsFromJSON', () => {
|
|||
mockPrisma.teamCollection.findMany.mockResolvedValueOnce([]);
|
||||
mockPrisma.$transaction.mockResolvedValueOnce([rootTeamCollection]);
|
||||
|
||||
const result = await teamCollectionService.importCollectionsFromJSON(
|
||||
await teamCollectionService.importCollectionsFromJSON(
|
||||
jsonString,
|
||||
rootTeamCollection.teamID,
|
||||
null,
|
||||
|
|
@ -1639,7 +1626,7 @@ describe('replaceCollectionsWithJSON', () => {
|
|||
mockPrisma.teamCollection.findMany.mockResolvedValueOnce([]);
|
||||
mockPrisma.$transaction.mockResolvedValueOnce([rootTeamCollection]);
|
||||
|
||||
const result = await teamCollectionService.replaceCollectionsWithJSON(
|
||||
await teamCollectionService.replaceCollectionsWithJSON(
|
||||
jsonString,
|
||||
rootTeamCollection.teamID,
|
||||
null,
|
||||
|
|
@ -1731,7 +1718,7 @@ describe('updateTeamCollection', () => {
|
|||
test('should send pubsub message to "team_coll/<teamID>/coll_updated" if TeamCollection is updated successfully', async () => {
|
||||
mockPrisma.teamCollection.update.mockResolvedValueOnce(rootTeamCollection);
|
||||
|
||||
const result = await teamCollectionService.updateTeamCollection(
|
||||
await teamCollectionService.updateTeamCollection(
|
||||
rootTeamCollection.id,
|
||||
JSON.stringify(rootTeamCollection.data),
|
||||
rootTeamCollection.title,
|
||||
|
|
|
|||
|
|
@ -932,7 +932,7 @@ export class TeamCollectionService {
|
|||
},
|
||||
});
|
||||
// Step 2: Update orderIndex of collection to length of list
|
||||
const updatedTeamCollection = await tx.teamCollection.update({
|
||||
await tx.teamCollection.update({
|
||||
where: { id: collection.right.id },
|
||||
data: {
|
||||
orderIndex: await this.getCollectionCount(
|
||||
|
|
@ -989,7 +989,7 @@ export class TeamCollectionService {
|
|||
},
|
||||
});
|
||||
// Step 3: Update OrderIndex of collection
|
||||
const updatedTeamCollection = await tx.teamCollection.update({
|
||||
await tx.teamCollection.update({
|
||||
where: { id: collection.right.id },
|
||||
data: {
|
||||
orderIndex: isMovingUp
|
||||
|
|
@ -1262,9 +1262,8 @@ export class TeamCollectionService {
|
|||
)
|
||||
SELECT * FROM collection_tree;
|
||||
`;
|
||||
const res = await this.prisma.$queryRaw<ParentTreeQueryReturnType[]>(
|
||||
query,
|
||||
);
|
||||
const res =
|
||||
await this.prisma.$queryRaw<ParentTreeQueryReturnType[]>(query);
|
||||
|
||||
const collectionParentTree = this.generateParentTree(res);
|
||||
return E.right(collectionParentTree);
|
||||
|
|
@ -1353,9 +1352,8 @@ export class TeamCollectionService {
|
|||
SELECT * FROM request_collection_tree;
|
||||
|
||||
`;
|
||||
const res = await this.prisma.$queryRaw<ParentTreeQueryReturnType[]>(
|
||||
query,
|
||||
);
|
||||
const res =
|
||||
await this.prisma.$queryRaw<ParentTreeQueryReturnType[]>(query);
|
||||
|
||||
const requestParentTree = this.generateParentTree(res);
|
||||
return E.right(requestParentTree);
|
||||
|
|
|
|||
|
|
@ -2,14 +2,12 @@ import { Module } from '@nestjs/common';
|
|||
import { TeamEnvironmentsService } from './team-environments.service';
|
||||
import { TeamEnvironmentsResolver } from './team-environments.resolver';
|
||||
import { UserModule } from 'src/user/user.module';
|
||||
import { PubSubModule } from 'src/pubsub/pubsub.module';
|
||||
import { TeamModule } from 'src/team/team.module';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
import { GqlTeamEnvTeamGuard } from './gql-team-env-team.guard';
|
||||
import { TeamEnvsTeamResolver } from './team.resolver';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, PubSubModule, UserModule, TeamModule],
|
||||
imports: [UserModule, TeamModule],
|
||||
providers: [
|
||||
TeamEnvironmentsResolver,
|
||||
TeamEnvironmentsService,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { UseGuards } from '@nestjs/common';
|
||||
import { Resolver, Mutation, Args, Subscription, ID } from '@nestjs/graphql';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
import { pipe } from 'fp-ts/function';
|
||||
import * as TE from 'fp-ts/TaskEither';
|
||||
import { GqlAuthGuard } from 'src/guards/gql-auth.guard';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||
|
|
@ -61,9 +59,8 @@ export class TeamEnvironmentsResolver {
|
|||
})
|
||||
id: string,
|
||||
): Promise<boolean> {
|
||||
const isDeleted = await this.teamEnvironmentsService.deleteTeamEnvironment(
|
||||
id,
|
||||
);
|
||||
const isDeleted =
|
||||
await this.teamEnvironmentsService.deleteTeamEnvironment(id);
|
||||
|
||||
if (E.isLeft(isDeleted)) throwErr(isDeleted.left);
|
||||
return isDeleted.right;
|
||||
|
|
@ -125,9 +122,8 @@ export class TeamEnvironmentsResolver {
|
|||
})
|
||||
id: string,
|
||||
): Promise<TeamEnvironment> {
|
||||
const res = await this.teamEnvironmentsService.createDuplicateEnvironment(
|
||||
id,
|
||||
);
|
||||
const res =
|
||||
await this.teamEnvironmentsService.createDuplicateEnvironment(id);
|
||||
|
||||
if (E.isLeft(res)) throwErr(res.left);
|
||||
return res.right;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import { PrismaService } from 'src/prisma/prisma.service';
|
|||
import { TeamEnvironment } from './team-environments.model';
|
||||
import { TeamEnvironmentsService } from './team-environments.service';
|
||||
import {
|
||||
JSON_INVALID,
|
||||
TEAM_ENVIRONMENT_NOT_FOUND,
|
||||
TEAM_ENVIRONMENT_SHORT_NAME,
|
||||
TEAM_MEMBER_NOT_FOUND,
|
||||
|
|
@ -92,7 +91,7 @@ describe('TeamEnvironmentsService', () => {
|
|||
test('should send pubsub message to "team_environment/<teamID>/created" if team environment is created successfully', async () => {
|
||||
mockPrisma.teamEnvironment.create.mockResolvedValue(teamEnvironment);
|
||||
|
||||
const result = await teamEnvironmentsService.createTeamEnvironment(
|
||||
await teamEnvironmentsService.createTeamEnvironment(
|
||||
teamEnvironment.name,
|
||||
teamEnvironment.teamID,
|
||||
JSON.stringify(teamEnvironment.variables),
|
||||
|
|
@ -122,9 +121,8 @@ describe('TeamEnvironmentsService', () => {
|
|||
test('should throw TEAM_ENVIRONMMENT_NOT_FOUND if given id is invalid', async () => {
|
||||
mockPrisma.teamEnvironment.delete.mockRejectedValue('RecordNotFound');
|
||||
|
||||
const result = await teamEnvironmentsService.deleteTeamEnvironment(
|
||||
'invalidid',
|
||||
);
|
||||
const result =
|
||||
await teamEnvironmentsService.deleteTeamEnvironment('invalidid');
|
||||
|
||||
expect(result).toEqualLeft(TEAM_ENVIRONMENT_NOT_FOUND);
|
||||
});
|
||||
|
|
@ -132,9 +130,7 @@ describe('TeamEnvironmentsService', () => {
|
|||
test('should send pubsub message to "team_environment/<teamID>/deleted" if team environment is deleted successfully', async () => {
|
||||
mockPrisma.teamEnvironment.delete.mockResolvedValueOnce(teamEnvironment);
|
||||
|
||||
const result = await teamEnvironmentsService.deleteTeamEnvironment(
|
||||
teamEnvironment.id,
|
||||
);
|
||||
await teamEnvironmentsService.deleteTeamEnvironment(teamEnvironment.id);
|
||||
|
||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||
`team_environment/${teamEnvironment.teamID}/deleted`,
|
||||
|
|
@ -244,7 +240,7 @@ describe('TeamEnvironmentsService', () => {
|
|||
test('should send pubsub message to "team_environment/<teamID>/updated" if team environment is updated successfully', async () => {
|
||||
mockPrisma.teamEnvironment.update.mockResolvedValueOnce(teamEnvironment);
|
||||
|
||||
const result = await teamEnvironmentsService.updateTeamEnvironment(
|
||||
await teamEnvironmentsService.updateTeamEnvironment(
|
||||
teamEnvironment.id,
|
||||
teamEnvironment.name,
|
||||
JSON.stringify([{ key: 'value' }]),
|
||||
|
|
@ -289,10 +285,9 @@ describe('TeamEnvironmentsService', () => {
|
|||
test('should send pubsub message to "team_environment/<teamID>/updated" if team environment is updated successfully', async () => {
|
||||
mockPrisma.teamEnvironment.update.mockResolvedValueOnce(teamEnvironment);
|
||||
|
||||
const result =
|
||||
await teamEnvironmentsService.deleteAllVariablesFromTeamEnvironment(
|
||||
teamEnvironment.id,
|
||||
);
|
||||
await teamEnvironmentsService.deleteAllVariablesFromTeamEnvironment(
|
||||
teamEnvironment.id,
|
||||
);
|
||||
|
||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||
`team_environment/${teamEnvironment.teamID}/updated`,
|
||||
|
|
@ -348,7 +343,7 @@ describe('TeamEnvironmentsService', () => {
|
|||
...teamEnvironment,
|
||||
});
|
||||
|
||||
const result = await teamEnvironmentsService.createDuplicateEnvironment(
|
||||
await teamEnvironmentsService.createDuplicateEnvironment(
|
||||
teamEnvironment.id,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
import { PubSubModule } from 'src/pubsub/pubsub.module';
|
||||
import { TeamModule } from 'src/team/team.module';
|
||||
import { UserModule } from 'src/user/user.module';
|
||||
import { TeamInvitationResolver } from './team-invitation.resolver';
|
||||
|
|
@ -11,7 +9,7 @@ import { TeamInviteeGuard } from './team-invitee.guard';
|
|||
import { TeamTeamInviteExtResolver } from './team-teaminvite-ext.resolver';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, TeamModule, PubSubModule, UserModule],
|
||||
imports: [TeamModule, UserModule],
|
||||
providers: [
|
||||
TeamInvitationService,
|
||||
TeamInvitationResolver,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ export class TeamInvitationResolver {
|
|||
private readonly userService: UserService,
|
||||
private readonly teamService: TeamService,
|
||||
private readonly teamInvitationService: TeamInvitationService,
|
||||
|
||||
private readonly pubsub: PubSubService,
|
||||
) {}
|
||||
|
||||
|
|
@ -85,9 +84,8 @@ export class TeamInvitationResolver {
|
|||
})
|
||||
inviteID: string,
|
||||
): Promise<TeamInvitation> {
|
||||
const teamInvitation = await this.teamInvitationService.getInvitation(
|
||||
inviteID,
|
||||
);
|
||||
const teamInvitation =
|
||||
await this.teamInvitationService.getInvitation(inviteID);
|
||||
if (O.isNone(teamInvitation)) throwErr(TEAM_INVITE_NO_INVITE_FOUND);
|
||||
return teamInvitation.value;
|
||||
}
|
||||
|
|
@ -125,9 +123,8 @@ export class TeamInvitationResolver {
|
|||
})
|
||||
inviteID: string,
|
||||
): Promise<true> {
|
||||
const isRevoked = await this.teamInvitationService.revokeInvitation(
|
||||
inviteID,
|
||||
);
|
||||
const isRevoked =
|
||||
await this.teamInvitationService.revokeInvitation(inviteID);
|
||||
if (E.isLeft(isRevoked)) throwErr(isRevoked.left);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export class TeamInvitationService {
|
|||
* @param dbTeamInvitation database TeamInvitation
|
||||
* @returns TeamInvitation model
|
||||
*/
|
||||
cast(dbTeamInvitation: DBTeamInvitation): TeamInvitation {
|
||||
private cast(dbTeamInvitation: DBTeamInvitation): TeamInvitation {
|
||||
return {
|
||||
...dbTeamInvitation,
|
||||
inviteeRole: TeamAccessRole[dbTeamInvitation.inviteeRole],
|
||||
|
|
|
|||
|
|
@ -36,9 +36,8 @@ export class GqlRequestTeamMemberGuard implements CanActivate {
|
|||
const { requestID } = gqlExecCtx.getArgs<{ requestID: string }>();
|
||||
if (!requestID) throw new Error(BUG_TEAM_REQ_NO_REQ_ID);
|
||||
|
||||
const team = await this.teamRequestService.getTeamOfRequestFromID(
|
||||
requestID,
|
||||
);
|
||||
const team =
|
||||
await this.teamRequestService.getTeamOfRequestFromID(requestID);
|
||||
if (O.isNone(team)) throw new Error(TEAM_REQ_NOT_FOUND);
|
||||
|
||||
const member = await this.teamService.getTeamMember(
|
||||
|
|
|
|||
|
|
@ -1,21 +1,13 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { TeamRequestService } from './team-request.service';
|
||||
import { TeamRequestResolver } from './team-request.resolver';
|
||||
import { PrismaModule } from '../prisma/prisma.module';
|
||||
import { TeamModule } from '../team/team.module';
|
||||
import { TeamCollectionModule } from '../team-collection/team-collection.module';
|
||||
import { GqlRequestTeamMemberGuard } from './guards/gql-request-team-member.guard';
|
||||
import { UserModule } from '../user/user.module';
|
||||
import { PubSubModule } from 'src/pubsub/pubsub.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
PrismaModule,
|
||||
TeamModule,
|
||||
TeamCollectionModule,
|
||||
UserModule,
|
||||
PubSubModule,
|
||||
],
|
||||
imports: [TeamModule, TeamCollectionModule, UserModule],
|
||||
providers: [
|
||||
TeamRequestService,
|
||||
TeamRequestResolver,
|
||||
|
|
|
|||
|
|
@ -57,9 +57,8 @@ export class TeamRequestResolver {
|
|||
complexity: 3,
|
||||
})
|
||||
async collection(@Parent() req: TeamRequest) {
|
||||
const teamCollection = await this.teamRequestService.getCollectionOfRequest(
|
||||
req,
|
||||
);
|
||||
const teamCollection =
|
||||
await this.teamRequestService.getCollectionOfRequest(req);
|
||||
if (E.isLeft(teamCollection)) throwErr(teamCollection.left);
|
||||
return teamCollection.right;
|
||||
}
|
||||
|
|
@ -196,9 +195,8 @@ export class TeamRequestResolver {
|
|||
})
|
||||
requestID: string,
|
||||
) {
|
||||
const isDeleted = await this.teamRequestService.deleteTeamRequest(
|
||||
requestID,
|
||||
);
|
||||
const isDeleted =
|
||||
await this.teamRequestService.deleteTeamRequest(requestID);
|
||||
if (E.isLeft(isDeleted)) throwErr(isDeleted.left);
|
||||
return isDeleted.right;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,9 @@ import { TeamResolver } from './team.resolver';
|
|||
import { UserModule } from '../user/user.module';
|
||||
import { TeamMemberResolver } from './team-member.resolver';
|
||||
import { GqlTeamMemberGuard } from './guards/gql-team-member.guard';
|
||||
import { PrismaModule } from '../prisma/prisma.module';
|
||||
import { PubSubModule } from '../pubsub/pubsub.module';
|
||||
|
||||
@Module({
|
||||
imports: [UserModule, PubSubModule, PrismaModule],
|
||||
imports: [UserModule],
|
||||
providers: [
|
||||
TeamService,
|
||||
TeamResolver,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { UserCollectionService } from './user-collection.service';
|
||||
import { UserCollectionResolver } from './user-collection.resolver';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
import { UserModule } from 'src/user/user.module';
|
||||
import { PubSubModule } from 'src/pubsub/pubsub.module';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, UserModule, PubSubModule],
|
||||
imports: [UserModule],
|
||||
providers: [UserCollectionService, UserCollectionResolver],
|
||||
exports: [UserCollectionService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -139,9 +139,8 @@ export class UserCollectionResolver {
|
|||
})
|
||||
userCollectionID: string,
|
||||
) {
|
||||
const userCollection = await this.userCollectionService.getUserCollection(
|
||||
userCollectionID,
|
||||
);
|
||||
const userCollection =
|
||||
await this.userCollectionService.getUserCollection(userCollectionID);
|
||||
|
||||
if (E.isLeft(userCollection)) throwErr(userCollection.left);
|
||||
return <UserCollection>{
|
||||
|
|
|
|||
|
|
@ -23,11 +23,7 @@ import { UserCollection } from './user-collections.model';
|
|||
const mockPrisma = mockDeep<PrismaService>();
|
||||
const mockPubSub = mockDeep<PubSubService>();
|
||||
|
||||
// @ts-ignore
|
||||
const userCollectionService = new UserCollectionService(
|
||||
mockPrisma,
|
||||
mockPubSub as any,
|
||||
);
|
||||
const userCollectionService = new UserCollectionService(mockPrisma, mockPubSub);
|
||||
|
||||
const currentTime = new Date();
|
||||
|
||||
|
|
@ -99,36 +95,6 @@ const rootRESTUserCollection_2: DBUserCollection = {
|
|||
data: {},
|
||||
};
|
||||
|
||||
const rootRESTUserCollection_2Casted: UserCollection = {
|
||||
id: '4gf',
|
||||
parentID: null,
|
||||
title: 'Root Collection 2',
|
||||
userID: user.uid,
|
||||
type: ReqType.REST,
|
||||
data: JSON.stringify(rootRESTUserCollection_2.data),
|
||||
};
|
||||
|
||||
const rootGQLUserCollection_2: DBUserCollection = {
|
||||
id: '4gf',
|
||||
orderIndex: 2,
|
||||
parentID: null,
|
||||
title: 'Root Collection 2',
|
||||
userUid: user.uid,
|
||||
type: ReqType.GQL,
|
||||
createdOn: currentTime,
|
||||
updatedOn: currentTime,
|
||||
data: {},
|
||||
};
|
||||
|
||||
const rootGQLUserCollection_2Casted: UserCollection = {
|
||||
id: '4gf',
|
||||
parentID: null,
|
||||
title: 'Root Collection 2',
|
||||
userID: user.uid,
|
||||
type: ReqType.GQL,
|
||||
data: JSON.stringify(rootGQLUserCollection_2.data),
|
||||
};
|
||||
|
||||
const childRESTUserCollection: DBUserCollection = {
|
||||
id: '234',
|
||||
orderIndex: 1,
|
||||
|
|
@ -192,27 +158,6 @@ const childRESTUserCollection_2Casted: UserCollection = {
|
|||
data: JSON.stringify({}),
|
||||
};
|
||||
|
||||
const childGQLUserCollection_2: DBUserCollection = {
|
||||
id: '0kn',
|
||||
orderIndex: 2,
|
||||
parentID: rootRESTUserCollection_2.id,
|
||||
title: 'Child Collection 2',
|
||||
userUid: user.uid,
|
||||
type: ReqType.GQL,
|
||||
createdOn: currentTime,
|
||||
updatedOn: currentTime,
|
||||
data: {},
|
||||
};
|
||||
|
||||
const childGQLUserCollection_2Casted: UserCollection = {
|
||||
id: '0kn',
|
||||
parentID: rootRESTUserCollection_2.id,
|
||||
title: 'Child Collection 2',
|
||||
userID: user.uid,
|
||||
type: ReqType.GQL,
|
||||
data: JSON.stringify({}),
|
||||
};
|
||||
|
||||
const childRESTUserCollectionList: DBUserCollection[] = [
|
||||
{
|
||||
id: '234',
|
||||
|
|
@ -639,9 +584,8 @@ describe('getParentOfUserCollection', () => {
|
|||
childRESTUserCollection,
|
||||
);
|
||||
|
||||
const result = await userCollectionService.getParentOfUserCollection(
|
||||
'invalidId',
|
||||
);
|
||||
const result =
|
||||
await userCollectionService.getParentOfUserCollection('invalidId');
|
||||
//TODO: check it not null
|
||||
expect(result).toEqual(null);
|
||||
});
|
||||
|
|
@ -899,7 +843,7 @@ describe('createUserCollection', () => {
|
|||
childRESTUserCollection,
|
||||
);
|
||||
|
||||
const result = await userCollectionService.createUserCollection(
|
||||
await userCollectionService.createUserCollection(
|
||||
user,
|
||||
childRESTUserCollection.title,
|
||||
JSON.stringify(childRESTUserCollection.data),
|
||||
|
|
@ -924,7 +868,7 @@ describe('createUserCollection', () => {
|
|||
childGQLUserCollection,
|
||||
);
|
||||
|
||||
const result = await userCollectionService.createUserCollection(
|
||||
await userCollectionService.createUserCollection(
|
||||
user,
|
||||
childGQLUserCollection.title,
|
||||
JSON.stringify(childGQLUserCollection.data),
|
||||
|
|
@ -949,7 +893,7 @@ describe('createUserCollection', () => {
|
|||
rootRESTUserCollection,
|
||||
);
|
||||
|
||||
const result = await userCollectionService.createUserCollection(
|
||||
await userCollectionService.createUserCollection(
|
||||
user,
|
||||
rootRESTUserCollection.title,
|
||||
JSON.stringify(rootRESTUserCollection.data),
|
||||
|
|
@ -974,7 +918,7 @@ describe('createUserCollection', () => {
|
|||
rootGQLUserCollection,
|
||||
);
|
||||
|
||||
const result = await userCollectionService.createUserCollection(
|
||||
await userCollectionService.createUserCollection(
|
||||
user,
|
||||
rootGQLUserCollection.title,
|
||||
JSON.stringify(rootGQLUserCollection.data),
|
||||
|
|
@ -1057,7 +1001,7 @@ describe('renameUserCollection', () => {
|
|||
title: 'NewTitle',
|
||||
});
|
||||
|
||||
const result = await userCollectionService.renameUserCollection(
|
||||
await userCollectionService.renameUserCollection(
|
||||
'NewTitle',
|
||||
rootRESTUserCollection.id,
|
||||
user.uid,
|
||||
|
|
@ -1162,7 +1106,7 @@ describe('deleteUserCollection', () => {
|
|||
rootRESTUserCollection,
|
||||
);
|
||||
|
||||
const result = await userCollectionService.deleteUserCollection(
|
||||
await userCollectionService.deleteUserCollection(
|
||||
rootRESTUserCollection.id,
|
||||
user.uid,
|
||||
);
|
||||
|
|
@ -1384,7 +1328,7 @@ describe('moveUserCollection', () => {
|
|||
orderIndex: 2,
|
||||
});
|
||||
|
||||
const result = await userCollectionService.moveUserCollection(
|
||||
await userCollectionService.moveUserCollection(
|
||||
childRESTUserCollection.id,
|
||||
null,
|
||||
user.uid,
|
||||
|
|
@ -1507,7 +1451,7 @@ describe('moveUserCollection', () => {
|
|||
orderIndex: 1,
|
||||
});
|
||||
|
||||
const result = await userCollectionService.moveUserCollection(
|
||||
await userCollectionService.moveUserCollection(
|
||||
rootRESTUserCollection.id,
|
||||
childRESTUserCollection.id,
|
||||
user.uid,
|
||||
|
|
@ -1624,7 +1568,7 @@ describe('updateUserCollectionOrder', () => {
|
|||
orderIndex: childRESTUserCollectionList.length,
|
||||
});
|
||||
|
||||
const result = await userCollectionService.updateUserCollectionOrder(
|
||||
await userCollectionService.updateUserCollectionOrder(
|
||||
childRESTUserCollectionList[4].id,
|
||||
null,
|
||||
user.uid,
|
||||
|
|
@ -1711,7 +1655,7 @@ describe('updateUserCollectionOrder', () => {
|
|||
.mockResolvedValueOnce(childRESTUserCollectionList[4])
|
||||
.mockResolvedValueOnce(childRESTUserCollectionList[2]);
|
||||
|
||||
const result = await userCollectionService.updateUserCollectionOrder(
|
||||
await userCollectionService.updateUserCollectionOrder(
|
||||
childRESTUserCollectionList[4].id,
|
||||
childRESTUserCollectionList[2].id,
|
||||
user.uid,
|
||||
|
|
@ -1818,7 +1762,7 @@ describe('updateUserCollection', () => {
|
|||
rootRESTUserCollection,
|
||||
);
|
||||
|
||||
const result = await userCollectionService.updateUserCollection(
|
||||
await userCollectionService.updateUserCollection(
|
||||
'new_title',
|
||||
JSON.stringify({ foo: 'bar' }),
|
||||
rootRESTUserCollection.id,
|
||||
|
|
|
|||
|
|
@ -744,7 +744,7 @@ export class UserCollectionService {
|
|||
},
|
||||
});
|
||||
// Step 2: Update orderIndex of collection to length of list
|
||||
const updatedUserCollection = await tx.userCollection.update({
|
||||
await tx.userCollection.update({
|
||||
where: { id: collection.right.id },
|
||||
data: {
|
||||
orderIndex: await this.getCollectionCount(
|
||||
|
|
@ -805,7 +805,7 @@ export class UserCollectionService {
|
|||
},
|
||||
});
|
||||
// Step 3: Update OrderIndex of collection
|
||||
const updatedUserCollection = await tx.userCollection.update({
|
||||
await tx.userCollection.update({
|
||||
where: { id: collection.right.id },
|
||||
data: {
|
||||
orderIndex: isMovingUp
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { ObjectType, Field, ID, registerEnumType } from '@nestjs/graphql';
|
||||
import { User } from '@prisma/client';
|
||||
import { ReqType } from 'src/types/RequestTypes';
|
||||
import { UserRequest } from 'src/user-request/user-request.model';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { PrismaModule } from '../prisma/prisma.module';
|
||||
import { PubSubModule } from '../pubsub/pubsub.module';
|
||||
import { UserModule } from '../user/user.module';
|
||||
import { UserEnvsUserResolver } from './user.resolver';
|
||||
import { UserEnvironmentsResolver } from './user-environments.resolver';
|
||||
import { UserEnvironmentsService } from './user-environments.service';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, PubSubModule, UserModule],
|
||||
imports: [UserModule],
|
||||
providers: [
|
||||
UserEnvironmentsResolver,
|
||||
UserEnvironmentsService,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { throwErr } from '../utils';
|
|||
@Resolver(() => User)
|
||||
export class UserEnvsUserResolver {
|
||||
constructor(private userEnvironmentsService: UserEnvironmentsService) {}
|
||||
|
||||
@ResolveField(() => [UserEnvironment], {
|
||||
description: 'Returns a list of users personal environments',
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { PrismaModule } from '../prisma/prisma.module';
|
||||
import { PubSubModule } from '../pubsub/pubsub.module';
|
||||
import { UserModule } from '../user/user.module';
|
||||
import { UserHistoryUserResolver } from './user.resolver';
|
||||
import { UserHistoryResolver } from './user-history.resolver';
|
||||
|
|
@ -8,7 +6,7 @@ import { UserHistoryService } from './user-history.service';
|
|||
import { InfraConfigModule } from 'src/infra-config/infra-config.module';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, PubSubModule, UserModule, InfraConfigModule],
|
||||
imports: [UserModule, InfraConfigModule],
|
||||
providers: [UserHistoryResolver, UserHistoryService, UserHistoryUserResolver],
|
||||
exports: [UserHistoryService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { PaginationArgs } from '../types/input-types.args';
|
|||
@Resolver(() => User)
|
||||
export class UserHistoryUserResolver {
|
||||
constructor(private userHistoryService: UserHistoryService) {}
|
||||
|
||||
@ResolveField(() => [UserHistory], {
|
||||
description: 'Returns a users REST history',
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { UseGuards } from '@nestjs/common';
|
||||
import {
|
||||
Args,
|
||||
Context,
|
||||
ID,
|
||||
Mutation,
|
||||
Query,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { UserCollectionModule } from 'src/user-collection/user-collection.module';
|
||||
import { PrismaModule } from '../prisma/prisma.module';
|
||||
import { PubSubModule } from '../pubsub/pubsub.module';
|
||||
import { UserRequestUserCollectionResolver } from './resolvers/user-collection.resolver';
|
||||
import { UserRequestResolver } from './resolvers/user-request.resolver';
|
||||
import { UserRequestService } from './user-request.service';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, PubSubModule, UserCollectionModule],
|
||||
imports: [UserCollectionModule],
|
||||
providers: [
|
||||
UserRequestResolver,
|
||||
UserRequestUserCollectionResolver,
|
||||
|
|
|
|||
|
|
@ -27,10 +27,9 @@ const mockPrisma = mockDeep<PrismaService>();
|
|||
const mockPubSub = mockDeep<PubSubService>();
|
||||
const mockUserCollectionService = mockDeep<UserCollectionService>();
|
||||
|
||||
// @ts-ignore
|
||||
const userRequestService = new UserRequestService(
|
||||
mockPrisma,
|
||||
mockPubSub as any,
|
||||
mockPubSub,
|
||||
mockUserCollectionService,
|
||||
);
|
||||
|
||||
|
|
@ -541,7 +540,7 @@ describe('UserRequestService', () => {
|
|||
mockPrisma.userRequest.findFirst.mockResolvedValue(dbUserRequests[0]);
|
||||
mockPrisma.userRequest.delete.mockResolvedValue(null);
|
||||
|
||||
const result = await userRequestService.deleteRequest(id, user);
|
||||
await userRequestService.deleteRequest(id, user);
|
||||
|
||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||
`user_request/${dbUserRequests[0].userUid}/deleted`,
|
||||
|
|
|
|||
|
|
@ -120,9 +120,8 @@ export class UserRequestService {
|
|||
const jsonRequest = stringToJson(request);
|
||||
if (E.isLeft(jsonRequest)) return E.left(jsonRequest.left);
|
||||
|
||||
const collection = await this.userCollectionService.getUserCollection(
|
||||
collectionID,
|
||||
);
|
||||
const collection =
|
||||
await this.userCollectionService.getUserCollection(collectionID);
|
||||
if (E.isLeft(collection)) return E.left(collection.left);
|
||||
|
||||
if (collection.right.userUid !== user.uid)
|
||||
|
|
@ -132,9 +131,8 @@ export class UserRequestService {
|
|||
return E.left(USER_REQUEST_INVALID_TYPE);
|
||||
|
||||
try {
|
||||
const requestCount = await this.getRequestsCountInCollection(
|
||||
collectionID,
|
||||
);
|
||||
const requestCount =
|
||||
await this.getRequestsCountInCollection(collectionID);
|
||||
|
||||
const request = await this.prisma.userRequest.create({
|
||||
data: {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
import { PubSubModule } from 'src/pubsub/pubsub.module';
|
||||
import { UserModule } from 'src/user/user.module';
|
||||
import { UserSettingsResolver } from './user-settings.resolver';
|
||||
import { UserSettingsService } from './user-settings.service';
|
||||
import { UserSettingsUserResolver } from './user.resolver';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, PubSubModule, UserModule],
|
||||
imports: [UserModule],
|
||||
providers: [
|
||||
UserSettingsResolver,
|
||||
UserSettingsService,
|
||||
|
|
|
|||
|
|
@ -79,11 +79,11 @@ export class UserDeletionResult {
|
|||
@Field(() => Boolean, {
|
||||
description: 'Flag to determine if user deletion was successful or not',
|
||||
})
|
||||
isDeleted: Boolean;
|
||||
isDeleted: boolean;
|
||||
|
||||
@Field({
|
||||
nullable: true,
|
||||
description: 'Error message if user deletion was not successful',
|
||||
})
|
||||
errorMessage: String;
|
||||
errorMessage: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,8 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { UserResolver } from './user.resolver';
|
||||
import { PubSubModule } from 'src/pubsub/pubsub.module';
|
||||
import { UserService } from './user.service';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
|
||||
@Module({
|
||||
imports: [PubSubModule, PrismaModule],
|
||||
providers: [UserResolver, UserService],
|
||||
exports: [UserService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import { TeamAccessRole } from 'src/team/team.model';
|
|||
@Injectable()
|
||||
export class UserService {
|
||||
constructor(
|
||||
private prisma: PrismaService,
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly pubsub: PubSubService,
|
||||
) {}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue