From 18aac0010cd8aae626425057c18f828b4643e3c1 Mon Sep 17 00:00:00 2001 From: Sveske_Juice Date: Sun, 6 Apr 2025 22:37:14 +0200 Subject: [PATCH] Insert users into sqlite database --- flake.nix | 32 +++++++++++------- modules/config.nix | 69 +++++++++++++++++++++++++++------------ modules/options/users.nix | 32 +++++++++++++----- tests/create_users.nix | 8 +++-- tests/defaultdb.nix | 1 - 5 files changed, 98 insertions(+), 44 deletions(-) diff --git a/flake.nix b/flake.nix index e805cc3..06e3e24 100644 --- a/flake.nix +++ b/flake.nix @@ -19,7 +19,9 @@ tests = system: builtins.listToAttrs (builtins.map (x: let - test = import (./tests + "/${x}") {pkgs = import nixpkgs {inherit system;};}; + test = import (./tests + "/${x}") { + pkgs = import nixpkgs {inherit system;}; + }; in { name = test.name; value = test.test; @@ -38,24 +40,30 @@ in pkgs.alejandra ); + nixosModules = rec { declarative-jellyfin = import ./modules; default = declarative-jellyfin; }; - packages = forAllSystems (system: let - pkgs = import nixpkgs {inherit system;}; - in {genhash = import ./modules/pbkdf2-sha512.nix {inherit pkgs;};}); - # Run all tests for all systems hydraJobs = forAllSystems tests; checks = forAllSystems tests; - devShell.x86_64-linux = let - pkgs = import nixpkgs {system = "x86_64-linux";}; - in - pkgs.mkShell { - buildInputs = with pkgs; [bear gcc nettle]; - nativeBuildInputs = [pkgs.nettle]; - }; + + packages = forAllSystems ( + system: let + pkgs = import nixpkgs {inherit system;}; + in {genhash = import ./modules/pbkdf2-sha512.nix {inherit pkgs;};} + ); + + devShell = forAllSystems ( + system: let + pkgs = import nixpkgs {inherit system;}; + in + pkgs.mkShell { + buildInputs = with pkgs; [bear gcc nettle]; + nativeBuildInputs = [pkgs.nettle]; + } + ); }; } diff --git a/modules/config.nix b/modules/config.nix index 2f9e4ab..c88d441 100644 --- a/modules/config.nix +++ b/modules/config.nix @@ -2,10 +2,12 @@ config, lib, pkgs, + self, ... }: with lib; let cfg = config.services.declarative-jellyfin; + genhash = import ./pbkdf2-sha512.nix {inherit pkgs;}; toXml' = (import ../lib {nixpkgs = pkgs;}).toXMLGeneric; isStrList = x: all (x: isString x) x; prepass = x: @@ -91,20 +93,40 @@ in { defaultDB = ./default.db; sq = "${pkgs.sqlite}/bin/sqlite3 \"${path}/${dbname}\" --"; path = "/var/lib/jellyfin/data"; + options = lib.attrsets.mapAttrsToList (key: value: "${key}") ( + builtins.removeAttrs ( + (import ./options/users.nix {inherit lib;}).options.services.declarative-jellyfin.Users.type.getSubOptions [] + ) + ["HashedPasswordFile" "_module"] + ); + + subtitleModes = { + Default = 0; + Always = 1; + OnlyForce = 2; + None = 3; + Smart = 4; + }; genUser = index: user: let - values = + values = builtins.removeAttrs ( builtins.mapAttrs - (name: value: - if (isBool value) - then - if value - then "1" - else "0" - else if (isNull value) - then "NULL" - else value) - (user + ( + name: value: + if (isBool value) # bool -> 1 or 0 + then + if value + then "1" + else "0" + else if (isNull value) # null -> NULL + then "NULL" + else if (name == "SubtitleMode") # SubtitleMode -> 0 | 1 | 2 | 3 | 4 + then subtitleModes.${value} + else if (isString value) + then "'${value}'" + else value + ) ( + user // { Id = if !(isNull user.Id) @@ -117,22 +139,24 @@ in { Password = if !(isNull user.HashedPasswordFile) then "$(${pkgs.coreutils}/bin/cat \"${user.HashedPasswordFile}\")" - else "$(${self.packages.${pkgs.system}.genhash}/bin/genhash -k \"${user.Password}\" -i 210000 -l 128 -u)"; - }); + else "$(${genhash}/bin/genhash -k \"${user.Password}\" -i 210000 -l 128 -u)"; + } + ) + ) ["HashedPasswordFile"]; in /* bash */ '' if [ -n $(${sq} "SELECT 1 FROM Users WHERE Username = '${user.Username}'") ]; then + echo "User doesn't exist. creaing new: ${user.Username}" >> /var/log/log.txt # Create user - ${sq} "INSERT INTO Users (${concatStringsSep "," - ( - builtins.filter (x: x != "HashedPasswordFile") - (lib.attrsets.mapAttrsToList (name: value: "${name}") - ((import ./options/users.nix {inherit lib;}).options.services.declarative-jellyfin.Users.type.getSubOptions [])) - )}) \\ - VALUES(${concatStringsSep "," (map toString (builtins.attrValues values))})" + sql=" + INSERT INTO Users (${concatStringsSep "," options}) VALUES(${concatStringsSep "," (map toString (builtins.attrValues values))})" + + echo "SQL COMMAND: $sql" >> /var/log/log.txt + res=$(${sq} "$sql") + echo "OUT: $res" >> /var/log/log.txt fi ''; in @@ -140,9 +164,13 @@ in { bash */ '' + mkdir -p /var/log + file /var/log/log.txt + mkdir -p ${path} # Make sure there is a database if [ ! -e "${path}/${dbname}" ]; then + echo "No DB found. Copying default..." >> /var/log/log.txt cp ${defaultDB} "${path}/${dbname}" chmod 770 "${path}/${dbname}" fi @@ -151,6 +179,7 @@ in { if [ -z "$maxIndex" ]; then maxIndex="1" fi + echo "Max index: $maxIndex" >> /var/log/log.txt ${ concatStringsSep "\n" diff --git a/modules/options/users.nix b/modules/options/users.nix index 04b6b01..6be56b8 100644 --- a/modules/options/users.nix +++ b/modules/options/users.nix @@ -93,7 +93,7 @@ with lib; { default = ""; }; HashedPasswordFile = mkOption { - type = with types; either path str; + type = types.nullOr types.path; description = '' A path to a pbkdf2-sha512 hash in this format [PHC string](https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md). @@ -110,7 +110,7 @@ with lib; { ``` ''; - default = ""; + default = null; example = '' # the format is: $[$=(,=)*][$[$]] $PBKDF2-SHA512$iterations=210000$D12C02D1DD15949D867BCA9971BE9987$67E75CDCD14E7F6FDDF96BAACBE9E84E5197FB9FE454FB039F5CD773D7DF558B57DC81DB42B6F7CF0E6B8207A771E5C0EE0DBFD91CE5BAF804FE53F70E61CD2E @@ -172,14 +172,28 @@ with lib; { type = types.str; default = "F007D354"; }; - }; + InvalidLoginAttemptCount = mkOption { + type = types.int; + default = 0; + }; + MustUpdatePassword = mkOption { + type = types.int; + default = 0; + }; + RowVersion = mkOption { + type = types.int; + default = 0; + }; - # Omitted database columns: - # InvalidLoginAttemptCount - # LastActivityDate - # LastLoginDate - # MustUpdatePassword - # RowVersion + LastActivityDate = mkOption { + type = with types; nullOr str; + default = null; + }; + LastLoginDate = mkOption { + type = with types; nullOr str; + default = null; + }; + }; })); }; } diff --git a/tests/create_users.nix b/tests/create_users.nix index f5d9ba0..9336f72 100644 --- a/tests/create_users.nix +++ b/tests/create_users.nix @@ -1,5 +1,5 @@ {pkgs ? import {}, ...}: let - name = "minimal"; + name = "createusers"; in { inherit name; test = pkgs.nixosTest { @@ -40,9 +40,13 @@ in { '' machine.start() machine.wait_for_unit("multi-user.target"); + output = machine.succeed("cat /var/log/log.txt") + print("Log: " + output) + print(machine.succeed("cat /var/lib/jellyfin/data/jellyfin.db")) machine.succeed("file /var/lib/jellyfin/data/jellyfin.db") users = machine.succeed("sqlite3 /var/lib/jellyfin/data/jellyfin.db -- \"SELECT * FROM Users\"") - print(users) + print("Users: " + users) + if machine.succeed("sqlite3 /var/lib/jellyfin/data/jellyfin.db -- \"SELECT * FROM Users WHERE Username = 'admin'\"") == "": assert False, "User not in db" ''; diff --git a/tests/defaultdb.nix b/tests/defaultdb.nix index 6f80497..1eb7b34 100644 --- a/tests/defaultdb.nix +++ b/tests/defaultdb.nix @@ -33,7 +33,6 @@ in { machine.systemctl("stop jellyfin.service") machine.wait_until_fails("pgrep jellyfin") machine.copy_from_vm("/var/lib/jellyfin/data/jellyfin.db", "jellyfin.db") - assert False ''; }; }