diff --git a/apps/backend/src/api/routes/posts.controller.ts b/apps/backend/src/api/routes/posts.controller.ts index 534e2642..3a4cdccf 100644 --- a/apps/backend/src/api/routes/posts.controller.ts +++ b/apps/backend/src/api/routes/posts.controller.ts @@ -139,11 +139,12 @@ export class PostsController { @Post('/') @CheckPolicies([AuthorizationActions.Create, Sections.POSTS_PER_MONTH]) - createPost( + async createPost( @GetOrgFromRequest() org: Organization, - @Body() body: CreatePostDto + @Body() rawBody: any ) { - console.log(JSON.stringify(body, null, 2)); + console.log(JSON.stringify(rawBody, null, 2)); + const body = await this._postsService.mapTypeToPost(rawBody, org.id); return this._postsService.createPost(org.id, body); } diff --git a/apps/backend/src/public-api/routes/v1/public.integrations.controller.ts b/apps/backend/src/public-api/routes/v1/public.integrations.controller.ts index 8304e874..ee512411 100644 --- a/apps/backend/src/public-api/routes/v1/public.integrations.controller.ts +++ b/apps/backend/src/public-api/routes/v1/public.integrations.controller.ts @@ -61,7 +61,6 @@ export class PublicIntegrationsController { @Query() query: GetPostsDto ) { const posts = await this._postsService.getPosts(org.id, query); - return { posts, // comments, @@ -70,10 +69,12 @@ export class PublicIntegrationsController { @Post('/posts') @CheckPolicies([AuthorizationActions.Create, Sections.POSTS_PER_MONTH]) - createPost( + async createPost( @GetOrgFromRequest() org: Organization, - @Body() body: CreatePostDto + @Body() rawBody: any ) { + const body = await this._postsService.mapTypeToPost(rawBody, org.id); + console.log(JSON.stringify(body, null, 2)); return this._postsService.createPost(org.id, body); } diff --git a/apps/frontend/src/components/new-launch/manage.modal.tsx b/apps/frontend/src/components/new-launch/manage.modal.tsx index 4cad9413..c6d2b899 100644 --- a/apps/frontend/src/components/new-launch/manage.modal.tsx +++ b/apps/frontend/src/components/new-launch/manage.modal.tsx @@ -240,7 +240,7 @@ export const ManageModal: FC = (props) => { posts: checkAllValid.map((p: any) => ({ integration: p.integration, group, - settings: { ...(p.settings || {}), __type: p.integration.identifier }, + settings: { ...(p.settings || {}) }, value: p.values.map((a: any) => ({ ...a, image: a.media || [], diff --git a/libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts b/libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts index 793022de..9d00df6f 100644 --- a/libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts +++ b/libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts @@ -1,4 +1,9 @@ -import { Injectable } from '@nestjs/common'; +import { + BadRequestException, + ForbiddenException, + Injectable, + ValidationPipe, +} from '@nestjs/common'; import { PostsRepository } from '@gitroom/nestjs-libraries/database/prisma/posts/posts.repository'; import { CreatePostDto } from '@gitroom/nestjs-libraries/dtos/posts/create.post.dto'; import dayjs from 'dayjs'; @@ -29,6 +34,8 @@ import sharp from 'sharp'; import { UploadFactory } from '@gitroom/nestjs-libraries/upload/upload.factory'; import { Readable } from 'stream'; import { OpenaiService } from '@gitroom/nestjs-libraries/openai/openai.service'; +import { plainToInstance } from 'class-transformer'; +import { validate } from 'class-validator'; dayjs.extend(utc); type PostWithConditionals = Post & { @@ -50,7 +57,7 @@ export class PostsService { private _mediaService: MediaService, private _shortLinkService: ShortLinkService, private _webhookService: WebhooksService, - private openaiService: OpenaiService, + private openaiService: OpenaiService ) {} async getStatistics(orgId: string, id: string) { @@ -65,6 +72,54 @@ export class PostsService { }; } + async mapTypeToPost( + body: CreatePostDto, + organization: string + ): Promise { + if (!body?.posts?.every((p) => p?.integration?.id)) { + throw new BadRequestException('All posts must have an integration id'); + } + + const mappedValues = { + ...body, + posts: await Promise.all( + body.posts.map(async (post) => { + const integration = await this._integrationService.getIntegrationById( + organization, + post.integration.id + ); + + if (!integration) { + throw new BadRequestException( + `Integration with id ${post.integration.id} not found` + ); + } + + return { + ...post, + settings: { + ...(post.settings || ({} as any)), + __type: integration.providerIdentifier, + }, + }; + }) + ), + }; + + const validationPipe = new ValidationPipe({ + skipMissingProperties: false, + transform: true, + transformOptions: { + enableImplicitConversion: true, + }, + }); + + return await validationPipe.transform(mappedValues, { + type: 'body', + metatype: CreatePostDto, + }); + } + async getPostsRecursively( id: string, includeIntegration = false, @@ -572,7 +627,10 @@ export class PostsService { } } - private async postArticle(integration: Integration, posts: Post[]): Promise { + private async postArticle( + integration: Integration, + posts: Post[] + ): Promise { const getIntegration = this._integrationManager.getArticlesIntegration( integration.providerIdentifier ); @@ -929,7 +987,10 @@ export class PostsService { } async findFreeDateTime(orgId: string, integrationId?: string) { - const findTimes = await this._integrationService.findFreeDateTime(orgId, integrationId); + const findTimes = await this._integrationService.findFreeDateTime( + orgId, + integrationId + ); return this.findFreeDateTimeRecursive( orgId, findTimes,