holosphere 1.1.1 → 1.1.3

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.
@@ -0,0 +1,337 @@
1
+ import HoloSphere from '../holosphere.js';
2
+ import * as h3 from 'h3-js';
3
+ import Gun from 'gun';
4
+ import 'gun/sea';
5
+
6
+ describe('Space Authentication and Authorization', () => {
7
+ // Global HoloSphere instances
8
+ let holoSphere;
9
+ let strictHoloSphere;
10
+ const testAppName = 'test-auth-app';
11
+ const testCredentials = {
12
+ spacename: 'testspace@example.com',
13
+ password: 'TestPassword123!'
14
+ };
15
+ const testHolon = h3.latLngToCell(40.7128, -74.0060, 7);
16
+ const testLens = 'authTestLens';
17
+
18
+ beforeAll(async () => {
19
+ // Create global instances
20
+ holoSphere = new HoloSphere(testAppName, false);
21
+ strictHoloSphere = new HoloSphere(testAppName, true);
22
+
23
+ // Clean up any existing test spaces
24
+ try {
25
+ await holoSphere.deleteGlobal('spaces', testCredentials.spacename);
26
+ await holoSphere.deleteGlobal('spaces', 'newspace@example.com');
27
+ await holoSphere.deleteGlobal('spaces', 'sharedspace@example.com');
28
+ } catch (error) {
29
+ console.log('Cleanup error (can be ignored):', error);
30
+ }
31
+
32
+ // Create a test space
33
+ await holoSphere.createSpace(testCredentials.spacename, testCredentials.password);
34
+ }, 10000); // Increase timeout for SEA operations
35
+
36
+ describe('Space Management with SEA', () => {
37
+ test('should create a new space with SEA authentication', async () => {
38
+ const newSpace = {
39
+ spacename: 'newspace@example.com',
40
+ password: 'NewPassword123!'
41
+ };
42
+
43
+ const result = await holoSphere.createSpace(newSpace.spacename, newSpace.password);
44
+ expect(result).toBeTruthy();
45
+
46
+ // Verify SEA data structure
47
+ const spaceData = await holoSphere.getGlobal('spaces', newSpace.spacename);
48
+ expect(spaceData).toBeDefined();
49
+ expect(spaceData.auth).toBeDefined();
50
+ expect(spaceData.pub).toBeDefined();
51
+ expect(spaceData.epub).toBeDefined();
52
+
53
+ // Try creating the same space again should fail
54
+ await expect(holoSphere.createSpace(newSpace.spacename, newSpace.password))
55
+ .rejects.toThrow('Space already exists');
56
+ });
57
+
58
+ test('should login space with SEA authentication', async () => {
59
+ const result = await holoSphere.login(testCredentials.spacename, testCredentials.password);
60
+ expect(result).toBeTruthy();
61
+ expect(holoSphere.currentSpace).toBeDefined();
62
+ expect(holoSphere.currentSpace.alias).toBe(testCredentials.spacename);
63
+ expect(holoSphere.currentSpace.auth).toBeDefined();
64
+ });
65
+
66
+ test('should reject login with incorrect credentials using SEA', async () => {
67
+ await expect(holoSphere.login(testCredentials.spacename, 'wrongpassword'))
68
+ .rejects.toThrow('Authentication failed');
69
+ });
70
+
71
+ test('should have valid SEA pair after login', async () => {
72
+ await holoSphere.login(testCredentials.spacename, testCredentials.password);
73
+ expect(holoSphere.currentSpace).toBeDefined();
74
+ expect(holoSphere.currentSpace.pub).toBeDefined();
75
+ expect(holoSphere.currentSpace.epub).toBeDefined();
76
+ expect(holoSphere.currentSpace.auth).toBeDefined();
77
+ });
78
+
79
+ test('should logout space', async () => {
80
+ await holoSphere.login(testCredentials.spacename, testCredentials.password);
81
+ expect(holoSphere.currentSpace).toBeDefined();
82
+
83
+ await holoSphere.logout();
84
+ expect(holoSphere.currentSpace).toBeNull();
85
+ });
86
+ });
87
+
88
+ describe('Authenticated Data Operations', () => {
89
+ beforeEach(async () => {
90
+ // Ensure both instances are logged out
91
+ if (holoSphere.currentSpace) {
92
+ await holoSphere.logout();
93
+ }
94
+ if (strictHoloSphere.currentSpace) {
95
+ await strictHoloSphere.logout();
96
+ }
97
+
98
+ // Login with test space to holoSphere
99
+ await holoSphere.login(testCredentials.spacename, testCredentials.password);
100
+
101
+ // Set up schema
102
+ const schema = {
103
+ type: 'object',
104
+ properties: {
105
+ id: { type: 'string' },
106
+ data: { type: 'string' },
107
+ owner: { type: 'string' }
108
+ },
109
+ required: ['id', 'data']
110
+ };
111
+ await holoSphere.setSchema(testLens, schema);
112
+ });
113
+
114
+ test('should store data with owner information', async () => {
115
+ const testData = {
116
+ id: 'secured-data-1',
117
+ data: 'This is secured content'
118
+ };
119
+
120
+ // Store data as authenticated space
121
+ await holoSphere.put(testHolon, testLens, testData);
122
+
123
+ // Retrieve data as authenticated space
124
+ const result = await holoSphere.get(testHolon, testLens, testData.id);
125
+ expect(result).toBeDefined();
126
+ expect(result.data).toBe(testData.data);
127
+ expect(result.owner).toBe(testCredentials.spacename);
128
+ });
129
+
130
+ test('should prevent unauthorized access to data', async () => {
131
+ const testData = {
132
+ id: 'secured-data-2',
133
+ data: 'This is private content'
134
+ };
135
+
136
+ // Store data as authenticated space
137
+ await holoSphere.put(testHolon, testLens, testData);
138
+
139
+ // Try to retrieve data as unauthenticated space
140
+ await strictHoloSphere.logout();
141
+ const result = await strictHoloSphere.get(testHolon, testLens, testData.id);
142
+ expect(result.owner).toBe(testCredentials.spacename);
143
+ expect(result.data).toBe(testData.data);
144
+ expect(result.federation).toBeDefined();
145
+ expect(result.federation.origin).toBe(testCredentials.spacename);
146
+ });
147
+
148
+ test('should prevent unauthorized modification of data', async () => {
149
+ const testData = {
150
+ id: 'secured-data-3',
151
+ data: 'Original content'
152
+ };
153
+
154
+ // Store data as authenticated space
155
+ await holoSphere.put(testHolon, testLens, testData);
156
+
157
+ // Try to modify data as unauthenticated space
158
+ await strictHoloSphere.logout();
159
+ const modifiedData = {
160
+ id: 'secured-data-3',
161
+ data: 'Modified content'
162
+ };
163
+
164
+ await expect(strictHoloSphere.put(testHolon, testLens, modifiedData))
165
+ .rejects.toThrow('Unauthorized to modify this data');
166
+ });
167
+
168
+ test('should prevent unauthorized deletion of data', async () => {
169
+ const testData = {
170
+ id: 'secured-data-4',
171
+ data: 'Content to protect'
172
+ };
173
+
174
+ // Store data as authenticated space
175
+ await holoSphere.put(testHolon, testLens, testData);
176
+
177
+ // Try to delete data as unauthenticated space
178
+ await strictHoloSphere.logout();
179
+ await expect(strictHoloSphere.delete(testHolon, testLens, testData.id))
180
+ .rejects.toThrow('Unauthorized to delete this data');
181
+ });
182
+
183
+ test('should allow data sharing between spaces', async () => {
184
+ // Create another space
185
+ const otherSpace = {
186
+ spacename: 'sharedspace@example.com',
187
+ password: 'SharedPass123!'
188
+ };
189
+ await holoSphere.createSpace(otherSpace.spacename, otherSpace.password);
190
+
191
+ // Login to the shared space
192
+ await strictHoloSphere.login(otherSpace.spacename, otherSpace.password);
193
+
194
+ const testData = {
195
+ id: 'shared-data-1',
196
+ data: 'This is shared content',
197
+ shared: [otherSpace.spacename]
198
+ };
199
+
200
+ // Store data as authenticated space with sharing
201
+ await holoSphere.put(testHolon, testLens, testData);
202
+
203
+ // Retrieve data as shared space
204
+ const result = await strictHoloSphere.get(testHolon, testLens, testData.id);
205
+ expect(result).toBeDefined();
206
+ expect(result.data).toBe(testData.data);
207
+ });
208
+
209
+ afterEach(async () => {
210
+ // Clean up test data
211
+ await holoSphere.deleteAll(testHolon, testLens);
212
+
213
+ // Logout from both instances
214
+ if (holoSphere.currentSpace) {
215
+ await holoSphere.logout();
216
+ }
217
+ if (strictHoloSphere.currentSpace) {
218
+ await strictHoloSphere.logout();
219
+ }
220
+ });
221
+ });
222
+
223
+ describe('Authentication Edge Cases', () => {
224
+ test('should handle expired sessions', async () => {
225
+ await holoSphere.login(testCredentials.spacename, testCredentials.password);
226
+
227
+ // Simulate session expiration
228
+ holoSphere.currentSpace.exp = Date.now() - 1000;
229
+
230
+ // Attempt operation with expired session
231
+ const testData = { id: 'test-expired', data: 'test' };
232
+ await expect(holoSphere.put(testHolon, testLens, testData))
233
+ .rejects.toThrow('Session expired');
234
+ });
235
+
236
+ test('should handle concurrent authentication requests', async () => {
237
+ const promises = Array(5).fill().map(() =>
238
+ holoSphere.login(testCredentials.spacename, testCredentials.password)
239
+ );
240
+
241
+ const results = await Promise.all(promises);
242
+ expect(results.every(result => result === true)).toBeTruthy();
243
+ });
244
+
245
+ test('should handle malformed credentials', async () => {
246
+ await expect(holoSphere.login(null, null))
247
+ .rejects.toThrow('Invalid credentials format');
248
+
249
+ await expect(holoSphere.login('', ''))
250
+ .rejects.toThrow('Invalid credentials format');
251
+
252
+ await expect(holoSphere.login(123, {}))
253
+ .rejects.toThrow('Invalid credentials format');
254
+ });
255
+ });
256
+
257
+ describe('SEA Encryption Edge Cases', () => {
258
+ test('should handle malformed SEA data', async () => {
259
+ const malformedSpace = {
260
+ spacename: 'malformed@example.com',
261
+ password: 'MalformedPass123!'
262
+ };
263
+
264
+ // Clean up any existing malformed space first
265
+ await holoSphere.deleteGlobal('spaces', malformedSpace.spacename);
266
+
267
+ // Wait for cleanup to complete
268
+ await new Promise(resolve => setTimeout(resolve, 2000));
269
+
270
+ // Create space but manipulate the auth data
271
+ await holoSphere.createSpace(malformedSpace.spacename, malformedSpace.password);
272
+
273
+ // Wait for space creation
274
+ await new Promise(resolve => setTimeout(resolve, 2000));
275
+
276
+ // Get and modify the space data
277
+ const spaceData = await holoSphere.getGlobal('spaces', malformedSpace.spacename);
278
+ expect(spaceData).toBeDefined();
279
+
280
+ // Corrupt the auth data
281
+ const corruptedData = {
282
+ ...spaceData,
283
+ auth: { corrupted: 'data' }
284
+ };
285
+ await holoSphere.putGlobal('spaces', corruptedData);
286
+
287
+ // Wait for corruption to be saved
288
+ await new Promise(resolve => setTimeout(resolve, 2000));
289
+
290
+ // Attempt to login should fail gracefully
291
+ await expect(holoSphere.login(malformedSpace.spacename, malformedSpace.password))
292
+ .rejects.toThrow('Authentication failed');
293
+
294
+ // Clean up after test
295
+ await holoSphere.deleteGlobal('spaces', malformedSpace.spacename);
296
+ }, 15000); // Increase timeout for this specific test
297
+
298
+ test('should handle concurrent SEA operations', async () => {
299
+ const promises = Array(3).fill().map(() =>
300
+ holoSphere.login(testCredentials.spacename, testCredentials.password)
301
+ );
302
+
303
+ const results = await Promise.all(promises);
304
+ expect(results.every(result => result === true)).toBeTruthy();
305
+ });
306
+ });
307
+
308
+ afterAll(async () => {
309
+ // Final cleanup
310
+ if (holoSphere.currentSpace) {
311
+ await holoSphere.logout();
312
+ }
313
+ if (strictHoloSphere.currentSpace) {
314
+ await strictHoloSphere.logout();
315
+ }
316
+
317
+ // Clear all test data
318
+ await holoSphere.deleteAll(testHolon, testLens);
319
+
320
+ // Clean up test spaces
321
+ try {
322
+ await holoSphere.deleteGlobal('spaces', testCredentials.spacename);
323
+ await holoSphere.deleteGlobal('spaces', 'newspace@example.com');
324
+ await holoSphere.deleteGlobal('spaces', 'sharedspace@example.com');
325
+ } catch (error) {
326
+ console.log('Cleanup error (can be ignored):', error);
327
+ }
328
+
329
+ // Clean up Gun instances
330
+ if (holoSphere.gun) {
331
+ holoSphere.gun.off();
332
+ }
333
+ if (strictHoloSphere.gun) {
334
+ strictHoloSphere.gun.off();
335
+ }
336
+ });
337
+ });