@bopen-io/messagebox-server 1.1.5 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/.dockerignore +11 -0
  2. package/.env.example +11 -0
  3. package/.eslintignore +2 -0
  4. package/.gcloudignore +17 -0
  5. package/.gitattributes +2 -0
  6. package/.github/workflows/build-and-push.yml +51 -0
  7. package/.github/workflows/deploy.yaml.example +64 -0
  8. package/.github/workflows/image.yaml +66 -0
  9. package/.vscode/launch.json +67 -0
  10. package/AGENTS.md +92 -0
  11. package/BASELINE.md +55 -0
  12. package/DEPLOYING.md +120 -0
  13. package/Dockerfile +63 -0
  14. package/docker-compose.yml +64 -0
  15. package/jest.config.integration.ts +26 -0
  16. package/jest.config.mjs +42 -0
  17. package/jest.config.ts +35 -0
  18. package/jest.setup.mjs +18 -0
  19. package/nginx.conf +36 -0
  20. package/package.json +68 -52
  21. package/scripts/build.js +19 -0
  22. package/scripts/mkenv.sh +31 -0
  23. package/scripts/start.sh +16 -0
  24. package/src/__tests/compose.test.ts +30 -0
  25. package/src/app.ts +210 -0
  26. package/src/compose.ts +286 -0
  27. package/src/config/firebase.ts +183 -0
  28. package/src/context.ts +49 -0
  29. package/src/index.ts +375 -0
  30. package/src/routes/__tests/acknowledgeMessage.test.ts +158 -0
  31. package/src/routes/__tests/listMessages.test.ts +240 -0
  32. package/src/routes/__tests/sendMessage.test.ts +362 -0
  33. package/src/routes/acknowledgeMessage.ts +153 -0
  34. package/src/routes/index.ts +17 -0
  35. package/src/routes/listDevices.ts +80 -0
  36. package/src/routes/listMessages.ts +195 -0
  37. package/src/routes/permissions/getPermission.ts +152 -0
  38. package/src/routes/permissions/getQuote.ts +192 -0
  39. package/src/routes/permissions/index.ts +12 -0
  40. package/src/routes/permissions/listPermissions.ts +202 -0
  41. package/src/routes/permissions/setPermission.ts +155 -0
  42. package/src/routes/registerDevice.ts +155 -0
  43. package/src/routes/sendMessage.ts +531 -0
  44. package/src/runtimeDeps.ts +29 -0
  45. package/src/swagger.ts +54 -0
  46. package/src/telemetry.ts +158 -0
  47. package/src/types/messagePermissions.ts +18 -0
  48. package/src/types/mock-knex.d.ts +18 -0
  49. package/src/types/notifications.ts +27 -0
  50. package/src/utils/logger.ts +92 -0
  51. package/src/utils/messagePermissions.ts +148 -0
  52. package/src/utils/sendFCMNotification.ts +143 -0
  53. package/tsconfig.json +36 -0
  54. package/tsconfig.types.json +11 -0
  55. package/out/knexfile.js +0 -25
  56. package/out/knexfile.js.map +0 -1
  57. package/out/src/app.js +0 -160
  58. package/out/src/app.js.map +0 -1
  59. package/out/src/config/firebase.js +0 -150
  60. package/out/src/config/firebase.js.map +0 -1
  61. package/out/src/index.js +0 -295
  62. package/out/src/index.js.map +0 -1
  63. package/out/src/migrations/2022-12-28-001-initial-migration.js +0 -28
  64. package/out/src/migrations/2022-12-28-001-initial-migration.js.map +0 -1
  65. package/out/src/migrations/2023-01-17-messages-update.js +0 -11
  66. package/out/src/migrations/2023-01-17-messages-update.js.map +0 -1
  67. package/out/src/migrations/2024-03-05-001-messageID-upgrade.js +0 -21
  68. package/out/src/migrations/2024-03-05-001-messageID-upgrade.js.map +0 -1
  69. package/out/src/migrations/2025-01-31-001-notification-permissions.js +0 -59
  70. package/out/src/migrations/2025-01-31-001-notification-permissions.js.map +0 -1
  71. package/out/src/migrations/2025-01-31-002-device-registrations.js +0 -24
  72. package/out/src/migrations/2025-01-31-002-device-registrations.js.map +0 -1
  73. package/out/src/routes/__tests/acknowledgeMessage.test.js +0 -129
  74. package/out/src/routes/__tests/acknowledgeMessage.test.js.map +0 -1
  75. package/out/src/routes/__tests/listMessages.test.js +0 -211
  76. package/out/src/routes/__tests/listMessages.test.js.map +0 -1
  77. package/out/src/routes/__tests/sendMessage.test.js +0 -307
  78. package/out/src/routes/__tests/sendMessage.test.js.map +0 -1
  79. package/out/src/routes/acknowledgeMessage.js +0 -144
  80. package/out/src/routes/acknowledgeMessage.js.map +0 -1
  81. package/out/src/routes/index.js +0 -17
  82. package/out/src/routes/index.js.map +0 -1
  83. package/out/src/routes/listDevices.js +0 -74
  84. package/out/src/routes/listDevices.js.map +0 -1
  85. package/out/src/routes/listMessages.js +0 -186
  86. package/out/src/routes/listMessages.js.map +0 -1
  87. package/out/src/routes/permissions/getPermission.js +0 -149
  88. package/out/src/routes/permissions/getPermission.js.map +0 -1
  89. package/out/src/routes/permissions/getQuote.js +0 -165
  90. package/out/src/routes/permissions/getQuote.js.map +0 -1
  91. package/out/src/routes/permissions/index.js +0 -12
  92. package/out/src/routes/permissions/index.js.map +0 -1
  93. package/out/src/routes/permissions/listPermissions.js +0 -190
  94. package/out/src/routes/permissions/listPermissions.js.map +0 -1
  95. package/out/src/routes/permissions/setPermission.js +0 -137
  96. package/out/src/routes/permissions/setPermission.js.map +0 -1
  97. package/out/src/routes/registerDevice.js +0 -150
  98. package/out/src/routes/registerDevice.js.map +0 -1
  99. package/out/src/routes/sendMessage.js +0 -451
  100. package/out/src/routes/sendMessage.js.map +0 -1
  101. package/out/src/swagger.js +0 -49
  102. package/out/src/swagger.js.map +0 -1
  103. package/out/src/types/messagePermissions.js +0 -2
  104. package/out/src/types/messagePermissions.js.map +0 -1
  105. package/out/src/types/notifications.js +0 -2
  106. package/out/src/types/notifications.js.map +0 -1
  107. package/out/src/utils/logger.js +0 -24
  108. package/out/src/utils/logger.js.map +0 -1
  109. package/out/src/utils/messagePermissions.js +0 -126
  110. package/out/src/utils/messagePermissions.js.map +0 -1
  111. package/out/src/utils/sendFCMNotification.js +0 -121
  112. package/out/src/utils/sendFCMNotification.js.map +0 -1
  113. package/out/tsconfig.tsbuildinfo +0 -1
package/out/src/index.js DELETED
@@ -1,295 +0,0 @@
1
- /**
2
- * @file index.ts
3
- * @description
4
- * Main entry point for the MessageBox Server.
5
- *
6
- * Responsibilities:
7
- * - Initializes environment variables and config
8
- * - Creates HTTP and WebSocket servers
9
- * - Boots authentication and route handlers
10
- * - Sets up database migrations after a short delay
11
- * - Emits and handles real-time message events over WebSocket
12
- *
13
- * Exports:
14
- * - `start()` for programmatic bootstrapping
15
- * - `http` and `io` server instances
16
- * - `HTTP_PORT` and `ROUTING_PREFIX` for external reference
17
- */
18
- import * as dotenv from 'dotenv';
19
- import { app, appReady, getWallet, knex } from './app.js';
20
- import { createServer } from 'http';
21
- import { PublicKey } from '@bsv/sdk';
22
- import { Logger } from './utils/logger.js';
23
- import { AuthSocketServer } from '@bsv/authsocket';
24
- import * as crypto from 'crypto';
25
- import { initializeFirebase } from './config/firebase.js';
26
- global.self = { crypto };
27
- dotenv.config();
28
- // Load environment variables
29
- const { NODE_ENV = 'development', PORT, SERVER_PRIVATE_KEY, ENABLE_WEBSOCKETS = 'true', ROUTING_PREFIX = '' } = process.env;
30
- // if (NODE_ENV === 'development' || process.env.LOGGING_ENABLED === 'true') {
31
- // Logger.enable()
32
- // }
33
- Logger.enable();
34
- // Determine which port to listen on
35
- const parsedPort = Number(PORT);
36
- const parsedEnvPort = Number(process.env.HTTP_PORT);
37
- const HTTP_PORT = NODE_ENV !== 'development'
38
- ? 3000
39
- : !isNaN(parsedPort) && parsedPort > 0
40
- ? parsedPort
41
- : !isNaN(parsedEnvPort) && parsedEnvPort > 0
42
- ? parsedEnvPort
43
- : 8080;
44
- // Ensure private key is available before proceeding
45
- if (SERVER_PRIVATE_KEY === undefined || SERVER_PRIVATE_KEY === null || SERVER_PRIVATE_KEY.trim() === '') {
46
- throw new Error('SERVER_PRIVATE_KEY is not defined in the environment variables.');
47
- }
48
- // Initialize Firebase Admin (only when ENABLE_FIREBASE=true)
49
- initializeFirebase();
50
- // Create HTTP server
51
- /* eslint-disable @typescript-eslint/no-misused-promises */
52
- const http = createServer(app);
53
- // WebSocket setup (only if enabled)
54
- let io = null;
55
- /**
56
- * @function start
57
- * @description
58
- * Initializes the WebSocket server with identity-key-based authentication
59
- * and attaches all supported event handlers for:
60
- * - `sendMessage`
61
- * - `joinRoom`
62
- * - `leaveRoom`
63
- * - `disconnect`
64
- *
65
- * Only runs if `ENABLE_WEBSOCKETS` is set to `true` in the environment.
66
- *
67
- * @returns {Promise<void>} Resolves once WebSocket listeners are fully attached.
68
- */
69
- export const start = async () => {
70
- await appReady;
71
- if (ENABLE_WEBSOCKETS.toLowerCase() === 'true') {
72
- Logger.log('[WEBSOCKET] Initializing WebSocket support...');
73
- io = new AuthSocketServer(http, {
74
- wallet: await getWallet(),
75
- cors: {
76
- origin: '*',
77
- methods: ['GET', 'POST']
78
- }
79
- });
80
- // Map to store authenticated identity keys
81
- const authenticatedSockets = new Map();
82
- io.on('connection', (socket) => {
83
- Logger.log('[WEBSOCKET] New connection established.');
84
- // Handle immediate authentication if identityKey is available
85
- if (typeof socket.identityKey === 'string' && socket.identityKey.trim() !== '') {
86
- try {
87
- const parsedIdentityKey = PublicKey.fromString(socket.identityKey);
88
- Logger.log('[DEBUG] Parsed WebSocket Identity Key Successfully:', parsedIdentityKey.toString());
89
- authenticatedSockets.set(socket.id, parsedIdentityKey.toString());
90
- Logger.log('[WEBSOCKET] Identity key stored for socket ID:', socket.id);
91
- // Send confirmation immediately if identity key is provided on connection
92
- void socket.emit('authenticationSuccess', { status: 'success' });
93
- }
94
- catch (error) {
95
- Logger.error('[ERROR] Failed to parse WebSocket identity key:', error);
96
- }
97
- }
98
- else {
99
- // Wait for 'authenticated' event if identityKey was not in handshake
100
- Logger.warn('[WARN] WebSocket connection received without identity key. Waiting for authentication...');
101
- let identityKeyHandled = false;
102
- const authListener = async (data) => {
103
- if (identityKeyHandled)
104
- return;
105
- Logger.log('[WEBSOCKET] Received authentication data:', data);
106
- if (data !== null && data !== undefined && typeof data.identityKey === 'string' && data.identityKey.trim().length > 0) {
107
- try {
108
- const parsedIdentityKey = PublicKey.fromString(data.identityKey);
109
- Logger.log('[DEBUG] Retrieved and parsed Identity Key after connection:', parsedIdentityKey.toString());
110
- authenticatedSockets.set(socket.id, parsedIdentityKey.toString());
111
- Logger.log('[WEBSOCKET] Stored authenticated Identity Key for socket ID:', socket.id);
112
- identityKeyHandled = true;
113
- Logger.log(`New authenticated WebSocket connection from: ${authenticatedSockets.get(socket.id) ?? 'unknown'}`);
114
- // Emit authentication success message
115
- await socket.emit('authenticationSuccess', { status: 'success' }).catch(error => {
116
- Logger.error('[WEBSOCKET ERROR] Failed to send authentication success event:', error);
117
- });
118
- }
119
- catch (error) {
120
- Logger.error('[ERROR] Failed to parse Identity Key from authenticated event:', error);
121
- await socket.emit('authenticationFailed', { reason: 'Invalid identity key format' });
122
- }
123
- }
124
- else {
125
- Logger.warn('[WARN] Invalid or missing identity key in authentication event.');
126
- await socket.emit('authenticationFailed', { reason: 'Missing identity key' });
127
- }
128
- };
129
- // Ensure `authListener` is used properly
130
- socket.on('authenticated', authListener);
131
- }
132
- // Handle sendMessage over WebSocket
133
- socket.on('sendMessage', async (data) => {
134
- if (typeof data !== 'object' || data == null) {
135
- Logger.error('[WEBSOCKET ERROR] Invalid data object received.');
136
- await socket.emit('messageFailed', { reason: 'Invalid data object' });
137
- return;
138
- }
139
- const { roomId, message } = data;
140
- if (!authenticatedSockets.has(socket.id)) {
141
- Logger.warn('[WEBSOCKET] Unauthorized attempt to send a message.');
142
- await socket.emit('paymentFailed', { reason: 'Unauthorized: WebSocket not authenticated' });
143
- return;
144
- }
145
- Logger.log(`[WEBSOCKET] Processing sendMessage for room: ${roomId}`);
146
- try {
147
- if (typeof roomId !== 'string' || roomId.trim() === '') {
148
- Logger.error('[WEBSOCKET ERROR] Invalid roomId:', roomId);
149
- await socket.emit('messageFailed', { reason: 'Invalid room ID' });
150
- return;
151
- }
152
- if (typeof message !== 'object' || message == null) {
153
- Logger.error('[WEBSOCKET ERROR] Invalid message object:', message);
154
- await socket.emit('messageFailed', { reason: 'Invalid message object' });
155
- return;
156
- }
157
- if (typeof message.body !== 'string' || message.body.trim() === '') {
158
- Logger.error('[WEBSOCKET ERROR] Invalid message body:', message.body);
159
- await socket.emit('messageFailed', { reason: 'Invalid message body' });
160
- return;
161
- }
162
- Logger.log(`[WEBSOCKET] Acknowledging message ${message.messageId} to sender.`);
163
- const ackPayload = {
164
- status: 'success',
165
- messageId: message.messageId
166
- };
167
- Logger.log(`[WEBSOCKET] Emitting ack event: sendMessageAck-${roomId}`);
168
- socket.emit(`sendMessageAck-${roomId}`, ackPayload).catch((error) => {
169
- Logger.error(`[WEBSOCKET ERROR] Failed to emit sendMessageAck-${roomId}:`, error);
170
- });
171
- // Store message in the database just like HTTP sendMessage route
172
- try {
173
- const parts = roomId.split('-');
174
- const messageBoxType = parts.length > 1 ? parts[1] : 'default';
175
- Logger.log(`[WEBSOCKET] Parsed messageBoxType: ${messageBoxType}`);
176
- Logger.log(`[WEBSOCKET] Attempting to store message for recipient: ${message.recipient}, box type: ${messageBoxType}`);
177
- let messageBox = await knex('messageBox')
178
- .where({ identityKey: message.recipient, type: messageBoxType })
179
- .first();
180
- if (messageBox === null || messageBox === undefined) {
181
- Logger.log('[WEBSOCKET] messageBox not found. Creating new messageBox.');
182
- await knex('messageBox').insert({
183
- identityKey: message.recipient,
184
- type: messageBoxType,
185
- created_at: new Date(),
186
- updated_at: new Date()
187
- });
188
- }
189
- messageBox = await knex('messageBox')
190
- .where({ identityKey: message.recipient, type: messageBoxType })
191
- .select('messageBoxId')
192
- .first();
193
- const messageBoxId = messageBox?.messageBoxId ?? null;
194
- if (messageBoxId === null || messageBoxId === undefined) {
195
- Logger.warn('[WEBSOCKET WARNING] messageBoxId is null — message may not be stored correctly!');
196
- }
197
- else {
198
- Logger.log(`[WEBSOCKET] Resolved messageBoxId: ${String(messageBoxId)}`);
199
- }
200
- const senderKey = authenticatedSockets.get(socket.id) ?? null;
201
- const insertResult = await knex('messages')
202
- .insert({
203
- messageId: message.messageId,
204
- messageBoxId,
205
- sender: senderKey,
206
- recipient: message.recipient,
207
- body: message.body,
208
- created_at: new Date(),
209
- updated_at: new Date()
210
- })
211
- .onConflict('messageId')
212
- .ignore();
213
- if (insertResult.length === 0) {
214
- Logger.warn('[WEBSOCKET WARNING] Message insert was ignored due to conflict (duplicate messageId?)');
215
- }
216
- else {
217
- Logger.log('[WEBSOCKET] Message successfully stored in DB.');
218
- }
219
- }
220
- catch (dbError) {
221
- Logger.error('[WEBSOCKET ERROR] Failed to store message in DB:', dbError);
222
- await socket.emit('messageFailed', { reason: 'Failed to store message' });
223
- return;
224
- }
225
- if (io != null) {
226
- Logger.log(`[WEBSOCKET] Emitting message to room ${roomId}`);
227
- io.emit(`sendMessage-${roomId}`, {
228
- sender: authenticatedSockets.get(socket.id),
229
- messageId: message.messageId,
230
- body: message.body
231
- });
232
- }
233
- else {
234
- Logger.error('[WEBSOCKET ERROR] io is null, cannot emit message.');
235
- }
236
- }
237
- catch (error) {
238
- Logger.error('[WEBSOCKET ERROR] Unexpected failure in sendMessage handler:', error);
239
- await socket.emit('messageFailed', { reason: 'Unexpected error occurred' });
240
- }
241
- });
242
- // Handle joining/leaving rooms
243
- socket.on('joinRoom', async (roomId) => {
244
- if (!authenticatedSockets.has(socket.id)) {
245
- Logger.warn('[WEBSOCKET] Unauthorized attempt to join a room.');
246
- await socket.emit('joinFailed', { reason: 'Unauthorized: WebSocket not authenticated' });
247
- return;
248
- }
249
- if (roomId == null || typeof roomId !== 'string' || roomId.trim() === '') {
250
- Logger.error('[WEBSOCKET ERROR] Invalid roomId:', roomId);
251
- await socket.emit('joinFailed', { reason: 'Invalid room ID' });
252
- return;
253
- }
254
- Logger.log(`[WEBSOCKET] User ${socket.id} joined room ${roomId}`);
255
- await socket.emit('joinedRoom', { roomId });
256
- });
257
- socket.on('leaveRoom', async (roomId) => {
258
- if (!authenticatedSockets.has(socket.id)) {
259
- Logger.warn('[WEBSOCKET] Unauthorized attempt to leave a room.');
260
- await socket.emit('leaveFailed', { reason: 'Unauthorized: WebSocket not authenticated' });
261
- return;
262
- }
263
- if (roomId == null || roomId === '' || typeof roomId !== 'string' || roomId.trim() === '') {
264
- Logger.error('[WEBSOCKET ERROR] Invalid roomId:', roomId);
265
- await socket.emit('leaveFailed', { reason: 'Invalid room ID' });
266
- return;
267
- }
268
- Logger.log(`[WEBSOCKET] User ${socket.id} left room ${roomId}`);
269
- await socket.emit('leftRoom', { roomId });
270
- });
271
- // Clean up on disconnect
272
- socket.on('disconnect', (reason) => {
273
- Logger.log(`[WEBSOCKET] Disconnected: ${reason}`);
274
- authenticatedSockets.delete(socket.id);
275
- });
276
- });
277
- }
278
- };
279
- // Export for testing and CLI use
280
- export { io, http, HTTP_PORT, ROUTING_PREFIX };
281
- // Only run server if not in test mode
282
- if (NODE_ENV !== 'test') {
283
- http.listen(HTTP_PORT, () => {
284
- Logger.log('MessageBox listening on port', HTTP_PORT);
285
- (async () => {
286
- await knex.migrate.latest();
287
- })().catch((error) => {
288
- Logger.error('[STARTUP ERROR]', error);
289
- });
290
- });
291
- start().catch(error => {
292
- Logger.error('[SERVER INIT ERROR]', error);
293
- });
294
- }
295
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,28 +0,0 @@
1
- export async function up(knex) {
2
- await knex.schema.createTable('messageBox', (table) => {
3
- table.increments('messageBoxId').primary();
4
- table.timestamps(true, true);
5
- table.string('type').notNullable(); // What type of messages go in here?
6
- table.string('identityKey').notNullable(); // Who's message box is this?
7
- table.unique(['type', 'identityKey']);
8
- });
9
- await knex.schema.createTable('messages', (table) => {
10
- table.increments('messageId').primary();
11
- table.timestamps(true, true);
12
- table
13
- .integer('messageBoxId')
14
- .unsigned()
15
- .references('messageBoxId')
16
- .inTable('messageBox')
17
- .onDelete('CASCADE'); // All messages get deleted if the messageBox is deleted
18
- table.string('sender').notNullable();
19
- table.string('recipient').notNullable();
20
- table.text('body', 'longtext').notNullable(); // Contents of the message
21
- table.boolean('acknowledged').defaultTo(false);
22
- });
23
- }
24
- export async function down(knex) {
25
- await knex.schema.dropTableIfExists('messages');
26
- await knex.schema.dropTableIfExists('messageBox');
27
- }
28
- //# sourceMappingURL=2022-12-28-001-initial-migration.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"2022-12-28-001-initial-migration.js","sourceRoot":"","sources":["../../../src/migrations/2022-12-28-001-initial-migration.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,EAAE,CAAE,IAAU;IAClC,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE;QACpD,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAA;QAC1C,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QAC5B,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAA,CAAC,oCAAoC;QACvE,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,CAAA,CAAC,6BAA6B;QACvE,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE;QAClD,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,CAAA;QACvC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QAC5B,KAAK;aACF,OAAO,CAAC,cAAc,CAAC;aACvB,QAAQ,EAAE;aACV,UAAU,CAAC,cAAc,CAAC;aAC1B,OAAO,CAAC,YAAY,CAAC;aACrB,QAAQ,CAAC,SAAS,CAAC,CAAA,CAAC,wDAAwD;QAC/E,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAA;QACpC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAA;QACvC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,WAAW,EAAE,CAAA,CAAC,0BAA0B;QACvE,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAE,IAAU;IACpC,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAA;IAC/C,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAA;AACnD,CAAC"}
@@ -1,11 +0,0 @@
1
- export async function up(knex) {
2
- await knex.schema.alterTable('messages', (table) => {
3
- table.dropColumn('acknowledged');
4
- });
5
- }
6
- export async function down(knex) {
7
- await knex.schema.alterTable('messages', (table) => {
8
- table.boolean('acknowledged').defaultTo(false);
9
- });
10
- }
11
- //# sourceMappingURL=2023-01-17-messages-update.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"2023-01-17-messages-update.js","sourceRoot":"","sources":["../../../src/migrations/2023-01-17-messages-update.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,EAAE,CAAE,IAAU;IAClC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE;QACjD,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,CAAA;IAClC,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAE,IAAU;IACpC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE;QACjD,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -1,21 +0,0 @@
1
- export async function up(knex) {
2
- // Drop the existing 'messageId' column
3
- await knex.schema.alterTable('messages', (table) => {
4
- table.dropColumn('messageId');
5
- });
6
- // Add 'messageId' back as a unique string
7
- await knex.schema.alterTable('messages', (table) => {
8
- table.string('messageId').unique().notNullable();
9
- });
10
- }
11
- export async function down(knex) {
12
- // Drop the new 'messageId' column
13
- await knex.schema.alterTable('messages', (table) => {
14
- table.dropColumn('messageId');
15
- });
16
- // Restore 'messageId' as an auto-incrementing primary key
17
- await knex.schema.alterTable('messages', (table) => {
18
- table.increments('messageId').primary();
19
- });
20
- }
21
- //# sourceMappingURL=2024-03-05-001-messageID-upgrade.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"2024-03-05-001-messageID-upgrade.js","sourceRoot":"","sources":["../../../src/migrations/2024-03-05-001-messageID-upgrade.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,EAAE,CAAE,IAAU;IAClC,uCAAuC;IACvC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE;QACjD,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;IAC/B,CAAC,CAAC,CAAA;IAEF,0CAA0C;IAC1C,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE;QACjD,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAA;IAClD,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAE,IAAU;IACpC,kCAAkC;IAClC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE;QACjD,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;IAC/B,CAAC,CAAC,CAAA;IAEF,0DAA0D;IAC1D,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE;QACjD,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,CAAA;IACzC,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -1,59 +0,0 @@
1
- export async function up(knex) {
2
- // Create generalized message permissions table for all box/sender combinations
3
- await knex.schema.createTable('message_permissions', (table) => {
4
- table.increments('id').primary();
5
- table.timestamp('created_at').defaultTo(knex.fn.now());
6
- table.timestamp('updated_at').defaultTo(knex.fn.now());
7
- table.string('recipient', 255).notNullable(); // identityKey of who this permission belongs to
8
- table.string('sender', 255).nullable(); // identityKey of sender (NULL for box-wide defaults)
9
- table.string('message_box', 255).notNullable(); // messageBox type (e.g., 'notifications', 'inbox', etc.)
10
- table.integer('recipient_fee').notNullable(); // -1 = block all, 0 = always allow, >0 = satoshi amount required
11
- table.unique(['recipient', 'sender', 'message_box']);
12
- table.index('recipient');
13
- table.index(['recipient', 'message_box']);
14
- table.index('message_box');
15
- table.index('sender');
16
- });
17
- // Create server fee configuration table
18
- await knex.schema.createTable('server_fees', (table) => {
19
- table.increments('id').primary();
20
- table.timestamp('created_at').defaultTo(knex.fn.now());
21
- table.timestamp('updated_at').defaultTo(knex.fn.now());
22
- table.string('message_box').notNullable(); // messageBox type
23
- table.integer('delivery_fee').notNullable(); // Server delivery fee in satoshis
24
- table.unique(['message_box']); // Each box type can only have one server fee setting
25
- });
26
- // Insert default server fees for different message box types
27
- const existingFees = await knex('server_fees').select('message_box');
28
- const existingMessageBoxes = existingFees.map(fee => fee.message_box);
29
- const defaultFees = [
30
- {
31
- message_box: 'notifications',
32
- delivery_fee: 10, // Higher fee for FCM delivery
33
- created_at: new Date(),
34
- updated_at: new Date()
35
- },
36
- {
37
- message_box: 'inbox',
38
- delivery_fee: 0, // Free for regular inbox
39
- created_at: new Date(),
40
- updated_at: new Date()
41
- },
42
- {
43
- message_box: 'payment_inbox',
44
- delivery_fee: 0, // Free for payment inbox
45
- created_at: new Date(),
46
- updated_at: new Date()
47
- }
48
- ];
49
- // Only insert fees for message boxes that don't already exist
50
- const feesToInsert = defaultFees.filter(fee => !existingMessageBoxes.includes(fee.message_box));
51
- if (feesToInsert.length > 0) {
52
- await knex('server_fees').insert(feesToInsert);
53
- }
54
- }
55
- export async function down(knex) {
56
- await knex.schema.dropTableIfExists('server_fees');
57
- await knex.schema.dropTableIfExists('message_permissions');
58
- }
59
- //# sourceMappingURL=2025-01-31-001-notification-permissions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"2025-01-31-001-notification-permissions.js","sourceRoot":"","sources":["../../../src/migrations/2025-01-31-001-notification-permissions.ts"],"names":[],"mappings":"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"}
@@ -1,24 +0,0 @@
1
- export async function up(knex) {
2
- // Create device registrations table for FCM push notifications
3
- await knex.schema.createTable('device_registrations', (table) => {
4
- table.increments('id').primary();
5
- table.timestamp('created_at').defaultTo(knex.fn.now());
6
- table.timestamp('updated_at').defaultTo(knex.fn.now());
7
- table.string('identity_key', 255).notNullable(); // User's identity key
8
- table.string('fcm_token', 500).notNullable(); // Firebase Cloud Messaging token (can be long)
9
- table.string('device_id', 255).nullable(); // Optional device identifier
10
- table.string('platform', 50).nullable(); // 'ios', 'android', 'web', etc.
11
- table.timestamp('last_used').nullable(); // When this token was last successfully used
12
- table.boolean('active').defaultTo(true); // Whether this token is still active
13
- // Unique constraint to prevent duplicate token registrations
14
- table.unique(['fcm_token']);
15
- // Index for efficient lookups by identity key
16
- table.index('identity_key');
17
- table.index(['identity_key', 'active']);
18
- table.index('last_used');
19
- });
20
- }
21
- export async function down(knex) {
22
- await knex.schema.dropTableIfExists('device_registrations');
23
- }
24
- //# sourceMappingURL=2025-01-31-002-device-registrations.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"2025-01-31-002-device-registrations.js","sourceRoot":"","sources":["../../../src/migrations/2025-01-31-002-device-registrations.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC,IAAU;IACjC,+DAA+D;IAC/D,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,sBAAsB,EAAE,CAAC,KAAK,EAAE,EAAE;QAC9D,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAA;QAChC,KAAK,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAA;QACtD,KAAK,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAA;QACtD,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA,CAAC,sBAAsB;QACtE,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA,CAAC,+CAA+C;QAC5F,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAA,CAAC,6BAA6B;QACvE,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAA,CAAC,gCAAgC;QACxE,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAA,CAAC,6CAA6C;QACrF,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA,CAAC,qCAAqC;QAE7E,6DAA6D;QAC7D,KAAK,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC,CAAA;QAE3B,8CAA8C;QAC9C,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;QAC3B,KAAK,CAAC,KAAK,CAAC,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAA;QACvC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;IAC1B,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAU;IACnC,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,CAAC,CAAA;AAC7D,CAAC"}
@@ -1,129 +0,0 @@
1
- /* eslint-env jest */
2
- import acknowledgeMessage from '../acknowledgeMessage.js';
3
- import mockKnex from 'mock-knex';
4
- const knex = acknowledgeMessage.knex;
5
- let queryTracker;
6
- // Define Mock Express Response Object
7
- const mockRes = {
8
- status: jest.fn().mockReturnThis(),
9
- json: jest.fn().mockReturnThis(),
10
- sendStatus: jest.fn().mockReturnThis(),
11
- send: jest.fn().mockReturnThis(),
12
- end: jest.fn().mockReturnThis(),
13
- setHeader: jest.fn().mockReturnThis(),
14
- getHeader: jest.fn(),
15
- getHeaders: jest.fn(),
16
- header: jest.fn().mockReturnThis(),
17
- type: jest.fn().mockReturnThis(),
18
- format: jest.fn(),
19
- location: jest.fn().mockReturnThis(),
20
- redirect: jest.fn().mockReturnThis(),
21
- append: jest.fn().mockReturnThis(),
22
- render: jest.fn(),
23
- vary: jest.fn().mockReturnThis(),
24
- cookie: jest.fn().mockReturnThis(),
25
- clearCookie: jest.fn().mockReturnThis()
26
- };
27
- let validReq;
28
- describe('acknowledgeMessage', () => {
29
- beforeAll(() => {
30
- mockKnex.mock(knex);
31
- });
32
- beforeEach(() => {
33
- jest.spyOn(console, 'error').mockImplementation(() => { });
34
- queryTracker = mockKnex.getTracker();
35
- queryTracker.install();
36
- validReq = {
37
- auth: {
38
- identityKey: 'mockIdKey'
39
- },
40
- body: {
41
- messageIds: ['123']
42
- },
43
- get: jest.fn(),
44
- header: jest.fn()
45
- };
46
- });
47
- afterEach(() => {
48
- jest.clearAllMocks();
49
- if (queryTracker !== null && queryTracker !== undefined) {
50
- queryTracker.uninstall();
51
- }
52
- });
53
- afterAll(() => {
54
- mockKnex.unmock(knex);
55
- });
56
- it('Throws an error if messageId is missing', async () => {
57
- delete validReq.body.messageIds;
58
- await acknowledgeMessage.func(validReq, mockRes);
59
- expect(mockRes.status).toHaveBeenCalledWith(400);
60
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
61
- status: 'error',
62
- code: 'ERR_MESSAGE_ID_REQUIRED'
63
- }));
64
- });
65
- it('Throws an error if messageIds is not an Array', async () => {
66
- validReq.body.messageIds = '24';
67
- await acknowledgeMessage.func(validReq, mockRes);
68
- expect(mockRes.status).toHaveBeenCalledWith(400);
69
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
70
- status: 'error',
71
- code: 'ERR_INVALID_MESSAGE_ID',
72
- description: 'Message IDs must be formatted as an array of strings!'
73
- }));
74
- }, 7000);
75
- it('Deletes a message', async () => {
76
- queryTracker.on('query', (q, s) => {
77
- if (s === 1) {
78
- expect(q.method).toEqual('del');
79
- expect(q.sql).toEqual('delete from `messages` where `recipient` = ? and `messageId` in (?)');
80
- expect(q.bindings).toEqual([
81
- 'mockIdKey',
82
- '123'
83
- ]);
84
- q.response(true);
85
- }
86
- else {
87
- q.response([]);
88
- }
89
- });
90
- await acknowledgeMessage.func(validReq, mockRes);
91
- expect(mockRes.status).toHaveBeenCalledWith(200);
92
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
93
- status: 'success'
94
- }));
95
- });
96
- it('Throws an error if deletion fails', async () => {
97
- queryTracker.on('query', (q, step) => {
98
- if (step === 1) {
99
- expect(q.method).toEqual('del');
100
- expect(q.sql).toEqual('delete from `messages` where `recipient` = ? and `messageId` in (?)');
101
- expect(q.bindings).toEqual(['mockIdKey', '123']);
102
- q.response(0); // Simulate deletion failure
103
- }
104
- else {
105
- q.response([]); // Prevent test from hanging due to unhandled second query
106
- }
107
- });
108
- await acknowledgeMessage.func(validReq, mockRes);
109
- expect(mockRes.status).toHaveBeenCalledWith(400);
110
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
111
- status: 'error',
112
- code: 'ERR_INVALID_ACKNOWLEDGMENT',
113
- description: 'Message not found!'
114
- }));
115
- }, 7000);
116
- it('Throws unknown errors', async () => {
117
- queryTracker.on('query', () => {
118
- throw new Error('Failed');
119
- });
120
- await acknowledgeMessage.func(validReq, mockRes);
121
- expect(mockRes.status).toHaveBeenCalledWith(500);
122
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
123
- status: 'error',
124
- code: 'ERR_INTERNAL_ERROR',
125
- description: 'An internal error has occurred while acknowledging the message'
126
- }));
127
- });
128
- });
129
- //# sourceMappingURL=acknowledgeMessage.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"acknowledgeMessage.test.js","sourceRoot":"","sources":["../../../../src/routes/__tests/acknowledgeMessage.test.ts"],"names":[],"mappings":"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"}