diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7c3c73ec3..7d1882ac3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -9,10 +9,10 @@ on: jobs: messenger-web-deploy: - environment: ${{ github.ref_name == 'main' && 'prod' || (github.ref == 'develop' && 'staging' || 'testing') }} + environment: ${{ github.ref_name == 'main' && 'prod' || (github.ref_name == 'develop' && 'staging' || 'testing') }} runs-on: ubuntu-latest env: - environment_name: ${{ github.ref_name == 'main' && 'prod' || (github.ref == 'develop' && 'staging' || 'testing') }} + environment_name: ${{ github.ref_name == 'main' && 'prod' || (github.ref_name == 'develop' && 'staging' || 'testing') }} steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v3 diff --git a/packages/backend/package.json b/packages/backend/package.json index 0179abe18..3fff07e0c 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -28,7 +28,7 @@ }, "scripts": { "docker:up": "docker-compose up -d", - "prisma-init": "prisma generate && prisma migrate dev ", + "prisma-init": "prisma generate && prisma migrate deploy ", "start": "yarn prisma-init && node ./dist/index.js", "start-inspect": "node --inspect=0.0.0.0:9229 ./dist/index.js", "test": "yarn run before:tests && DATABASE_URL='postgresql://prisma:prisma@localhost:5433/tests?schema=public' yarn jest --coverage --runInBand --transformIgnorePatterns 'node_modules/(?!(dm3-lib-\\w*)/)'", diff --git a/packages/backend/src/persistence/getDatabase.ts b/packages/backend/src/persistence/getDatabase.ts index faa510a6b..ec23fdbc6 100644 --- a/packages/backend/src/persistence/getDatabase.ts +++ b/packages/backend/src/persistence/getDatabase.ts @@ -3,7 +3,6 @@ import { ISessionDatabase } from '@dm3-org/dm3-lib-server-side'; import { UserStorage } from '@dm3-org/dm3-lib-storage'; import { PrismaClient } from '@prisma/client'; import { createClient } from 'redis'; -import Pending from './pending'; import Session from './session'; import Storage from './storage'; import { ConversationRecord } from './storage/postgres/dto/ConversationRecord'; @@ -15,7 +14,6 @@ export enum RedisPrefix { Sync = 'sync:', Session = 'session:', UserStorage = 'user.storage:', - Pending = 'pending:', NotificationChannel = 'notificationChannel:', GlobalNotification = 'globalNotification:', Otp = 'otp:', @@ -69,10 +67,6 @@ export async function getDatabase( //Legacy remove after storage has been merged getUserStorage: Storage.getUserStorageOld(redis), setUserStorage: Storage.setUserStorageOld(redis), - //Pending - addPending: Pending.addPending(redis), - getPending: Pending.getPending(redis), - deletePending: Pending.deletePending(redis), //Storage AddConversation addConversation: Storage.addConversation(prisma), getConversationList: Storage.getConversationList(prisma), @@ -110,9 +104,6 @@ export interface IDatabase extends ISessionDatabase { //Legacy remove after storage has been merged getUserStorage: (ensName: string) => Promise; setUserStorage: (ensName: string, data: string) => Promise; - addPending: (ensName: string, contactEnsName: string) => Promise; - getPending: (ensName: string) => Promise; - deletePending: (ensName: string) => Promise; addConversation: ( ensName: string, diff --git a/packages/backend/src/persistence/pending/addPending.ts b/packages/backend/src/persistence/pending/addPending.ts deleted file mode 100644 index 67fd1dc2d..000000000 --- a/packages/backend/src/persistence/pending/addPending.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Redis, RedisPrefix } from '../getDatabase'; -import { normalizeEnsName } from '@dm3-org/dm3-lib-profile'; - -export function addPending(redis: Redis) { - return async (ensName: string, contactEnsName: string): Promise => { - await redis.sAdd( - RedisPrefix.Pending + normalizeEnsName(contactEnsName), - normalizeEnsName(ensName), - ); - }; -} diff --git a/packages/backend/src/persistence/pending/deletePending.ts b/packages/backend/src/persistence/pending/deletePending.ts deleted file mode 100644 index 779b5eba3..000000000 --- a/packages/backend/src/persistence/pending/deletePending.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Redis, RedisPrefix } from '../getDatabase'; -import { getIdEnsName } from '../getIdEnsName'; - -export function deletePending(redis: Redis) { - return async (ensName: string): Promise => { - await redis.del( - RedisPrefix.Pending + (await getIdEnsName(redis)(ensName)), - ); - }; -} diff --git a/packages/backend/src/persistence/pending/getPending.ts b/packages/backend/src/persistence/pending/getPending.ts deleted file mode 100644 index 1f0941834..000000000 --- a/packages/backend/src/persistence/pending/getPending.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Redis, RedisPrefix } from '../getDatabase'; -import { getIdEnsName } from '../getIdEnsName'; - -export function getPending(redis: Redis) { - return async (ensName: string): Promise => { - return redis.sMembers( - RedisPrefix.Pending + (await getIdEnsName(redis)(ensName)), - ); - }; -} diff --git a/packages/backend/src/persistence/pending/index.ts b/packages/backend/src/persistence/pending/index.ts deleted file mode 100644 index 7d367e2f2..000000000 --- a/packages/backend/src/persistence/pending/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { addPending } from './addPending'; -import { getPending } from './getPending'; -import { deletePending } from './deletePending'; - -export default { addPending, deletePending, getPending }; diff --git a/packages/backend/src/persistence/storage/postgres/haltedMessage/clearHaltedMessage.ts b/packages/backend/src/persistence/storage/postgres/haltedMessage/clearHaltedMessage.ts index 60d15ded4..1abf02eb5 100644 --- a/packages/backend/src/persistence/storage/postgres/haltedMessage/clearHaltedMessage.ts +++ b/packages/backend/src/persistence/storage/postgres/haltedMessage/clearHaltedMessage.ts @@ -25,6 +25,7 @@ export const clearHaltedMessage = const message = await db.encryptedMessage.findFirst({ where: { id: messageId, + ownerId: account.id, }, }); diff --git a/packages/backend/src/profile.test.ts b/packages/backend/src/profile.test.ts index 617c0c7d9..81337112f 100644 --- a/packages/backend/src/profile.test.ts +++ b/packages/backend/src/profile.test.ts @@ -107,7 +107,6 @@ describe('Profile', () => { setSession: async (_: string, __: any) => { return (_: any, __: any, ___: any) => {}; }, - getPending: (_: any) => [], getIdEnsName: async (ensName: string) => ensName, }; diff --git a/packages/backend/src/storage.test.ts b/packages/backend/src/storage.test.ts index 1e27b9d7d..5f99e60ab 100644 --- a/packages/backend/src/storage.test.ts +++ b/packages/backend/src/storage.test.ts @@ -490,8 +490,6 @@ describe('Storage', () => { }) .send(); - console.log(body); - expect(body.length).toBe(1); expect(body[0].contact).toEqual(sha256(receiver.account.ensName)); expect(JSON.parse(body[0].previewMessage)).toEqual(envelop3); @@ -508,8 +506,6 @@ describe('Storage', () => { }) .send(); - console.log(body); - expect(status).toBe(400); }); @@ -522,8 +518,6 @@ describe('Storage', () => { }) .send(); - console.log(body); - expect(status).toBe(400); }); }); @@ -980,7 +974,7 @@ describe('Storage', () => { .send({ encryptedEnvelopContainer: JSON.stringify(envelop1), encryptedContactName: sha256(receiver.account.ensName), - messageId: '123', + messageId: envelop1.metadata.encryptedMessageHash, createdAt: 1, isHalted: true, }); @@ -1007,7 +1001,7 @@ describe('Storage', () => { authorization: 'Bearer ' + token, }) .send({ - messageId: 123, + messageId: messages[0].messageId, }); expect(deleteStatus).toBe(200); @@ -1162,9 +1156,6 @@ describe('Storage', () => { isHalted: false, }); - console.log('xxxx', x.status); - console.log('xxxx', x.body); - await request(app) .post(`/new/bob.eth/addMessage`) .set({ diff --git a/packages/backend/src/storage.ts b/packages/backend/src/storage.ts index 00288534d..2c4a122d5 100644 --- a/packages/backend/src/storage.ts +++ b/packages/backend/src/storage.ts @@ -279,22 +279,12 @@ export default ( } const ensName = normalizeEnsName(req.params.ensName); - //Since the message is fully encrypted, we cannot use the messageHash as an identifier. - //Instead we use the hash of the ensName and the messageId to have a unique identifier - const uniqueMessageId = sha256(ensName + messageId); - - console.log( - 'clearHaltedMessage uniqueMessageId ', - uniqueMessageId, - ensName, - messageId, - ); const success = await db.clearHaltedMessage( ensName, //If the aliasName is not provided, we use the ensName as the client has no intention to use an alias aliasName, - uniqueMessageId, + messageId, ); if (success) { diff --git a/packages/delivery-service/src/delivery.test.ts b/packages/delivery-service/src/delivery.test.ts index 561025824..d3940b4c4 100644 --- a/packages/delivery-service/src/delivery.test.ts +++ b/packages/delivery-service/src/delivery.test.ts @@ -69,49 +69,6 @@ describe('Delivery', () => { }); }); - describe('getPendingMessages', () => { - it('Returns 200 if schema is valid', async () => { - const web3Provider = { - resolveName: async () => - '0x99C19AB10b9EC8aC6fcda9586E81f6B73a298870', - }; - - const token = await createAuthToken( - '0x99C19AB10b9EC8aC6fcda9586E81f6B73a298870', - ); - - const db = { - getSession: async (ensName: string) => ({ - challenge: 'deprecated challenge', - token: 'deprecated token that is not used anymore', - }), - setSession: async (_: string, __: any) => { - return (_: any, __: any, ___: any) => {}; - }, - getPending: (_: any) => [], - deletePending: (_: any) => [], - getIdEnsName: async (ensName: string) => ensName, - }; - const app = express(); - app.use(bodyParser.json()); - app.use( - delivery(web3Provider as any, db as any, keysA, serverSecret), - ); - - const { status } = await request(app) - .post( - '/messages/0x99C19AB10b9EC8aC6fcda9586E81f6B73a298870/pending', - ) - .set({ - authorization: `Bearer ${token}`, - }) - - .send(); - - expect(status).toBe(200); - }); - }); - describe('syncAcknoledgment', () => { it('Returns 200 if schema is valid', async () => { const web3Provider = { diff --git a/packages/delivery-service/src/delivery.ts b/packages/delivery-service/src/delivery.ts index f71f047a8..6105edd95 100644 --- a/packages/delivery-service/src/delivery.ts +++ b/packages/delivery-service/src/delivery.ts @@ -88,7 +88,7 @@ export default ( req.params.ensName, //Fetch the last 10 messages per conversation //If we decide to add pagination for that endpoint we can pass this value as a param - 10, + 1000, ); res.json(incomingMessages); } catch (e) { @@ -97,18 +97,6 @@ export default ( }, ); - router.post('/messages/:ensName/pending', async (req, res, next) => { - try { - const account = await db.getIdEnsName(req.params.ensName); - const pending = await db.getPending(account); - await db.deletePending(account); - - res.json(pending); - } catch (e) { - next(e); - } - }); - //TODO remove after storage refactoring router.post( '/messages/:ensName/syncAcknoledgment/:last_message_pull', diff --git a/packages/delivery-service/src/messaging.test.ts b/packages/delivery-service/src/messaging.test.ts index f7ae1d360..459e17bbf 100644 --- a/packages/delivery-service/src/messaging.test.ts +++ b/packages/delivery-service/src/messaging.test.ts @@ -249,37 +249,4 @@ describe('Messaging', () => { )(getSocketMock()); }); }); - - describe('pendingMessage', () => { - it('returns error if schema is invalid', async () => { - const data = { - accountAddress: '', - contactAddress: '', - }; - const callback = jest.fn((e: any) => { - if (e.error !== 'invalid schema') { - throw Error(e); - } - expect(e.error).toBe('invalid schema'); - }); - const getSocketMock = jest.fn(() => { - return { - on: async (name: string, onPendingMessage: any) => { - //We just want to test the submitMessage callback fn - if (name === 'pendingMessage') { - await onPendingMessage(data, callback); - } - }, - } as unknown as Socket; - }); - onConnection( - io as any, - web3Provider as any, - db as any, - keysA, - serverSecret, - mockWsManager, - )(getSocketMock()); - }); - }); }); diff --git a/packages/delivery-service/src/messaging.ts b/packages/delivery-service/src/messaging.ts index e091d024a..c7cf82993 100644 --- a/packages/delivery-service/src/messaging.ts +++ b/packages/delivery-service/src/messaging.ts @@ -11,17 +11,6 @@ import { getDeliveryServiceProperties } from './config/getDeliveryServicePropert import { IDatabase } from './persistence/getDatabase'; import { IWebSocketManager } from '@dm3-org/dm3-lib-shared'; -const pendingMessageSchema = { - type: 'object', - properties: { - ensName: { type: 'string' }, - contactEnsName: { type: 'string' }, - token: { type: 'string' }, - }, - required: ['ensName', 'contactEnsName', 'token'], - additionalProperties: false, -}; - export function onConnection( io: Server, web3Provider: ethers.providers.JsonRpcProvider, @@ -116,75 +105,5 @@ export function onConnection( } }, ); - - /** - * Queue a message for a user that has not yet published their profile. - * The queue is managed on the delivery service of the sending user. - */ - socket.on('pendingMessage', async (data, callback) => { - const isSchemaValid = validateSchema(pendingMessageSchema, data); - - if (!isSchemaValid) { - const error = 'invalid schema'; - global.logger.warn({ - method: 'WS PENDING MESSAGE', - error, - }); - - return callback({ error }); - } - - let idEnsName: string; - let idContactEnsName: string; - const ensName = normalizeEnsName(data.ensName); - const contactEnsName = normalizeEnsName(data.contactEnsName); - - try { - idEnsName = await db.getIdEnsName(ensName); - idContactEnsName = await db.getIdEnsName(contactEnsName); - } catch (error) { - global.logger.warn({ - method: 'WS PENDING MESSAGE', - error, - }); - - return callback({ error }); - } - - global.logger.info({ - method: 'WS PENDING MESSAGE', - ensName, - contactEnsName, - }); - try { - if ( - !(await checkToken( - web3Provider, - db.getSession, - idEnsName, - data.token, - serverSecret, - )) - ) { - const error = 'Token check failed'; - global.logger.warn({ - method: 'WS PENDING MESSAGE', - error, - }); - return callback({ error }); - } - - await db.addPending(ensName, idContactEnsName); - - callback({ response: 'success' }); - } catch (error) { - global.logger.warn({ - method: 'WS PENDING MESSAGE', - error: (error as Error).toString(), - }); - - return callback({ error: "Can't add pending message" }); - } - }); }; } diff --git a/packages/delivery-service/src/persistence/getDatabase.ts b/packages/delivery-service/src/persistence/getDatabase.ts index 780f3586f..14c0631e4 100644 --- a/packages/delivery-service/src/persistence/getDatabase.ts +++ b/packages/delivery-service/src/persistence/getDatabase.ts @@ -12,7 +12,6 @@ import Messages from './messages'; import { syncAcknowledge } from './messages/syncAcknowledge'; import Notification from './notification'; import Otp from './otp'; -import Pending from './pending'; import Session from './session'; export enum RedisPrefix { @@ -21,7 +20,6 @@ export enum RedisPrefix { Sync = 'sync:', Session = 'session:', UserStorage = 'user.storage:', - Pending = 'pending:', NotificationChannel = 'notificationChannel:', GlobalNotification = 'globalNotification:', Otp = 'otp:', @@ -73,11 +71,8 @@ export async function getDatabase( //Session setSession: Session.setSession(redis), getSession: Session.getSession(redis), - //Pending - addPending: Pending.addPending(redis), - getPending: Pending.getPending(redis), - deletePending: Pending.deletePending(redis), getIdEnsName: getIdEnsName(redis), + //Sync syncAcknowledge: syncAcknowledge(redis), //Notification getUsersNotificationChannels: @@ -116,9 +111,6 @@ export interface IDatabase extends ISessionDatabase { createdAt?: number, ) => Promise; deleteExpiredMessages: (time: number) => Promise; - addPending: (ensName: string, contactEnsName: string) => Promise; - getPending: (ensName: string) => Promise; - deletePending: (ensName: string) => Promise; getIdEnsName: (ensName: string) => Promise; syncAcknowledge: ( conversationId: string, diff --git a/packages/delivery-service/src/persistence/pending/addPending.ts b/packages/delivery-service/src/persistence/pending/addPending.ts deleted file mode 100644 index 67fd1dc2d..000000000 --- a/packages/delivery-service/src/persistence/pending/addPending.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Redis, RedisPrefix } from '../getDatabase'; -import { normalizeEnsName } from '@dm3-org/dm3-lib-profile'; - -export function addPending(redis: Redis) { - return async (ensName: string, contactEnsName: string): Promise => { - await redis.sAdd( - RedisPrefix.Pending + normalizeEnsName(contactEnsName), - normalizeEnsName(ensName), - ); - }; -} diff --git a/packages/delivery-service/src/persistence/pending/deletePending.ts b/packages/delivery-service/src/persistence/pending/deletePending.ts deleted file mode 100644 index 779b5eba3..000000000 --- a/packages/delivery-service/src/persistence/pending/deletePending.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Redis, RedisPrefix } from '../getDatabase'; -import { getIdEnsName } from '../getIdEnsName'; - -export function deletePending(redis: Redis) { - return async (ensName: string): Promise => { - await redis.del( - RedisPrefix.Pending + (await getIdEnsName(redis)(ensName)), - ); - }; -} diff --git a/packages/delivery-service/src/persistence/pending/getPending.ts b/packages/delivery-service/src/persistence/pending/getPending.ts deleted file mode 100644 index 1f0941834..000000000 --- a/packages/delivery-service/src/persistence/pending/getPending.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Redis, RedisPrefix } from '../getDatabase'; -import { getIdEnsName } from '../getIdEnsName'; - -export function getPending(redis: Redis) { - return async (ensName: string): Promise => { - return redis.sMembers( - RedisPrefix.Pending + (await getIdEnsName(redis)(ensName)), - ); - }; -} diff --git a/packages/delivery-service/src/persistence/pending/index.ts b/packages/delivery-service/src/persistence/pending/index.ts deleted file mode 100644 index 7d367e2f2..000000000 --- a/packages/delivery-service/src/persistence/pending/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { addPending } from './addPending'; -import { getPending } from './getPending'; -import { deletePending } from './deletePending'; - -export default { addPending, deletePending, getPending }; diff --git a/packages/delivery-service/src/profile.test.ts b/packages/delivery-service/src/profile.test.ts index 18c0dce36..a52ab219d 100644 --- a/packages/delivery-service/src/profile.test.ts +++ b/packages/delivery-service/src/profile.test.ts @@ -64,7 +64,6 @@ describe('Profile', () => { setSession: async (_: string, __: any) => { return (_: any, __: any, ___: any) => {}; }, - getPending: (_: any) => [], getIdEnsName: async (ensName: string) => ensName, }; const app = express(); @@ -110,7 +109,6 @@ describe('Profile', () => { setSession: async (_: string, __: any) => { return (_: any, __: any, ___: any) => {}; }, - getPending: (_: any) => [], getIdEnsName: async (ensName: string) => ensName, }; diff --git a/packages/lib/delivery-api/src/messaging-ws.ts b/packages/lib/delivery-api/src/messaging-ws.ts index 3454309e1..58f25102f 100644 --- a/packages/lib/delivery-api/src/messaging-ws.ts +++ b/packages/lib/delivery-api/src/messaging-ws.ts @@ -32,38 +32,3 @@ export async function sendMessage( ); } export type SendMessage = typeof sendMessage; - -/** - * creates an pending message entry on the delivery service - * @param socket The socket.io web socket to use - * @param token The auth token - * @param ensName Sender ENS name - * @param contactEnsName Receiver ENS name - * @param onSuccess Callback in case of success - * @param onError Callback in case that an error occured - */ -export async function createPendingEntry( - socket: Socket, - token: string, - ensName: string, - contactEnsName: string, - onSuccess: () => void, - onError: () => void, -): Promise { - socket.emit( - 'pendingMessage', - { - ensName, - contactEnsName, - token, - }, - (result: any) => { - if (result.response === 'success') { - onSuccess(); - } else { - onError(); - } - }, - ); -} -export type CreatePendingEntry = typeof createPendingEntry; diff --git a/packages/lib/storage/src/migrate-storage.test.ts b/packages/lib/storage/src/migrate-storage.test.ts deleted file mode 100644 index 6f01b30d5..000000000 --- a/packages/lib/storage/src/migrate-storage.test.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { - createStorageKey, - getStorageKeyCreationMessage, -} from '@dm3-org/dm3-lib-crypto'; -import { createProfileKeys } from '@dm3-org/dm3-lib-profile'; -import { ethers } from 'ethers'; -import { StorageEnvelopContainer } from './new/types'; -import { Message, Envelop, MessageState } from '@dm3-org/dm3-lib-messaging'; -import { StorageAPI } from '../dist'; -import { Conversation } from './new/types'; -import { migrageStorage } from './new/migrateStorage'; -import { createDB } from './Storage'; - -const USER_1 = 'alice.eth'; -const USER_2 = 'bob.eth'; - -const getMockProfileKeys = async () => { - const nonce = '0'; - const wallet = new ethers.Wallet( - '0xac58f2f021d6f148fd621b355edbd0ebadcf9682019015ef1219cf9c0c2ddc8b', - ); - - const nonceMsg = getStorageKeyCreationMessage(nonce, wallet.address); - const signedMessage = await wallet.signMessage(nonceMsg); - - return await createProfileKeys( - await createStorageKey(signedMessage), - nonce, - ); -}; -const getStorageEnvelopeContainer = (msg: string, timestamp: number = 0) => { - const message: Message = { - metadata: { - to: '', - from: USER_1, - timestamp, - type: 'NEW', - }, - message: msg, - signature: '', - }; - - const envelop: Envelop = { - message, - metadata: { - deliveryInformation: { - from: '', - to: '', - deliveryInstruction: '', - }, - encryptedMessageHash: '', - version: '', - encryptionScheme: '', - signature: '', - }, - }; - - return { - messageState: MessageState.Created, - envelop: envelop, - deliveryServiceIncommingTimestamp: 123, - } as StorageEnvelopContainer; -}; -describe('MigrateStorage', () => { - let newStorage: StorageAPI; - - beforeEach(() => { - //Mock newStorage - newStorage = (() => { - const conversations = new Map(); - - return { - getConversations: async (page: number) => - Array.from(conversations.keys()).map((contactEnsName) => ({ - contactEnsName, - isHidden: false, - previewMessage: undefined, - updatedAt: 0, - })), - getMessages: async (contactEnsName: string, page: number) => [], - addMessageBatch: async ( - contactEnsName: string, - batch: StorageEnvelopContainer[], - ) => { - conversations.set(contactEnsName, [ - ...(conversations.get(contactEnsName) ?? []), - ...batch, - ]); - return ''; - }, - editMessageBatch: async ( - contactEnsName: string, - editedMessage: StorageEnvelopContainer[], - ) => {}, - getNumberOfMessages: async (contactEnsName: string) => 0, - getNumberOfConverations: async () => 0, - addConversation: async (contactEnsName: string) => { - conversations.set(contactEnsName, []); - }, - addMessage: async ( - contactEnsName: string, - envelop: StorageEnvelopContainer, - ) => '', - toggleHideConversation: async ( - contactEnsName: string, - isHidden: boolean, - ) => {}, - }; - })(); - }); - it('should migrate storage', async () => { - const profileKeys = await getMockProfileKeys(); - const db = createDB(profileKeys); - db.conversations.set(USER_1, [ - getStorageEnvelopeContainer('hello', 1), - getStorageEnvelopeContainer('dm3', 2), - ]); - db.conversations.set(USER_2, [ - getStorageEnvelopeContainer('123', 1), - getStorageEnvelopeContainer('456', 2), - ]); - - const tldResolver = async (ensName: string) => { - return ensName.replace('.eth', '.addr.user.dm3.eth'); - }; - - await migrageStorage(db, newStorage, tldResolver); - - const newConversations = await newStorage.getConversations(100, 0); - 0.45; - expect(newConversations.length).toBe(2); - expect(newConversations[0].contactEnsName).toBe( - 'alice.addr.user.dm3.eth', - ); - expect(newConversations[1].contactEnsName).toBe( - 'bob.addr.user.dm3.eth', - ); - }); - it('resolve tld names', async () => { - const profileKeys = await getMockProfileKeys(); - const db = createDB(profileKeys); - db.conversations.set(USER_1, [ - getStorageEnvelopeContainer('hello', 1), - getStorageEnvelopeContainer('dm3', 2), - ]); - db.conversations.set('foo.addr.user.dm3.gno', [ - getStorageEnvelopeContainer('123', 1), - getStorageEnvelopeContainer('456', 2), - ]); - - const tldResolver = async (ensName: string) => { - return ensName.replace('.eth', '.addr.user.dm3.eth'); - }; - - await migrageStorage(db, newStorage, tldResolver); - - const newConversations = await newStorage.getConversations(100, 0); - 0.45; - expect(newConversations.length).toBe(2); - expect(newConversations[0].contactEnsName).toBe( - 'alice.addr.user.dm3.eth', - ); - expect(newConversations[1].contactEnsName).toBe( - 'foo.addr.user.dm3.gno', - ); - }); -}); diff --git a/packages/lib/storage/src/new/cloudStorage/getCloudStorage.ts b/packages/lib/storage/src/new/cloudStorage/getCloudStorage.ts index be167a014..d4cfa3834 100644 --- a/packages/lib/storage/src/new/cloudStorage/getCloudStorage.ts +++ b/packages/lib/storage/src/new/cloudStorage/getCloudStorage.ts @@ -82,10 +82,6 @@ export const getCloudStorage = ( const decryptedEnvelopContainer = await encryption.decryptAsync( message.encryptedEnvelopContainer, ); - console.log( - 'decryptedEnvelopContainer haltedMessages', - decryptedEnvelopContainer, - ); return JSON.parse(decryptedEnvelopContainer); }), diff --git a/packages/messenger-demo/package.json b/packages/messenger-demo/package.json index 6f0f391e0..668c3ffdf 100644 --- a/packages/messenger-demo/package.json +++ b/packages/messenger-demo/package.json @@ -16,6 +16,7 @@ "bootstrap": "^5.1.3", "express": "^4.18.2", "postcss": "^8.4.24", + "react": "^18.3.1", "react-dom": "^18.2.0", "typescript": "^4.7.3", "web-vitals": "^2.1.4" diff --git a/packages/messenger-widget/src/components/Contacts/Contacts.tsx b/packages/messenger-widget/src/components/Contacts/Contacts.tsx index 63b07132c..c6b98aba7 100644 --- a/packages/messenger-widget/src/components/Contacts/Contacts.tsx +++ b/packages/messenger-widget/src/components/Contacts/Contacts.tsx @@ -172,7 +172,7 @@ export function Contacts() { style={{ display: 'flex', flexDirection: 'column', - overflow: 'hidden', + overflow: 'unset', }} inverse={false} hasMore={hasMoreContact} diff --git a/packages/messenger-widget/src/hooks/haltDelivery/useHaltDelivery.test.tsx b/packages/messenger-widget/src/hooks/haltDelivery/useHaltDelivery.test.tsx index 3a6767511..10f5defc1 100644 --- a/packages/messenger-widget/src/hooks/haltDelivery/useHaltDelivery.test.tsx +++ b/packages/messenger-widget/src/hooks/haltDelivery/useHaltDelivery.test.tsx @@ -85,6 +85,7 @@ describe('useConversation hook test cases', () => { }, addConversationAsync: jest.fn(), toggleHideContactAsync: jest.fn(), + getHaltedMessages: () => Promise.resolve([]), initialized: true, }); const deliveryServiceContext: DeliveryServiceContextType = diff --git a/packages/messenger-widget/src/hooks/haltDelivery/useHaltDelivery.ts b/packages/messenger-widget/src/hooks/haltDelivery/useHaltDelivery.ts index f215e0322..17e8f88f4 100644 --- a/packages/messenger-widget/src/hooks/haltDelivery/useHaltDelivery.ts +++ b/packages/messenger-widget/src/hooks/haltDelivery/useHaltDelivery.ts @@ -1,15 +1,15 @@ -import { useContext, useEffect } from 'react'; -import { StorageContext } from '../../context/StorageContext'; -import { TLDContext } from '../../context/TLDContext'; +import { encryptAsymmetric } from '@dm3-org/dm3-lib-crypto'; +import { buildEnvelop } from '@dm3-org/dm3-lib-messaging'; import { Account, DeliveryServiceProfile, getUserProfile, } from '@dm3-org/dm3-lib-profile'; -import { MainnetProviderContext } from '../../context/ProviderContext'; -import { DispatchableEnvelop, buildEnvelop } from '@dm3-org/dm3-lib-messaging'; -import { encryptAsymmetric } from '@dm3-org/dm3-lib-crypto'; +import { useContext, useEffect } from 'react'; import { AuthContext } from '../../context/AuthContext'; +import { MainnetProviderContext } from '../../context/ProviderContext'; +import { StorageContext } from '../../context/StorageContext'; +import { TLDContext } from '../../context/TLDContext'; import { fetchDsProfiles } from '../../utils/deliveryService/fetchDsProfiles'; import { submitEnvelopsToReceiversDs } from '../../utils/deliveryService/submitEnvelopsToReceiversDs'; @@ -47,8 +47,6 @@ export const useHaltDelivery = () => { })), ); - console.log('resolvedAliases', resolvedAliases); - //For each recipient, get the users account const withAccounts = await Promise.all( resolvedAliases.map( @@ -82,12 +80,7 @@ export const useHaltDelivery = () => { return { ...dm3User, messages }; }); - console.log('haltedMessages', dm3UsersWithMessages); - - console.log('withUserProfiles', withAccounts); - console.log('dm3Users', dm3Users); //fetch the ds profiles of every recipient - const withDsProfile = await Promise.all( dm3UsersWithMessages.map(async (dm3User) => ({ ...dm3User, @@ -109,7 +102,7 @@ export const useHaltDelivery = () => { async ( dsProfile: DeliveryServiceProfile, ) => { - //build the dispatchable envelop + //build the dispatchable envelop containing the deliveryInformation of the receiver const dispatchableEnvelop = await buildEnvelop( message.envelop.message, @@ -130,6 +123,10 @@ export const useHaltDelivery = () => { }, ); return { + //To clear the envelop that has been used to store the halted message + haltedEnvelopId: + message.envelop.metadata + ?.encryptedMessageHash!, ...dispatchableEnvelop, //we keep the alias name for the receiver. In case it differes from the ensName aliasName: @@ -146,18 +143,11 @@ export const useHaltDelivery = () => { //The envelops are now ready to be disptched const dispatchableEnvelops = envelops.flat(2); - console.log('flat dispatchableenvelops', dispatchableEnvelops); - await submitEnvelopsToReceiversDs(dispatchableEnvelops); dispatchableEnvelops.map((envelop) => { - clearHaltedMessages( - envelop.envelop.metadata?.encryptedMessageHash!, - envelop.aliasName, - ); + clearHaltedMessages(envelop.haltedEnvelopId, envelop.aliasName); }); - - //Clear messages after they have been dispatched }; handleHaltedMessages(); diff --git a/packages/messenger-widget/src/utils/common-utils.ts b/packages/messenger-widget/src/utils/common-utils.ts index 396d4774b..9d156092b 100644 --- a/packages/messenger-widget/src/utils/common-utils.ts +++ b/packages/messenger-widget/src/utils/common-utils.ts @@ -128,6 +128,8 @@ export const ACCOUNT_CHANGE_POPUP_MESSAGE = export const ENS_PROFILE_BASE_URL = 'https://app.ens.domains/'; +export const AVATAR_IPFS_URL_PREFIX = 'https://ipfs.euc.li/ipfs/'; + export const MOBILE_SCREEN_WIDTH = 800; export const TERMS_AND_CONDITIONS = 'https://dm3.network/terms-and-conditions'; diff --git a/packages/messenger-widget/src/utils/ens-utils.ts b/packages/messenger-widget/src/utils/ens-utils.ts index f0ee95bc0..e6d795535 100644 --- a/packages/messenger-widget/src/utils/ens-utils.ts +++ b/packages/messenger-widget/src/utils/ens-utils.ts @@ -4,11 +4,23 @@ import { ethers } from 'ethers'; import humanIcon from '../assets/images/human.svg'; import { EnsProfileDetails } from '../interfaces/utils'; import { + AVATAR_IPFS_URL_PREFIX, ENS_PROFILE_BASE_URL, MOBILE_SCREEN_WIDTH, getEtherscanUrl, } from './common-utils'; import { RightViewSelected } from './enum-type-utils'; +import axios from 'axios'; + +const isImageLoadable = async (url: string): Promise => { + try { + const { status } = await axios.get(url); + return status === 200; + } catch (error) { + console.log('error in loading image : ', error); + return false; + } +}; // method to get avatar/image url export const getAvatar = async ( @@ -33,7 +45,25 @@ export const getAvatarProfilePic = async ( const avatar = await resolver .getText('avatar') .catch(() => null); - if (avatar) return avatar; + if (avatar) { + /** + * If the image URL is of IPFS, then it can't be directly loaded by + * the browser, so trim the URL and create a proper IPFS url so that + * image can be rendered. Example :- + * Original URL fetched : ipfs://QmQqzMTavQgT4f4T5v6PWBp7XNKtoPmC9jvn12WPT3gkSE (not loadable in browser) + * Modified URL : https://ipfs.euc.li/ipfs/QmQqzMTavQgT4f4T5v6PWBp7XNKtoPmC9jvn12WPT3gkSE (loadable in browser) + */ + const splittedIpfsUrl = avatar.split('ipfs://'); + const imageUrl = + splittedIpfsUrl.length === 2 + ? AVATAR_IPFS_URL_PREFIX.concat( + splittedIpfsUrl[1], + ) + : avatar; + if (await isImageLoadable(imageUrl)) { + return imageUrl; + } + } } const address = await provider.resolveName(ensName); if (address) { diff --git a/yarn.lock b/yarn.lock index a5cedae86..459315227 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2344,6 +2344,7 @@ __metadata: path-browserify: ^1.0.1 postcss: ^8.4.24 process: ^0.11.10 + react: ^18.3.1 react-app-rewired: ^2.2.1 react-dom: ^18.2.0 stream-browserify: ^3.0.0