Insert users into sqlite database
All checks were successful
Run tests / run_tests (push) Successful in 1m32s

This commit is contained in:
Sveske_Juice 2025-04-06 22:37:14 +02:00
parent df0ff3f095
commit 18aac0010c
5 changed files with 98 additions and 44 deletions

View file

@ -19,7 +19,9 @@
tests = system: tests = system:
builtins.listToAttrs (builtins.map builtins.listToAttrs (builtins.map
(x: let (x: let
test = import (./tests + "/${x}") {pkgs = import nixpkgs {inherit system;};}; test = import (./tests + "/${x}") {
pkgs = import nixpkgs {inherit system;};
};
in { in {
name = test.name; name = test.name;
value = test.test; value = test.test;
@ -38,24 +40,30 @@
in in
pkgs.alejandra pkgs.alejandra
); );
nixosModules = rec { nixosModules = rec {
declarative-jellyfin = import ./modules; declarative-jellyfin = import ./modules;
default = declarative-jellyfin; 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 # Run all tests for all systems
hydraJobs = forAllSystems tests; hydraJobs = forAllSystems tests;
checks = forAllSystems tests; checks = forAllSystems tests;
devShell.x86_64-linux = let
pkgs = import nixpkgs {system = "x86_64-linux";}; packages = forAllSystems (
in system: let
pkgs.mkShell { pkgs = import nixpkgs {inherit system;};
buildInputs = with pkgs; [bear gcc nettle]; in {genhash = import ./modules/pbkdf2-sha512.nix {inherit pkgs;};}
nativeBuildInputs = [pkgs.nettle]; );
};
devShell = forAllSystems (
system: let
pkgs = import nixpkgs {inherit system;};
in
pkgs.mkShell {
buildInputs = with pkgs; [bear gcc nettle];
nativeBuildInputs = [pkgs.nettle];
}
);
}; };
} }

View file

@ -2,10 +2,12 @@
config, config,
lib, lib,
pkgs, pkgs,
self,
... ...
}: }:
with lib; let with lib; let
cfg = config.services.declarative-jellyfin; cfg = config.services.declarative-jellyfin;
genhash = import ./pbkdf2-sha512.nix {inherit pkgs;};
toXml' = (import ../lib {nixpkgs = pkgs;}).toXMLGeneric; toXml' = (import ../lib {nixpkgs = pkgs;}).toXMLGeneric;
isStrList = x: all (x: isString x) x; isStrList = x: all (x: isString x) x;
prepass = x: prepass = x:
@ -91,20 +93,40 @@ in {
defaultDB = ./default.db; defaultDB = ./default.db;
sq = "${pkgs.sqlite}/bin/sqlite3 \"${path}/${dbname}\" --"; sq = "${pkgs.sqlite}/bin/sqlite3 \"${path}/${dbname}\" --";
path = "/var/lib/jellyfin/data"; 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 genUser = index: user: let
values = values = builtins.removeAttrs (
builtins.mapAttrs builtins.mapAttrs
(name: value: (
if (isBool value) name: value:
then if (isBool value) # bool -> 1 or 0
if value then
then "1" if value
else "0" then "1"
else if (isNull value) else "0"
then "NULL" else if (isNull value) # null -> NULL
else value) then "NULL"
(user else if (name == "SubtitleMode") # SubtitleMode -> 0 | 1 | 2 | 3 | 4
then subtitleModes.${value}
else if (isString value)
then "'${value}'"
else value
) (
user
// { // {
Id = Id =
if !(isNull user.Id) if !(isNull user.Id)
@ -117,22 +139,24 @@ in {
Password = Password =
if !(isNull user.HashedPasswordFile) if !(isNull user.HashedPasswordFile)
then "$(${pkgs.coreutils}/bin/cat \"${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 in
/* /*
bash bash
*/ */
'' ''
if [ -n $(${sq} "SELECT 1 FROM Users WHERE Username = '${user.Username}'") ]; then 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 # Create user
${sq} "INSERT INTO Users (${concatStringsSep "," sql="
( INSERT INTO Users (${concatStringsSep "," options}) VALUES(${concatStringsSep "," (map toString (builtins.attrValues values))})"
builtins.filter (x: x != "HashedPasswordFile")
(lib.attrsets.mapAttrsToList (name: value: "${name}") echo "SQL COMMAND: $sql" >> /var/log/log.txt
((import ./options/users.nix {inherit lib;}).options.services.declarative-jellyfin.Users.type.getSubOptions [])) res=$(${sq} "$sql")
)}) \\ echo "OUT: $res" >> /var/log/log.txt
VALUES(${concatStringsSep "," (map toString (builtins.attrValues values))})"
fi fi
''; '';
in in
@ -140,9 +164,13 @@ in {
bash bash
*/ */
'' ''
mkdir -p /var/log
file /var/log/log.txt
mkdir -p ${path} mkdir -p ${path}
# Make sure there is a database # Make sure there is a database
if [ ! -e "${path}/${dbname}" ]; then if [ ! -e "${path}/${dbname}" ]; then
echo "No DB found. Copying default..." >> /var/log/log.txt
cp ${defaultDB} "${path}/${dbname}" cp ${defaultDB} "${path}/${dbname}"
chmod 770 "${path}/${dbname}" chmod 770 "${path}/${dbname}"
fi fi
@ -151,6 +179,7 @@ in {
if [ -z "$maxIndex" ]; then if [ -z "$maxIndex" ]; then
maxIndex="1" maxIndex="1"
fi fi
echo "Max index: $maxIndex" >> /var/log/log.txt
${ ${
concatStringsSep "\n" concatStringsSep "\n"

View file

@ -93,7 +93,7 @@ with lib; {
default = ""; default = "";
}; };
HashedPasswordFile = mkOption { HashedPasswordFile = mkOption {
type = with types; either path str; type = types.nullOr types.path;
description = '' description = ''
A path to a pbkdf2-sha512 hash 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). 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 = '' example = ''
# the format is: $<id>[$<param>=<value>(,<param>=<value>)*][$<salt>[$<hash>]] # the format is: $<id>[$<param>=<value>(,<param>=<value>)*][$<salt>[$<hash>]]
$PBKDF2-SHA512$iterations=210000$D12C02D1DD15949D867BCA9971BE9987$67E75CDCD14E7F6FDDF96BAACBE9E84E5197FB9FE454FB039F5CD773D7DF558B57DC81DB42B6F7CF0E6B8207A771E5C0EE0DBFD91CE5BAF804FE53F70E61CD2E $PBKDF2-SHA512$iterations=210000$D12C02D1DD15949D867BCA9971BE9987$67E75CDCD14E7F6FDDF96BAACBE9E84E5197FB9FE454FB039F5CD773D7DF558B57DC81DB42B6F7CF0E6B8207A771E5C0EE0DBFD91CE5BAF804FE53F70E61CD2E
@ -172,14 +172,28 @@ with lib; {
type = types.str; type = types.str;
default = "F007D354"; 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: LastActivityDate = mkOption {
# InvalidLoginAttemptCount type = with types; nullOr str;
# LastActivityDate default = null;
# LastLoginDate };
# MustUpdatePassword LastLoginDate = mkOption {
# RowVersion type = with types; nullOr str;
default = null;
};
};
})); }));
}; };
} }

View file

@ -1,5 +1,5 @@
{pkgs ? import <nixpkgs> {}, ...}: let {pkgs ? import <nixpkgs> {}, ...}: let
name = "minimal"; name = "createusers";
in { in {
inherit name; inherit name;
test = pkgs.nixosTest { test = pkgs.nixosTest {
@ -40,9 +40,13 @@ in {
'' ''
machine.start() machine.start()
machine.wait_for_unit("multi-user.target"); 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") machine.succeed("file /var/lib/jellyfin/data/jellyfin.db")
users = machine.succeed("sqlite3 /var/lib/jellyfin/data/jellyfin.db -- \"SELECT * FROM Users\"") 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'\"") == "": if machine.succeed("sqlite3 /var/lib/jellyfin/data/jellyfin.db -- \"SELECT * FROM Users WHERE Username = 'admin'\"") == "":
assert False, "User not in db" assert False, "User not in db"
''; '';

View file

@ -33,7 +33,6 @@ in {
machine.systemctl("stop jellyfin.service") machine.systemctl("stop jellyfin.service")
machine.wait_until_fails("pgrep jellyfin") machine.wait_until_fails("pgrep jellyfin")
machine.copy_from_vm("/var/lib/jellyfin/data/jellyfin.db", "jellyfin.db") machine.copy_from_vm("/var/lib/jellyfin/data/jellyfin.db", "jellyfin.db")
assert False
''; '';
}; };
} }