holosphere 1.1.2 → 1.1.4

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