Repository: solid/community-server (ts)

Issue:
Using a ResourceStore for internal storage is broken
Using the config feature `storage/key-value/resource-store.json` breaks the server. Reason being that we have a circular dependency:
 * `LockingResourceStore` uses a `GreedyReadWriteLocker`
 * `GreedyReadWriteLocker` uses a `JsonResourceStorage` for storage (when the above config is enabled)
 * `JsonResourceStorage` uses the main `ResourceStore`, which has the `LockingResourceStore` in it as second store.

This makes it impossible to instantiate the server with that config. None of the integration tests use a setup with that storage setup so this remained undetected (woops). The IDP does use that kind of storage but in that case there is no loop since the storage it uses is a different instance than the one used by the locker.

Possible solutions:
 1. Let the `JsonResourceStorage` use the backend resource store (so only the `DataAccessorBasedStore` in default cases)
 2. Set up a custom store stack specifically for the storage that has a new `LockingResourceStore` wrapped around the backend store.
 3. Completely copy the store stack for the storage so it has an identical store stack as normal requests (but a different instance).

Solution 1 is the easiest since it's just using a different identifier in the config. The fact that this bypasses the locker is currently not an issue since the only class using it is the `GreedyReadWriteLocker` which already has its own locks around the requests. To be future proof we probably want at least solution 2, so there are no potential issues when multiple instances are writing to the storage. Solution 3 seems overkill since all the other stores in the store stack are irrelevant for the storage. This might change in the future of course.

Pull request:
fix: Prevent cyclical dependency with locker and storage
Closes #862 

My proposal for a solution (includes some cleanup for the storage configs).

I would use a specific storage for the lockers that only uses the backend. The expectation is then that the lockers handle the locking themselves (which they currently do).

All other classes can then use a storage that still references the full store stack. The only one we currently have is the IDP one.

I also updated one integration config to use the resource store storage so this would be caught by tests using this config.

After #757 (which is how I discovered this) the plan is to update all the default configs we have to use this kind of storage instead of the memory one which is now the default.

Patch:
diff --git a/config/identity/handler/default.json b/config/identity/handler/default.json
index f47063605..dcae01c4e 100644
--- a/config/identity/handler/default.json
+++ b/config/identity/handler/default.json
@@ -3,7 +3,7 @@
   "import": [
     "files-scs:config/identity/handler/adapter-factory/webid.json",
     "files-scs:config/identity/handler/interaction/handler.json",
-    "files-scs:config/identity/handler/key-value/resource-store.json",
+    "files-scs:config/identity/handler/key-value/storage.json",
     "files-scs:config/identity/handler/provider-factory/identity.json"
   ],
   "@graph": [
diff --git a/config/identity/handler/key-value/resource-store.json b/config/identity/handler/key-value/storage.json
similarity index 63%
rename from config/identity/handler/key-value/resource-store.json
rename to config/identity/handler/key-value/storage.json
index 97e4a285a..868f07c29 100644
--- a/config/identity/handler/key-value/resource-store.json
+++ b/config/identity/handler/key-value/storage.json
@@ -1,14 +1,6 @@
 {
   "@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^1.0.0/components/context.jsonld",
   "@graph": [
-    {
-      "comment": "This storage specifically uses the same path as the IDP routing, thereby guaranteeing outside access is impossible.",
-      "@id": "urn:solid-server:default:IdpStorage",
-      "@type": "JsonResourceStorage",
-      "source": { "@id": "urn:solid-server:default:ResourceStore" },
-      "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" },
-      "container": "/idp/data/"
-    },
     {
       "comment": "Stores expiring data. This class has a `finalize` function that needs to be called after stopping the server.",
       "@id": "urn:solid-server:default:ExpiringIdpStorage",
diff --git a/config/storage/key-value/memory.json b/config/storage/key-value/memory.json
index 2ebc55417..2b707b61b 100644
--- a/config/storage/key-value/memory.json
+++ b/config/storage/key-value/memory.json
@@ -2,8 +2,16 @@
   "@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^1.0.0/components/context.jsonld",
   "@graph": [
     {
-      "comment": "Used for internal storage by some classes. This uses a memory based solution.",
-      "@id": "urn:solid-server:default:Storage",
+      "comment": "These storage solutions store their data in memory."
+    },
+    {
+      "comment": "Used for internal storage by the locker.",
+      "@id": "urn:solid-server:default:LockStorage",
+      "@type": "MemoryMapStorage"
+    },
+    {
+      "comment": "Storage used by the IDP component.",
+      "@id": "urn:solid-server:default:IdpStorage",
       "@type": "MemoryMapStorage"
     }
   ]
diff --git a/config/storage/key-value/resource-store.json b/config/storage/key-value/resource-store.json
index 4fb911cf7..3394b2d40 100644
--- a/config/storage/key-value/resource-store.json
+++ b/config/storage/key-value/resource-store.json
@@ -2,12 +2,26 @@
   "@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^1.0.0/components/context.jsonld",
   "@graph": [
     {
-      "comment": "Used for internal storage by some classes. The specified container in the resource store will store internal data.",
-      "@id": "urn:solid-server:default:Storage",
+      "comment": "These storage solutions use the specified container in the ResourceStore to store their data."
+    },
+    {
+      "comment": [
+        "This is the internal storage for the locker, which maintains what resources are in use.",
+        "It writes directly to a low-level store, because higher-level storage typically already uses the locker and would thus cause a loop."
+      ],
+      "@id": "urn:solid-server:default:LockStorage",
+      "@type": "JsonResourceStorage",
+      "source": { "@id": "urn:solid-server:default:ResourceStore_Backend" },
+      "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" },
+      "container": "/locks/"
+    },
+    {
+      "comment": "Storage used by the IDP component.",
+      "@id": "urn:solid-server:default:IdpStorage",
       "@type": "JsonResourceStorage",
       "source": { "@id": "urn:solid-server:default:ResourceStore" },
       "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" },
-      "container": "/storage/"
+      "container": "/idp/data/"
     }
   ]
 }
diff --git a/config/util/resource-locker/memory.json b/config/util/resource-locker/memory.json
index 3175f50f4..886f30126 100644
--- a/config/util/resource-locker/memory.json
+++ b/config/util/resource-locker/memory.json
@@ -10,7 +10,7 @@
         "locker": {
           "@type": "SingleThreadedResourceLocker"
         },
-        "storage": { "@id": "urn:solid-server:default:Storage" },
+        "storage": { "@id": "urn:solid-server:default:LockStorage" },
         "suffixes_count": "count",
         "suffixes_read": "read",
         "suffixes_write": "write"
diff --git a/config/util/resource-locker/redis.json b/config/util/resource-locker/redis.json
index 54cf945f4..b15df4935 100644
--- a/config/util/resource-locker/redis.json
+++ b/config/util/resource-locker/redis.json
@@ -12,7 +12,7 @@
           "@type": "RedisResourceLocker",
           "redisClients": [ "6379" ]
         },
-        "storage": { "@id": "urn:solid-server:default:Storage" },
+        "storage": { "@id": "urn:solid-server:default:LockStorage" },
         "suffixes_count": "count",
         "suffixes_read": "read",
         "suffixes_write": "write"


Test patch:
diff --git a/test/integration/config/server-memory.json b/test/integration/config/server-memory.json
index 122c004c6..3bc5307b6 100644
--- a/test/integration/config/server-memory.json
+++ b/test/integration/config/server-memory.json
@@ -18,7 +18,7 @@
     "files-scs:config/ldp/metadata-writer/default.json",
     "files-scs:config/ldp/permissions/acl.json",
     "files-scs:config/storage/backend/memory.json",
-    "files-scs:config/storage/key-value/memory.json",
+    "files-scs:config/storage/key-value/resource-store.json",
     "files-scs:config/storage/middleware/default.json",
     "files-scs:config/util/auxiliary/acl.json",
     "files-scs:config/util/identifiers/suffix.json",