wiki-plugin-shoppe 0.0.30 → 0.0.31

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 (2) hide show
  1. package/package.json +1 -1
  2. package/server/server.js +43 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wiki-plugin-shoppe",
3
- "version": "0.0.30",
3
+ "version": "0.0.31",
4
4
  "description": "Multi-tenant digital goods shoppe for federated wiki, powered by Sanora",
5
5
  "keywords": [
6
6
  "wiki",
package/server/server.js CHANGED
@@ -477,6 +477,44 @@ function getMimeType(filename) {
477
477
  })[ext] || 'application/octet-stream';
478
478
  }
479
479
 
480
+ // Ensure the tenant's Sanora user exists (Redis may have been wiped).
481
+ // If the user is found by pubKey but has a different UUID (new registration),
482
+ // updates tenants.json so all subsequent product calls use the correct UUID.
483
+ async function sanoraEnsureUser(tenant) {
484
+ const { keys } = tenant;
485
+ const timestamp = Date.now().toString();
486
+ const message = timestamp + keys.pubKey;
487
+ sessionless.getKeys = () => keys;
488
+ const signature = await sessionless.sign(message);
489
+
490
+ const resp = await fetch(`${getSanoraUrl()}/user/create`, {
491
+ method: 'PUT',
492
+ headers: { 'Content-Type': 'application/json' },
493
+ body: JSON.stringify({ timestamp, pubKey: keys.pubKey, signature }),
494
+ timeout: 15000
495
+ });
496
+
497
+ if (!resp.ok) {
498
+ const text = await resp.text().catch(() => '');
499
+ throw new Error(`Sanora user ensure failed (${resp.status}): ${text.slice(0, 200)}`);
500
+ }
501
+
502
+ const sanoraUser = await resp.json();
503
+ if (sanoraUser.error) throw new Error(`Sanora user ensure: ${sanoraUser.error}`);
504
+
505
+ if (sanoraUser.uuid !== tenant.uuid) {
506
+ console.log(`[shoppe] Sanora UUID changed ${tenant.uuid} → ${sanoraUser.uuid} (Redis was reset). Updating tenants.json.`);
507
+ const tenants = loadTenants();
508
+ const oldUuid = tenant.uuid;
509
+ delete tenants[oldUuid];
510
+ tenant.uuid = sanoraUser.uuid;
511
+ tenants[sanoraUser.uuid] = tenant;
512
+ saveTenants(tenants);
513
+ }
514
+
515
+ return tenant; // tenant.uuid is now correct
516
+ }
517
+
480
518
  async function sanoraCreateProduct(tenant, title, category, description, price, shipping, tags) {
481
519
  const { uuid, keys } = tenant;
482
520
  const timestamp = Date.now().toString();
@@ -717,7 +755,7 @@ async function processArchive(zipPath) {
717
755
  throw new Error('manifest.json must contain uuid and emojicode');
718
756
  }
719
757
 
720
- const tenant = getTenantByIdentifier(manifest.uuid);
758
+ let tenant = getTenantByIdentifier(manifest.uuid);
721
759
  if (!tenant) throw new Error(`Unknown UUID: ${manifest.uuid}`);
722
760
  if (tenant.emojicode !== manifest.emojicode) {
723
761
  throw new Error('emojicode does not match registered tenant');
@@ -741,6 +779,10 @@ async function processArchive(zipPath) {
741
779
  Object.assign(tenant, tenantUpdates);
742
780
  }
743
781
 
782
+ // Ensure the Sanora user exists before uploading any products.
783
+ // If Redis was wiped, this re-creates the user and updates tenant.uuid.
784
+ tenant = await sanoraEnsureUser(tenant);
785
+
744
786
  const results = { books: [], music: [], posts: [], albums: [], products: [], videos: [], appointments: [], subscriptions: [], warnings: [] };
745
787
 
746
788
  function readInfo(entryPath) {