basic.test.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. const { eq, ok, notOk, deepEq, throwsAsync } = require('../../helpers/assert');
  2. const { makeNetwork, makePeer } = require('../../helpers/setup');
  3. describe('sub-tribes: hierarchy', (t) => {
  4. t('A creates parent + sub, both visible to A', async () => {
  5. const net = makeNetwork();
  6. const A = makePeer(net); A.setActor();
  7. const tm = A.use('tribes');
  8. const p = await tm.createTribe('P', '', null, '', [], false, true, 'strict', null, 'OPEN', '');
  9. const s = await tm.createTribe('S', '', null, '', [], false, true, 'strict', p.key, 'OPEN', '');
  10. const list = await tm.listAll();
  11. eq(list.length, 2);
  12. const sub = list.find(x => x.title === 'S');
  13. eq(sub.parentTribeId, p.key);
  14. });
  15. t('B invited to sub-tribe gets ONLY sub key (no parent leak)', async () => {
  16. const net = makeNetwork();
  17. const A = makePeer(net); const B = makePeer(net);
  18. A.setActor();
  19. const p = await A.use('tribes').createTribe('P', '', null, '', [], false, true, 'strict', null, 'OPEN', '');
  20. const s = await A.use('tribes').createTribe('S', '', null, '', [], false, true, 'strict', p.key, 'OPEN', '');
  21. const code = await A.use('tribes').generateInvite(s.key);
  22. B.setActor();
  23. await B.use('tribes').joinByInvite(code);
  24. eq(B.tribeCrypto.getKey(s.key) ? true : false, true);
  25. eq(B.tribeCrypto.getKey(p.key), null);
  26. });
  27. t('B in sub cannot read parent', async () => {
  28. const net = makeNetwork();
  29. const A = makePeer(net); const B = makePeer(net);
  30. A.setActor();
  31. const p = await A.use('tribes').createTribe('P', 'secret', null, '', [], false, true, 'strict', null, 'OPEN', '');
  32. const s = await A.use('tribes').createTribe('S', '', null, '', [], false, true, 'strict', p.key, 'OPEN', '');
  33. const code = await A.use('tribes').generateInvite(s.key);
  34. B.setActor();
  35. await B.use('tribes').joinByInvite(code);
  36. await throwsAsync(() => B.use('tribes').getTribeById(p.key), 'Tribe not found');
  37. });
  38. t('parent tombstone cascades to sub-tribe', async () => {
  39. const net = makeNetwork();
  40. const A = makePeer(net); A.setActor();
  41. const p = await A.use('tribes').createTribe('P', '', null, '', [], false, true, 'strict', null, 'OPEN', '');
  42. await A.use('tribes').createTribe('S', '', null, '', [], false, true, 'strict', p.key, 'OPEN', '');
  43. eq((await A.use('tribes').listAll()).length, 2);
  44. await A.use('tribes').publishTombstone(p.key);
  45. eq((await A.use('tribes').listAll()).length, 0);
  46. });
  47. t('pruneOrphanKeys removes keyring entries for tombstoned tribe', async () => {
  48. const net = makeNetwork();
  49. const A = makePeer(net); A.setActor();
  50. const r = await A.use('tribes').createTribe('Z', '', null, '', [], false, true, 'strict', null, 'OPEN', '');
  51. ok(A.tribeCrypto.getKey(r.key), 'key present before delete');
  52. await A.use('tribes').publishTombstone(r.key);
  53. const removed = await A.use('tribes').pruneOrphanKeys();
  54. eq(removed, 1);
  55. eq(A.tribeCrypto.getKey(r.key), null, 'key gone after prune');
  56. notOk(A.tribeCrypto.getAllRootIds().includes(r.key), 'rootId no longer in keyring');
  57. });
  58. t('pruneOrphanKeys cascades to sub-tribe keyring entries', async () => {
  59. const net = makeNetwork();
  60. const A = makePeer(net); A.setActor();
  61. const p = await A.use('tribes').createTribe('P', '', null, '', [], false, true, 'strict', null, 'OPEN', '');
  62. const s = await A.use('tribes').createTribe('S', '', null, '', [], false, true, 'strict', p.key, 'OPEN', '');
  63. eq(A.tribeCrypto.getAllRootIds().length, 2, 'two keys before delete');
  64. await A.use('tribes').publishTombstone(p.key);
  65. const removed = await A.use('tribes').pruneOrphanKeys();
  66. eq(removed, 2, 'both parent and sub keys removed');
  67. eq(A.tribeCrypto.getKey(p.key), null);
  68. eq(A.tribeCrypto.getKey(s.key), null);
  69. });
  70. t('pruneOrphanKeys leaves active tribes untouched', async () => {
  71. const net = makeNetwork();
  72. const A = makePeer(net); A.setActor();
  73. const r1 = await A.use('tribes').createTribe('Keep1', '', null, '', [], false, true, 'strict', null, 'OPEN', '');
  74. const r2 = await A.use('tribes').createTribe('Keep2', '', null, '', [], false, true, 'strict', null, 'OPEN', '');
  75. const removed = await A.use('tribes').pruneOrphanKeys();
  76. eq(removed, 0);
  77. ok(A.tribeCrypto.getKey(r1.key));
  78. ok(A.tribeCrypto.getKey(r2.key));
  79. });
  80. t('cycle in parentTribeId does not infinite-loop', async () => {
  81. const net = makeNetwork();
  82. const A = makePeer(net); A.setActor();
  83. const a = await A.use('tribes').createTribe('A', '', null, '', [], false, true, 'strict', null, 'OPEN', '');
  84. const b = await A.use('tribes').createTribe('B', '', null, '', [], false, true, 'strict', a.key, 'OPEN', '');
  85. await A.use('tribes').updateTribeById(a.key, { parentTribeId: b.key });
  86. const status = await A.use('tribes').getEffectiveStatus(b.key);
  87. ok(status);
  88. });
  89. t('three-level nesting: ancestry chain correct', async () => {
  90. const net = makeNetwork();
  91. const A = makePeer(net); A.setActor();
  92. const gp = await A.use('tribes').createTribe('GP', '', null, '', [], false, true, 'strict', null, 'OPEN', '');
  93. const p = await A.use('tribes').createTribe('P', '', null, '', [], false, true, 'strict', gp.key, 'OPEN', '');
  94. const s = await A.use('tribes').createTribe('S', '', null, '', [], false, true, 'strict', p.key, 'OPEN', '');
  95. deepEq(await A.use('tribes').getAncestryChain(s.key), [s.key, p.key, gp.key]);
  96. });
  97. });