diff --git a/.gitignore b/.gitignore index 63cf0569..cc006b58 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ node_modules .pnp .pnp.js +.env.development + # Local env files .env .env.local diff --git a/pglite-debug.log b/pglite-debug.log new file mode 100644 index 00000000..e69de29b diff --git a/platforms/blabsy-w3ds-auth-api/src/controllers/WebhookController.ts b/platforms/blabsy-w3ds-auth-api/src/controllers/WebhookController.ts index 0cd0e001..17d9af17 100644 --- a/platforms/blabsy-w3ds-auth-api/src/controllers/WebhookController.ts +++ b/platforms/blabsy-w3ds-auth-api/src/controllers/WebhookController.ts @@ -4,6 +4,7 @@ import path from "path"; import dotenv from "dotenv"; import { getFirestore } from "firebase-admin/firestore"; import { Timestamp } from "firebase-admin/firestore"; +import axios from "axios"; // Define types locally since we can't import from @blabsy/types type User = { @@ -86,7 +87,9 @@ export class WebhookController { try { const { data, schemaId, id } = req.body; - console.log("received webhook????", req.body); + if (process.env.ANCHR_URL) { + return axios.post(new URL(process.env.ANCHR_URL, process.env.PUBLIC_BLABSY_BASE_URL).toString(), req.body) + } if (adapter.lockedIds.includes(id)) return; console.log("processing -- not skipped"); @@ -248,15 +251,15 @@ export class WebhookController { createdBy, images: data.images ? data.images.map((i: string) => ({ - src: i, - })) + src: i, + })) : null, parent: data.parent && user ? { - id: data.parent.split("(")[1].split(")")[0], - username: user.username, - } + id: data.parent.split("(")[1].split(")")[0], + username: user.username, + } : null, createdAt: Timestamp.fromDate(new Date(Date.now())), userRetweets: [], @@ -279,11 +282,11 @@ export class WebhookController { updatedAt: now, lastMessage: data.lastMessage ? { - ...data.lastMessage, - timestamp: Timestamp.fromDate( - new Date(data.lastMessage.timestamp), - ), - } + ...data.lastMessage, + timestamp: Timestamp.fromDate( + new Date(data.lastMessage.timestamp), + ), + } : null, }; } diff --git a/platforms/blabsy/.env.development b/platforms/blabsy/.env.development deleted file mode 100644 index b68f47e9..00000000 --- a/platforms/blabsy/.env.development +++ /dev/null @@ -1,21 +0,0 @@ -# Dev URL -# NEXT_PUBLIC_URL=http://localhost -NEXT_PUBLIC_BASE_URL=http://192.168.0.231:4444 - -NEXT_PUBLIC_URL=https://blabsy.w3ds-prototype.merul.org -# NEXT_PUBLIC_BASE_URL=https://blabsy.w3ds-prototype.merul.org - -# Emulator -NEXT_PUBLIC_USE_EMULATOR=false - -# Firebase -NEXT_PUBLIC_API_KEY=AIzaSyBa59njuCotm34gRGuGd6_HOCmE0-sbF4A -NEXT_PUBLIC_AUTH_DOMAIN=blabsy-msf.firebaseapp.com -NEXT_PUBLIC_PROJECT_ID=blabsy-msf -NEXT_PUBLIC_STORAGE_BUCKET=blabsy-msf.firebasestorage.app -NEXT_PUBLIC_MESSAGING_SENDER_ID=876614847689 -NEXT_PUBLIC_APP_ID=1:876614847689:web:c90a9a6dbb2d0b87c2d118 -NEXT_PUBLIC_MEASUREMENT_ID=G-8Q1TEDQYT3 - -GOOGLE_APPLICATION_CREDENTIALS="/Users/mrl/Projects/metastate/platforms/blabsy/secrets/firebase-secrets.json" - diff --git a/platforms/blabsy/pglite-debug.log b/platforms/blabsy/pglite-debug.log new file mode 100644 index 00000000..e69de29b diff --git a/platforms/pictique-api/src/controllers/WebhookController.ts b/platforms/pictique-api/src/controllers/WebhookController.ts index 0593eab8..387eac66 100644 --- a/platforms/pictique-api/src/controllers/WebhookController.ts +++ b/platforms/pictique-api/src/controllers/WebhookController.ts @@ -8,6 +8,7 @@ import { User } from "database/entities/User"; import { Chat } from "database/entities/Chat"; import { MessageService } from "../services/MessageService"; import { Post } from "database/entities/Post"; +import axios from "axios"; export class WebhookController { userService: UserService; @@ -28,7 +29,9 @@ export class WebhookController { handleWebhook = async (req: Request, res: Response) => { try { - console.log("raw hook", req.body); + if (process.env.ANCHR_URL) { + return axios.post(new URL(process.env.ANCHR_URL, process.env.PUBLIC_PICTIQUE_BASE_URL).toString(), req.body) + } const schemaId = req.body.schemaId; const globalId = req.body.id; const mapping = Object.values(this.adapter.mapping).find( diff --git a/platforms/pictique-api/src/web3adapter/controllers/WebhookController.ts b/platforms/pictique-api/src/web3adapter/controllers/WebhookController.ts deleted file mode 100644 index 7a5eb553..00000000 --- a/platforms/pictique-api/src/web3adapter/controllers/WebhookController.ts +++ /dev/null @@ -1,298 +0,0 @@ -import { Request, Response } from "express"; -import { TransformService } from "../services/TransformService"; -import { web3AdapterConfig } from "../config"; -import { EntityType, WebhookPayload, TransformContext } from "../types"; -import { AppDataSource } from "../../database/data-source"; -import { User } from "../../database/entities/User"; -import { Post } from "../../database/entities/Post"; -import { Comment } from "../../database/entities/Comment"; -import { Chat } from "../../database/entities/Chat"; -import { Message } from "../../database/entities/Message"; -import { MessageReadStatus } from "../../database/entities/MessageReadStatus"; -import { In } from "typeorm"; - -export class WebhookController { - private userRepository = AppDataSource.getRepository(User); - private postRepository = AppDataSource.getRepository(Post); - private commentRepository = AppDataSource.getRepository(Comment); - private chatRepository = AppDataSource.getRepository(Chat); - private messageRepository = AppDataSource.getRepository(Message); - private messageReadStatusRepository = AppDataSource.getRepository(MessageReadStatus); - - async handleWebhook(req: Request, res: Response) { - const payload = req.body as WebhookPayload; - console.log("Received webhook payload:", payload); - - // For now, we're not verifying signatures - // TODO: Implement signature verification - - try { - const entityType = this.getEntityTypeFromGlobal(payload.entityType); - if (!entityType) { - throw new Error(`Unsupported global ontology type: ${payload.entityType}`); - } - - const transformContext: TransformContext = { - platform: "blabsy", - entityType, - internalId: payload.metaEnvelopeId - }; - - const platformData = TransformService.getInstance().fromGlobalOntology( - entityType, - payload.payload, - transformContext - ); - - switch (payload.operation) { - case "create": - await this.handleCreate(entityType, platformData); - break; - case "update": - await this.handleUpdate(entityType, platformData); - break; - case "delete": - await this.handleDelete(entityType, platformData); - break; - default: - throw new Error(`Unsupported operation: ${payload.operation}`); - } - - res.status(200).json({ success: true }); - } catch (error) { - console.error("Error handling webhook:", error); - res.status(500).json({ error: (error as Error).message }); - } - } - - private getEntityTypeFromGlobal(globalType: string): EntityType | null { - const mapping = Object.entries(web3AdapterConfig.entityMappings).find( - ([_, value]) => value === globalType - ); - return mapping ? (mapping[0] as EntityType) : null; - } - - private async handleCreate(entityType: EntityType, data: any) { - switch (entityType) { - case "User": { - const user = this.userRepository.create({ - ename: data.ename, - handle: data.username, - name: data.displayName, - description: data.bio, - avatarUrl: data.avatarUrl - }); - await this.userRepository.save(user); - break; - } - case "Post": { - const author = await this.userRepository.findOneBy({ ename: data.authorEname }); - if (!author) throw new Error(`Author not found: ${data.authorEname}`); - - const post = this.postRepository.create({ - text: data.content, - images: data.images, - hashtags: data.hashtags, - author - }); - await this.postRepository.save(post); - break; - } - case "Comment": { - const author = await this.userRepository.findOneBy({ ename: data.authorEname }); - if (!author) throw new Error(`Author not found: ${data.authorEname}`); - - // Find the parent post by its meta envelope ID - const parentPost = await this.postRepository.findOne({ - where: { id: data.parentId }, - relations: ["author"] - }); - if (!parentPost) throw new Error(`Parent post not found: ${data.parentId}`); - - const comment = this.commentRepository.create({ - text: data.content, - author, - post: parentPost - }); - await this.commentRepository.save(comment); - break; - } - case "Chat": { - const participants = await this.userRepository.findBy({ - ename: In(data.participants) - }); - if (participants.length === 0) { - throw new Error("No participants found"); - } - - const chat = this.chatRepository.create({ - name: data.name, - participants - }); - await this.chatRepository.save(chat); - break; - } - case "Message": { - const sender = await this.userRepository.findOneBy({ ename: data.authorEname }); - if (!sender) throw new Error(`Sender not found: ${data.authorEname}`); - - const chat = await this.chatRepository.findOneBy({ id: data.chatId }); - if (!chat) throw new Error(`Chat not found: ${data.chatId}`); - - const message = this.messageRepository.create({ - text: data.content, - sender, - chat - }); - await this.messageRepository.save(message); - - // Create read statuses for all chat participants except the sender - const readStatuses = chat.participants - .filter(p => p.ename !== data.authorEname) - .map(participant => - this.messageReadStatusRepository.create({ - message, - user: participant, - isRead: false - }) - ); - await this.messageReadStatusRepository.save(readStatuses); - break; - } - case "MessageReadStatus": { - const message = await this.messageRepository.findOneBy({ id: data.messageId }); - if (!message) throw new Error(`Message not found: ${data.messageId}`); - - const user = await this.userRepository.findOneBy({ ename: data.userEname }); - if (!user) throw new Error(`User not found: ${data.userEname}`); - - const readStatus = this.messageReadStatusRepository.create({ - message, - user, - isRead: data.isRead - }); - await this.messageReadStatusRepository.save(readStatus); - break; - } - } - } - - private async handleUpdate(entityType: EntityType, data: any) { - switch (entityType) { - case "User": { - const user = await this.userRepository.findOneBy({ ename: data.ename }); - if (!user) throw new Error(`User not found: ${data.ename}`); - - Object.assign(user, { - handle: data.username, - name: data.displayName, - description: data.bio, - avatarUrl: data.avatarUrl - }); - await this.userRepository.save(user); - break; - } - case "Post": { - const post = await this.postRepository.findOneBy({ id: data.id }); - if (!post) throw new Error(`Post not found: ${data.id}`); - - Object.assign(post, { - text: data.content, - images: data.images, - hashtags: data.hashtags - }); - await this.postRepository.save(post); - break; - } - case "Comment": { - const comment = await this.commentRepository.findOneBy({ id: data.id }); - if (!comment) throw new Error(`Comment not found: ${data.id}`); - - Object.assign(comment, { - text: data.content - }); - await this.commentRepository.save(comment); - break; - } - case "Chat": { - const chat = await this.chatRepository.findOneBy({ id: data.id }); - if (!chat) throw new Error(`Chat not found: ${data.id}`); - - const participants = await this.userRepository.findBy({ - ename: In(data.participants) - }); - if (participants.length === 0) { - throw new Error("No participants found"); - } - - Object.assign(chat, { - name: data.name, - participants - }); - await this.chatRepository.save(chat); - break; - } - case "Message": { - const message = await this.messageRepository.findOneBy({ id: data.id }); - if (!message) throw new Error(`Message not found: ${data.id}`); - - Object.assign(message, { - text: data.content - }); - await this.messageRepository.save(message); - break; - } - case "MessageReadStatus": { - const readStatus = await this.messageReadStatusRepository.findOneBy({ id: data.id }); - if (!readStatus) throw new Error(`Read status not found: ${data.id}`); - - Object.assign(readStatus, { - isRead: data.isRead - }); - await this.messageReadStatusRepository.save(readStatus); - break; - } - } - } - - private async handleDelete(entityType: EntityType, data: any) { - switch (entityType) { - case "User": { - const user = await this.userRepository.findOneBy({ ename: data.ename }); - if (!user) throw new Error(`User not found: ${data.ename}`); - await this.userRepository.softDelete(user.id); - break; - } - case "Post": { - const post = await this.postRepository.findOneBy({ id: data.id }); - if (!post) throw new Error(`Post not found: ${data.id}`); - await this.postRepository.softDelete(post.id); - break; - } - case "Comment": { - const comment = await this.commentRepository.findOneBy({ id: data.id }); - if (!comment) throw new Error(`Comment not found: ${data.id}`); - await this.commentRepository.softDelete(comment.id); - break; - } - case "Chat": { - const chat = await this.chatRepository.findOneBy({ id: data.id }); - if (!chat) throw new Error(`Chat not found: ${data.id}`); - await this.chatRepository.softDelete(chat.id); - break; - } - case "Message": { - const message = await this.messageRepository.findOneBy({ id: data.id }); - if (!message) throw new Error(`Message not found: ${data.id}`); - await this.messageRepository.softDelete(message.id); - break; - } - case "MessageReadStatus": { - const readStatus = await this.messageReadStatusRepository.findOneBy({ id: data.id }); - if (!readStatus) throw new Error(`Read status not found: ${data.id}`); - await this.messageReadStatusRepository.softDelete(readStatus.id); - break; - } - } - } -} \ No newline at end of file diff --git a/platforms/pictique/vite.config.ts b/platforms/pictique/vite.config.ts index 73d957c9..a23ecdce 100644 --- a/platforms/pictique/vite.config.ts +++ b/platforms/pictique/vite.config.ts @@ -3,8 +3,12 @@ import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vite'; export default defineConfig({ - plugins: [tailwindcss(), sveltekit()], - server: { - allowedHosts: ["pictique.w3ds-prototype.merul.org"] - } + plugins: [tailwindcss(), sveltekit()], + server: { + allowedHosts: [ + 'pictique.w3ds-prototype.merul.org', + 'pictique.staging.metastate.foundation', + 'pictique.w3ds.metastate.foundation' + ] + } });