about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVika <vika@fireburn.ru>2021-09-28 01:57:16 +0300
committerVika <vika@fireburn.ru>2021-09-28 01:57:16 +0300
commit5545edcca7d8d67ef156c924351fd9cb912c160b (patch)
tree8b00b6df6a03530b9898913ede6636284d3f3dcd
parenta8a38e54cd6d7c771c1ceecd4d8fcd86c33d3f1e (diff)
Modified the module to use BACKEND_URI
-rw-r--r--flake.nix62
-rw-r--r--onboarding.json33
-rw-r--r--src/database/file/mod.rs2
-rw-r--r--src/frontend/mod.rs13
4 files changed, 75 insertions, 35 deletions
diff --git a/flake.nix b/flake.nix
index c2d3b30..c879a7f 100644
--- a/flake.nix
+++ b/flake.nix
@@ -62,11 +62,22 @@
             example = "info";
             description = "Specify the server verbosity level. Uses RUST_LOG environment variable internally.";
           };
-          redisUri = mkOption {
-            type = types.nullOr types.str;
-            default = null;
-            example = "redis://192.168.1.200:6379/";
-            description = "Set the Redis instance used as backing storage. If null, Redis will be configured on localhost. Use services.redis to change parameters.";
+          backendUri = mkOption {
+            type = types.str;
+            default = "file:///var/lib/kittybox/data";
+            example = "redis://192.168.1.200:6379";
+            description = ''
+              Set the backend used for storing data. Available backends are:
+               - file:// - static folder backend (recommended)
+               - redis:// - Redis backend
+
+              Make sure that if you are using the file backend, the state
+              directory is accessible by Kittybox. By default, the unit config
+              uses DynamicUser=true, which prevents the unit from accessing
+              data outside of its directory. It is recommended to use a
+              bind-mount to /var/lib/private/kittybox if you require the state
+              directory to reside elsewhere.
+            '';
           };
           tokenEndpoint = mkOption {
             type = types.str;
@@ -124,7 +135,7 @@
 
           restartTriggers = [
             cfg.package
-            cfg.redisUri cfg.tokenEndpoint
+            cfg.backendUri cfg.tokenEndpoint
             cfg.authorizationEndpoint
             cfg.internalTokenFile
             cfg.bind cfg.port
@@ -137,7 +148,8 @@
             MEDIA_ENDPOINT = cfg.mediaEndpoint;
             MICROSUB_ENDPOINT = cfg.microsubServer;
             WEBMENTION_ENDPOINT = cfg.webmentionEndpoint;
-            REDIS_URI = if (cfg.redisUri == null) then "redis://127.0.0.1:6379/" else cfg.redisUri;
+            #REDIS_URI = if (cfg.redisUri == null) then "redis://127.0.0.1:6379/" else cfg.redisUri;
+            BACKEND_URI = cfg.backendUri;
             RUST_LOG = "${cfg.logLevel}";
           };
 
@@ -152,11 +164,9 @@
 
           serviceConfig = {
             DynamicUser = true;
+            StateDirectory = "kittybox";
           };
         };
-        services.redis = lib.mkIf (cfg.redisUri == null) {
-          enable = true;
-        };
       };
     };
   } // forAllSystems (system: let
@@ -195,7 +205,7 @@
     defaultPackage = self.packages.${system}.kittybox;
 
     checks = {
-      nixos-test = pkgs.nixosTest ({ lib }: {
+      nixos-test = (pkgs.nixosTest ({ lib }: {
         name = "nixos-kittybox";
 
         nodes = {
@@ -209,6 +219,7 @@
               #       make an e2e test for common workflows (e.g. making a post)
               tokenEndpoint = "https://example.com";
               authorizationEndpoint = "https://example.com";
+              logLevel = "debug";
             };
 
             environment.systemPackages = with pkgs; [
@@ -218,38 +229,21 @@
         };
 
         testScript = ''
-          import json
-
           kittybox.start()
           kittybox.wait_for_unit("default.target")
           with subtest("Verify that Kittybox started correctly..."):
               kittybox.succeed("curl --silent http://localhost:8080/micropub")
 
           with subtest("Onboarding should correctly work..."):
-              onboarding_json = {
-                  "user": {
-                      "type": ["h-card"],
-                      "properties": {
-                          "name": ["Vika"],
-                          "pronoun": ["she/her"],
-                          "url": ["https://twitter.com/VikaNezrimaya"],
-                          "note": ["Just a simple girl. Do I even exist or am I a vestige of the past long gone?"]
-                      }
-                    },
-                    "first_post": {
-                        "type": ["h-entry"],
-                        "properties": {
-                            "content": ["Hello!"]
-                        }
-                    },
-                    "blog_name": "Test Hideout",
-                    "feeds": []
-              }
-              kittybox.succeed("echo '{}' | curl --silent http://localhost:8080/ -d@- -H 'Content-Type: application/json'".format(json.dumps(onboarding_json).replace("'", "'\''$")))
+              # Here we rely on a fact that the /nix/store is shared between the host and the VM
+              kittybox.succeed("curl -vvv http://localhost:8080/ -d${./onboarding.json}")
               # Testing for a known string is the easiest way to determine that the onboarding worked
               kittybox.succeed("curl --silent http://localhost:8080/ | grep 'vestige of the past long gone'")
         '';
-      });
+      }))
+      # This test is broken! For some reason the file locks don't seem to work and hang the executable instead.
+      #.overrideAttrs(o: { meta.broken = true; })
+      ;
     };
 
     devShell = pkgs.mkShell {
diff --git a/onboarding.json b/onboarding.json
new file mode 100644
index 0000000..04acbf8
--- /dev/null
+++ b/onboarding.json
@@ -0,0 +1,33 @@
+{
+  "user": {
+    "type": [
+      "h-card"
+    ],
+    "properties": {
+      "name": [
+        "Vika"
+      ],
+      "pronoun": [
+        "she/her"
+      ],
+      "url": [
+        "https://twitter.com/VikaNezrimaya"
+      ],
+      "note": [
+        "Just a simple girl. Do I even exist or am I a vestige of the past long gone?"
+      ]
+    }
+  },
+  "first_post": {
+    "type": [
+      "h-entry"
+    ],
+    "properties": {
+      "content": [
+        "Hello!"
+      ]
+    }
+  },
+  "blog_name": "Test Hideout",
+  "feeds": []
+}
diff --git a/src/database/file/mod.rs b/src/database/file/mod.rs
index acbb44b..f58317e 100644
--- a/src/database/file/mod.rs
+++ b/src/database/file/mod.rs
@@ -483,8 +483,10 @@ impl Storage for FileStorage {
             .create(true)
             .open(&path).await?;
         let mut lock = get_lockable_file(file).await;
+        log::debug!("Created a lock. Locking for writing...");
         let mut guard = lock.write()?;
 
+        log::debug!("Locked. Writing.");
         let mut content = String::new();
         guard.read_to_string(&mut content).await?;
         let mut settings: HashMap<String, String> = if content.len() == 0 {
diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs
index 37420ac..890879c 100644
--- a/src/frontend/mod.rs
+++ b/src/frontend/mod.rs
@@ -120,6 +120,8 @@ struct OnboardingData {
 pub async fn onboarding_receiver<S: Storage>(mut req: Request<ApplicationState<S>>) -> Result {
     use serde_json::json;
 
+    log::debug!("Entering onboarding receiver...");
+
     // This cannot error out as the URL must be valid. Or there is something horribly wrong
     // and we shouldn't serve this request anyway.
     <dyn AsMut<tide::http::Request>>::as_mut(&mut req)
@@ -127,7 +129,9 @@ pub async fn onboarding_receiver<S: Storage>(mut req: Request<ApplicationState<S
         .set_scheme("https")
         .unwrap();
 
+    log::debug!("Parsing the body...");
     let body = req.body_json::<OnboardingData>().await?;
+    log::debug!("Body parsed!");
     let backend = &req.state().storage;
 
     #[cfg(any(not(debug_assertions), test))]
@@ -135,6 +139,8 @@ pub async fn onboarding_receiver<S: Storage>(mut req: Request<ApplicationState<S
     #[cfg(all(debug_assertions, not(test)))]
     let me = url::Url::parse("https://localhost:8080/").unwrap();
 
+    log::debug!("me value: {:?}", me);
+
     if get_post_from_database(backend, me.as_str(), None, &None)
         .await
         .is_ok()
@@ -149,6 +155,7 @@ pub async fn onboarding_receiver<S: Storage>(mut req: Request<ApplicationState<S
 
     let user = crate::indieauth::User::new(me.as_str(), "https://kittybox.fireburn.ru/", "create");
 
+    log::debug!("Setting the site name to {}", &body.blog_name);
     backend
         .set_setting("site_name", user.me.as_str(), &body.blog_name)
         .await?;
@@ -173,9 +180,13 @@ pub async fn onboarding_receiver<S: Storage>(mut req: Request<ApplicationState<S
     // post function is just to ensure that the posts will be syndicated
     // and inserted into proper feeds. Here, we don't have a need for this,
     // since the h-card is DIRECTLY accessible via its own URL.
+    log::debug!("Saving the h-card...");
     backend.put_post(&hcard, me.as_str()).await?;
 
+    log::debug!("Creating feeds...");
     for feed in body.feeds {
+        if &feed.name == "" || &feed.slug == "" { continue };
+        log::debug!("Creating feed {} with slug {}", &feed.name, &feed.slug);
         let (_, feed) = crate::micropub::normalize_mf2(
             json!({
                 "type": ["h-feed"],
@@ -186,7 +197,7 @@ pub async fn onboarding_receiver<S: Storage>(mut req: Request<ApplicationState<S
 
         backend.put_post(&feed, me.as_str()).await?;
     }
-
+    log::debug!("Saving the h-entry...");
     // This basically puts the h-entry post through the normal creation process.
     // We need to insert it into feeds and optionally send a notification to everywhere.
     req.set_ext(user);