@@ -876,6 +876,7 @@
|
||||
./services/misc/ihaskell.nix
|
||||
./services/misc/iio-niri.nix
|
||||
./services/misc/input-remapper.nix
|
||||
./services/misc/inventree.nix
|
||||
./services/misc/invidious-router.nix
|
||||
./services/misc/irkerd.nix
|
||||
./services/misc/jackett.nix
|
||||
|
||||
@@ -0,0 +1,457 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.inventree;
|
||||
pkg = cfg.package;
|
||||
|
||||
mysqlLocal = cfg.database.createLocally && cfg.database.dbtype == "mysql";
|
||||
pgsqlLocal = cfg.database.createLocally && cfg.database.dbtype == "postgresql";
|
||||
|
||||
manage = pkgs.writeShellScriptBin "inventree-manage" ''
|
||||
set -a
|
||||
${lib.toShellVars cfg.settings}
|
||||
${lib.optionalString (
|
||||
cfg.database.passwordFile != null
|
||||
) ''INVENTREE_DB_PASSWORD="$(<"${cfg.database.passwordFile}")"''}
|
||||
set +a
|
||||
|
||||
pushd "${cfg.dataDir}"
|
||||
sudo=exec
|
||||
if [[ "$USER" != ${cfg.user} ]]; then
|
||||
${
|
||||
if config.security.sudo.enable then
|
||||
"sudo='exec ${config.security.wrapperDir}/sudo -u ${cfg.user} -E'"
|
||||
else
|
||||
">&2 echo 'Aborting, inventree-manage must be run as user `${cfg.user}`!'; exit 2"
|
||||
}
|
||||
fi
|
||||
$sudo ${cfg.package}/bin/inventree "$@"
|
||||
popd
|
||||
'';
|
||||
|
||||
in
|
||||
{
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
kurogeek
|
||||
];
|
||||
|
||||
options.services.inventree = with lib; {
|
||||
enable = lib.mkEnableOption "inventree";
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/inventree";
|
||||
description = "Inventree's data storage path. Will be `/var/lib/inventree` by default.";
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
description = "Which package to use for the InvenTree instance.";
|
||||
default = pkgs.inventree;
|
||||
defaultText = literalExpression "pkgs.inventree";
|
||||
};
|
||||
|
||||
adminPasswordFile = mkOption {
|
||||
type = types.nullOr lib.types.path;
|
||||
default = null;
|
||||
example = "/run/keys/inventree-password";
|
||||
description = "Path to a file containing admin password";
|
||||
};
|
||||
|
||||
secretKeyFile = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.dataDir}/secret_key.txt";
|
||||
example = "/run/keys/inventree-secret-key";
|
||||
description = ''
|
||||
Path to a file containing the secret key
|
||||
'';
|
||||
};
|
||||
|
||||
database = {
|
||||
dbtype = mkOption {
|
||||
type = lib.types.nullOr (
|
||||
lib.types.enum [
|
||||
"postgresql"
|
||||
"mysql"
|
||||
]
|
||||
);
|
||||
default = "postgresql";
|
||||
description = "Database type.";
|
||||
};
|
||||
dbhost = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default =
|
||||
if pgsqlLocal then
|
||||
"/run/postgresql"
|
||||
else if mysqlLocal then
|
||||
"/run/mysqld/mysqld.sock"
|
||||
else
|
||||
"localhost";
|
||||
defaultText = "localhost";
|
||||
example = "localhost";
|
||||
description = ''
|
||||
Database host or socket path.
|
||||
If [](#opt-services.inventree.database.createLocally) is true and
|
||||
[](#opt-services.inventree.database.dbtype) is either `postgresql` or `mysql`,
|
||||
defaults to the correct Unix socket instead.
|
||||
'';
|
||||
};
|
||||
dbport = mkOption {
|
||||
type = types.port;
|
||||
default = 5432;
|
||||
description = "Database host port.";
|
||||
};
|
||||
dbname = mkOption {
|
||||
type = types.str;
|
||||
default = "inventree";
|
||||
description = "Database name.";
|
||||
};
|
||||
dbuser = mkOption {
|
||||
type = types.str;
|
||||
default = "inventree";
|
||||
defaultText = lib.literalExpression "inventree";
|
||||
description = "Database username.";
|
||||
};
|
||||
passwordFile = mkOption {
|
||||
type = with types; nullOr path;
|
||||
default = null;
|
||||
example = "/run/keys/inventree-dbpassword";
|
||||
description = ''
|
||||
A file containing the password corresponding to
|
||||
<option>database.user</option>.
|
||||
'';
|
||||
};
|
||||
createLocally = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Create the database and database user locally.";
|
||||
};
|
||||
};
|
||||
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = "localhost";
|
||||
example = "inventree.example.com";
|
||||
description = mdDoc ''
|
||||
The INVENTREE_SITE_URL option defines the base URL for the
|
||||
InvenTree server. This is a critical setting, and it is required
|
||||
for correct operation of the server. If not specified, the
|
||||
server will attempt to determine the site URL automatically -
|
||||
but this may not always be correct!
|
||||
|
||||
The site URL is the URL that users will use to access the
|
||||
InvenTree server. For example, if the server is accessible at
|
||||
`https://inventree.example.com`, the site URL should be set to
|
||||
`https://inventree.example.com`. Note that this is not
|
||||
necessarily the same as the internal URL that the server is
|
||||
running on - the internal URL will depend entirely on your
|
||||
server configuration and may be obscured by a reverse proxy or
|
||||
other such setup.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "inventree";
|
||||
description = "User under which InvenTree runs.";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "inventree";
|
||||
description = "Group under which InvenTree runs.";
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type =
|
||||
with lib.types;
|
||||
attrsOf (
|
||||
nullOr (oneOf [
|
||||
path
|
||||
str
|
||||
])
|
||||
);
|
||||
default = {
|
||||
INVENTREE_CONFIG_FILE = lib.mkDefault "${cfg.dataDir}/config/config.yaml";
|
||||
INVENTREE_OIDC_PRIVATE_KEY_FILE = lib.mkDefault "${cfg.dataDir}/config/oidc_private_key.txt";
|
||||
INVENTREE_STATIC_ROOT = lib.mkDefault "${cfg.dataDir}/data/static_root";
|
||||
INVENTREE_MEDIA_ROOT = lib.mkDefault "${cfg.dataDir}/data/media";
|
||||
INVENTREE_BACKUP_DIR = lib.mkDefault "${cfg.dataDir}/data/backups";
|
||||
INVENTREE_SITE_URL = lib.mkDefault "http://${cfg.domain}";
|
||||
INVENTREE_PLUGIN_FILE = lib.mkDefault "${cfg.dataDir}/data/plugins/plugins.txt";
|
||||
INVENTREE_PLUGIN_DIR = lib.mkDefault "${cfg.dataDir}/data/plugins";
|
||||
INVENTREE_ADMIN_PASSWORD_FILE = lib.mkDefault cfg.adminPasswordFile;
|
||||
INVENTREE_SECRET_KEY_FILE = lib.mkDefault cfg.secretKeyFile;
|
||||
INVENTREE_AUTO_UPDATE = lib.mkDefault "false";
|
||||
};
|
||||
description = ''
|
||||
InvenTree config options.
|
||||
|
||||
See [the documentation](https://docs.inventree.org/en/stable/start/config/) for available options.
|
||||
'';
|
||||
example = {
|
||||
INVENTREE_CACHE_ENABLED = true;
|
||||
INVENTREE_CACHE_HOST = "localhost";
|
||||
|
||||
INVENTREE_EMAIL_HOST = "smtp.example.com";
|
||||
INVENTREE_EMAIL_PORT = 25;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable (
|
||||
lib.mkMerge [
|
||||
{
|
||||
services.inventree.settings = {
|
||||
INVENTREE_DB_ENGINE = cfg.database.dbtype;
|
||||
INVENTREE_DB_NAME = cfg.database.dbname;
|
||||
INVENTREE_DB_HOST = cfg.database.dbhost;
|
||||
INVENTREE_DB_USER = cfg.database.dbuser;
|
||||
INVENTREE_DB_PORT = toString cfg.database.dbport;
|
||||
|
||||
INVENTREE_CONFIG_FILE = lib.mkDefault "${cfg.dataDir}/config/config.yaml";
|
||||
INVENTREE_OIDC_PRIVATE_KEY_FILE = lib.mkDefault "${cfg.dataDir}/config/oidc_private_key.txt";
|
||||
INVENTREE_STATIC_ROOT = lib.mkDefault "${cfg.dataDir}/data/static_root";
|
||||
INVENTREE_MEDIA_ROOT = lib.mkDefault "${cfg.dataDir}/data/media";
|
||||
INVENTREE_BACKUP_DIR = lib.mkDefault "${cfg.dataDir}/data/backups";
|
||||
INVENTREE_SITE_URL = lib.mkDefault "http://${cfg.domain}";
|
||||
INVENTREE_PLUGIN_FILE = lib.mkDefault "${cfg.dataDir}/data/plugins/plugins.txt";
|
||||
INVENTREE_PLUGIN_DIR = lib.mkDefault "${cfg.dataDir}/data/plugins";
|
||||
INVENTREE_ADMIN_PASSWORD_FILE = lib.mkDefault cfg.adminPasswordFile;
|
||||
INVENTREE_SECRET_KEY_FILE = lib.mkDefault cfg.secretKeyFile;
|
||||
INVENTREE_AUTO_UPDATE = lib.mkDefault "false";
|
||||
};
|
||||
environment.systemPackages = [ manage ];
|
||||
systemd.tmpfiles.rules = (
|
||||
map (dir: "d ${dir} 0755 inventree inventree") [
|
||||
"${cfg.dataDir}"
|
||||
"${cfg.dataDir}/config"
|
||||
"${cfg.dataDir}/data"
|
||||
"${cfg.dataDir}/data/static_root"
|
||||
"${cfg.dataDir}/data/media"
|
||||
"${cfg.dataDir}/data/backups"
|
||||
"${cfg.dataDir}/data/plugins"
|
||||
]
|
||||
);
|
||||
|
||||
services.postgresql = lib.mkIf pgsqlLocal {
|
||||
enable = true;
|
||||
ensureDatabases = [ cfg.database.dbname ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = cfg.database.dbuser;
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.mysql = lib.mkIf mysqlLocal {
|
||||
enable = true;
|
||||
package = lib.mkDefault pkgs.mariadb;
|
||||
ensureDatabases = [ cfg.database.dbname ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = cfg.database.dbuser;
|
||||
ensurePermissions = {
|
||||
"${cfg.database.dbname}.*" = "ALL PRIVILEGES";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.nginx.enable = true;
|
||||
services.nginx.virtualHosts.${cfg.domain} = {
|
||||
locations =
|
||||
let
|
||||
unixPath = config.systemd.sockets.inventree-server.socketConfig.ListenStream;
|
||||
in
|
||||
{
|
||||
"/" = {
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-By $server_addr:$server_port;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header CLIENT_IP $remote_addr;
|
||||
|
||||
proxy_pass_request_headers on;
|
||||
|
||||
proxy_redirect off;
|
||||
|
||||
client_max_body_size 100M;
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
'';
|
||||
proxyPass = "http://unix:${unixPath}";
|
||||
};
|
||||
"/auth" = {
|
||||
extraConfig = ''
|
||||
internal;
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
proxy_set_header X-Original-URI $request_uri;
|
||||
'';
|
||||
proxyPass = "http://unix:${unixPath}:/auth/";
|
||||
};
|
||||
"/static/" = {
|
||||
alias = "${cfg.settings.INVENTREE_STATIC_ROOT}/";
|
||||
extraConfig = ''
|
||||
autoindex on;
|
||||
|
||||
# Caching settings
|
||||
expires 30d;
|
||||
add_header Pragma public;
|
||||
add_header Cache-Control "public";
|
||||
'';
|
||||
};
|
||||
"/media/" = {
|
||||
alias = "${cfg.settings.INVENTREE_MEDIA_ROOT}/";
|
||||
extraConfig = ''
|
||||
auth_request /auth;
|
||||
add_header Content-disposition "attachment";
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.inventree-setup = {
|
||||
description = "Inventree setup";
|
||||
wantedBy = [ "inventree.target" ];
|
||||
partOf = [ "inventree.target" ];
|
||||
after = lib.optional mysqlLocal "mysql.service" ++ lib.optional pgsqlLocal "postgresql.target";
|
||||
requires = lib.optional mysqlLocal "mysql.service" ++ lib.optional pgsqlLocal "postgresql.target";
|
||||
before = [
|
||||
"inventree-static.service"
|
||||
"inventree-server.service"
|
||||
"inventree-qcluster.service"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
RemainAfterExit = true;
|
||||
PrivateTmp = true;
|
||||
}
|
||||
// lib.optionalAttrs (cfg.database.passwordFile != null) {
|
||||
LoadCredential = "db_password:${cfg.database.passwordFile}";
|
||||
};
|
||||
environment = cfg.settings;
|
||||
script = ''
|
||||
set -euo pipefail
|
||||
umask u=rwx,g=,o=
|
||||
|
||||
${
|
||||
lib.optionalString (cfg.database.passwordFile != null) ''
|
||||
INVENTREE_DB_PASSWORD=$(<"$CREDENTIALS_DIRECTORY/db_password")
|
||||
''
|
||||
} \
|
||||
exec ${pkg}/bin/inventree migrate
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.inventree-static = {
|
||||
description = "Inventree static migration";
|
||||
wantedBy = [ "inventree.target" ];
|
||||
partOf = [ "inventree.target" ];
|
||||
before = [ "inventree-server.service" ];
|
||||
environment = cfg.settings;
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
StateDirectory = "inventree";
|
||||
PrivateTmp = true;
|
||||
}
|
||||
// lib.optionalAttrs (cfg.database.passwordFile != null) {
|
||||
LoadCredential = "db_password:${cfg.database.passwordFile}";
|
||||
};
|
||||
script = ''
|
||||
${
|
||||
lib.optionalString (cfg.database.passwordFile != null) ''
|
||||
INVENTREE_DB_PASSWORD=$(<"$CREDENTIALS_DIRECTORY/db_password")
|
||||
''
|
||||
} \
|
||||
exec ${pkg}/bin/inventree collectstatic --no-input
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.inventree-server = {
|
||||
description = "Inventree Gunicorn service";
|
||||
requiredBy = [ "inventree.target" ];
|
||||
partOf = [ "inventree.target" ];
|
||||
environment = cfg.settings;
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
StateDirectory = "inventree";
|
||||
PrivateTmp = true;
|
||||
}
|
||||
// lib.optionalAttrs (cfg.database.passwordFile != null) {
|
||||
LoadCredential = "db_password:${cfg.database.passwordFile}";
|
||||
};
|
||||
script = ''
|
||||
${
|
||||
lib.optionalString (cfg.database.passwordFile != null) ''
|
||||
INVENTREE_DB_PASSWORD=$(<"$CREDENTIALS_DIRECTORY/db_password")
|
||||
''
|
||||
} \
|
||||
exec ${pkg}/bin/gunicorn InvenTree.wsgi
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.sockets.inventree-server = {
|
||||
wantedBy = [ "sockets.target" ];
|
||||
partOf = [ "inventree.target" ];
|
||||
socketConfig.ListenStream = "/run/inventree/gunicorn.socket";
|
||||
};
|
||||
|
||||
systemd.services.inventree-qcluster = {
|
||||
description = "InvenTree qcluster server";
|
||||
requiredBy = [ "inventree.target" ];
|
||||
wantedBy = [ "inventree.target" ];
|
||||
partOf = [ "inventree.target" ];
|
||||
environment = cfg.settings;
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
StateDirectory = "inventree";
|
||||
PrivateTmp = true;
|
||||
}
|
||||
// lib.optionalAttrs (cfg.database.passwordFile != null) {
|
||||
LoadCredential = "db_password:${cfg.database.passwordFile}";
|
||||
};
|
||||
script = ''
|
||||
${
|
||||
lib.optionalString (cfg.database.passwordFile != null) ''
|
||||
INVENTREE_DB_PASSWORD=$(<"$CREDENTIALS_DIRECTORY/db_password")
|
||||
''
|
||||
} \
|
||||
exec ${pkg}/bin/inventree qcluster
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.targets.inventree = {
|
||||
description = "Target for all InvenTree services";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
};
|
||||
|
||||
users = lib.optionalAttrs (cfg.user == cfg.user) {
|
||||
users.${cfg.user} = {
|
||||
group = cfg.group;
|
||||
isSystemUser = true;
|
||||
home = cfg.dataDir;
|
||||
};
|
||||
groups.${cfg.group}.members = [ cfg.user ];
|
||||
};
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -790,6 +790,7 @@ in
|
||||
installer = handleTest ./installer.nix { };
|
||||
installer-systemd-stage-1 = handleTest ./installer-systemd-stage-1.nix { };
|
||||
intune = runTest ./intune.nix;
|
||||
inventree = runTest ./inventree.nix;
|
||||
invidious = runTest ./invidious.nix;
|
||||
invoiceplane = runTest ./invoiceplane.nix;
|
||||
iodine = runTest ./iodine.nix;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "inventree";
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
kurogeek
|
||||
];
|
||||
|
||||
nodes = {
|
||||
psqlTest = {
|
||||
services.inventree = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
mysqlTest = {
|
||||
services.inventree = {
|
||||
enable = true;
|
||||
database.dbtype = "mysql";
|
||||
};
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
start_all()
|
||||
psqlTest.wait_for_unit("inventree.target")
|
||||
psqlTest.wait_for_unit("inventree-server.service")
|
||||
psqlTest.wait_for_open_unix_socket("/run/inventree/gunicorn.socket")
|
||||
psqlTest.wait_until_succeeds("curl -sf http://localhost/web")
|
||||
|
||||
mysqlTest.wait_for_unit("inventree.target")
|
||||
mysqlTest.wait_for_unit("inventree-server.service")
|
||||
mysqlTest.wait_for_open_unix_socket("/run/inventree/gunicorn.socket")
|
||||
mysqlTest.wait_until_succeeds("curl -sf http://localhost/web")
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
{
|
||||
fetchFromGitHub,
|
||||
fetchYarnDeps,
|
||||
lib,
|
||||
nodejs,
|
||||
python312,
|
||||
stdenv,
|
||||
yarnBuildHook,
|
||||
yarnConfigHook,
|
||||
yarnInstallHook,
|
||||
}:
|
||||
let
|
||||
python3 = python312.override {
|
||||
self = python3;
|
||||
packageOverrides = self: super: {
|
||||
django = super.django_4;
|
||||
};
|
||||
};
|
||||
|
||||
version = "0.18.0";
|
||||
src = fetchFromGitHub {
|
||||
owner = "inventree";
|
||||
repo = "inventree";
|
||||
rev = "d6c722041987d13a4e596711aafa0f30cde3f9a0";
|
||||
hash = "sha256-BnRE6BM6/LHUtP3H0L8qh3LAxFphNlpll+r1oH4sGuQ=";
|
||||
};
|
||||
|
||||
frontend =
|
||||
let
|
||||
frontendSource = src + "/src/frontend";
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
pname = "inventree-frontend";
|
||||
inherit version;
|
||||
|
||||
src = frontendSource;
|
||||
|
||||
yarnOfflineCache = fetchYarnDeps {
|
||||
yarnLock = finalAttrs.src + "/yarn.lock";
|
||||
hash = "sha256-wXIVtW1dMxhyuZ1LmuYZ2IwUbRZwbYmdRkiribMbK20=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
nodejs
|
||||
yarnConfigHook
|
||||
yarnBuildHook
|
||||
yarnInstallHook
|
||||
];
|
||||
|
||||
buildPhase = ''
|
||||
mkdir -p $out
|
||||
|
||||
export PATH=$PATH:$TMP/frontend/node_modules/.bin
|
||||
substituteInPlace $TMP/frontend/vite.config.ts --replace-warn "../../src/backend/InvenTree/web/static/web" "$out/static/web"
|
||||
|
||||
npm run extract
|
||||
npm run compile
|
||||
npm run build
|
||||
'';
|
||||
});
|
||||
in
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "inventree";
|
||||
pyproject = true;
|
||||
inherit version src;
|
||||
|
||||
dependencies =
|
||||
with python3.pkgs;
|
||||
[
|
||||
django
|
||||
dj-rest-auth
|
||||
django-allauth
|
||||
django-cleanup
|
||||
django-cors-headers
|
||||
django-crispy-forms
|
||||
django-dbbackup
|
||||
django-error-report-2
|
||||
django-filter
|
||||
django-flags
|
||||
django-formtools
|
||||
django-ical
|
||||
django-import-export
|
||||
django-maintenance-mode
|
||||
django-markdownify
|
||||
django-money
|
||||
django-mptt
|
||||
django-mailbox
|
||||
django-anymail
|
||||
django-q2
|
||||
django-redis
|
||||
django-sesame
|
||||
django-sql-utils
|
||||
django-sslserver
|
||||
django-stdimage
|
||||
django-structlog
|
||||
django-taggit
|
||||
django-oauth-toolkit
|
||||
django-otp
|
||||
django-user-sessions
|
||||
django-weasyprint
|
||||
standard-imghdr
|
||||
django-xforwardedfor-middleware
|
||||
djangorestframework-simplejwt
|
||||
djangorestframework
|
||||
drf-spectacular
|
||||
|
||||
bleach
|
||||
cryptography
|
||||
distutils
|
||||
dulwich
|
||||
feedparser
|
||||
gunicorn
|
||||
jinja2
|
||||
pdf2image
|
||||
pillow
|
||||
pint
|
||||
python-barcode
|
||||
python-dotenv
|
||||
qrcode
|
||||
pytz
|
||||
pyyaml
|
||||
rapidfuzz
|
||||
sentry-sdk
|
||||
structlog
|
||||
tablib
|
||||
tinycss2
|
||||
weasyprint
|
||||
whitenoise
|
||||
pypdf
|
||||
ppf-datamatrix
|
||||
psycopg2
|
||||
mysqlclient
|
||||
|
||||
opentelemetry-api
|
||||
opentelemetry-sdk
|
||||
opentelemetry-exporter-otlp
|
||||
opentelemetry-instrumentation-django
|
||||
opentelemetry-instrumentation-requests
|
||||
opentelemetry-instrumentation-redis
|
||||
opentelemetry-instrumentation-sqlite3
|
||||
opentelemetry-instrumentation-system-metrics
|
||||
opentelemetry-instrumentation-wsgi
|
||||
]
|
||||
++ tablib.optional-dependencies.all
|
||||
++ tablib.optional-dependencies.xls
|
||||
++ tablib.optional-dependencies.xlsx
|
||||
++ djangorestframework-simplejwt.optional-dependencies.crypto
|
||||
++ django-anymail.optional-dependencies.amazon-ses
|
||||
++ django-allauth.optional-dependencies.socialaccount
|
||||
++ django-allauth.optional-dependencies.saml
|
||||
++ django-allauth.optional-dependencies.openid
|
||||
++ django-allauth.optional-dependencies.mfa;
|
||||
|
||||
build-system = [ python3.pkgs.setuptools ];
|
||||
|
||||
prePatch =
|
||||
let
|
||||
skippedCheckFunctions = [
|
||||
"test_task_check_for_updates"
|
||||
"test_download_image"
|
||||
"test_commit_info"
|
||||
"test_rates"
|
||||
"test_download_build_orders"
|
||||
"test_valid_url"
|
||||
"test_refresh_endpoint"
|
||||
"test_download_csv"
|
||||
"test_download_line_items"
|
||||
"test_export"
|
||||
"test_download_xlsx"
|
||||
"test_download_csv"
|
||||
"test_export"
|
||||
"test_part_label_translation"
|
||||
"test_part_download"
|
||||
"test_date_filters"
|
||||
"test_bom_export"
|
||||
"test_hash"
|
||||
"test_date"
|
||||
"test_api_call"
|
||||
"test_function_errors"
|
||||
"test_stocktake_exporter"
|
||||
"test_return"
|
||||
"test_plugin_install"
|
||||
"test_full_process"
|
||||
"test_package_loading"
|
||||
"test_export"
|
||||
"test_users_exist"
|
||||
];
|
||||
skippedFuncScripts = builtins.map (funcName: ''
|
||||
grep -rlZ ${funcName} . | while IFS= read -r -d "" file; do
|
||||
substituteInPlace "$file" --replace-fail "${funcName}" "skip_${funcName}"
|
||||
done
|
||||
'') skippedCheckFunctions;
|
||||
in
|
||||
''
|
||||
${lib.concatStringsSep "\n" skippedFuncScripts}
|
||||
'';
|
||||
|
||||
installPhase =
|
||||
let
|
||||
pythonPath = python3.pkgs.makePythonPath dependencies;
|
||||
in
|
||||
''
|
||||
runHook preInstall
|
||||
|
||||
# Don't need to bother with a non-maintained library from ages ago
|
||||
substituteInPlace src/backend/InvenTree/InvenTree/settings.py --replace-fail "django_slowtests.testrunner.DiscoverSlowestTestsRunner" "django.test.runner.DiscoverRunner"
|
||||
|
||||
mkdir -p $out/lib/${pname}/src/backend/InvenTree/web/
|
||||
cp -r src $out/lib/${pname}
|
||||
ln -s ${frontend}/static $out/lib/${pname}/src/backend/InvenTree/web
|
||||
# cp -r ${frontend}/static $out/lib/${pname}/src/backend/InvenTree/web
|
||||
|
||||
chmod +x $out/lib/${pname}/src/backend/InvenTree/manage.py
|
||||
|
||||
makeWrapper $out/lib/${pname}/src/backend/InvenTree/manage.py $out/bin/${pname} \
|
||||
--prefix PYTHONPATH : "${pythonPath}:$out/lib/${pname}/src/backend/InvenTree"
|
||||
|
||||
makeWrapper ${lib.getExe python3.pkgs.gunicorn} $out/bin/gunicorn \
|
||||
--prefix PYTHONPATH : "${pythonPath}:$out/${python3.sitePackages}":"${pythonPath}:$out/lib/${pname}/src/backend/InvenTree"
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
doCheck = true;
|
||||
env = {
|
||||
DJANGO_SETTINGS_MODULE = "InvenTree.settings";
|
||||
};
|
||||
|
||||
checkPhase = ''
|
||||
runHook preCheck
|
||||
|
||||
tmpDir=$(mktemp -d)
|
||||
mkdir -p $tmpDir/media
|
||||
mkdir -p $tmpDir/.cache/fontconfig
|
||||
export HOME=$tmpDir
|
||||
export INVENTREE_STATIC_ROOT=$tmpDir
|
||||
export INVENTREE_MEDIA_ROOT=$tmpDir/media
|
||||
export INVENTREE_BACKUP_DIR=$tmpDir
|
||||
export INVENTREE_DB_ENGINE=django.db.backends.sqlite3
|
||||
export INVENTREE_DB_NAME=inventree.db
|
||||
export INVENTREE_SITE_URL="http://localhost:8000"
|
||||
|
||||
export INVENTREE_PLUGINS_ENABLED=true
|
||||
export INVENTREE_PLUGIN_TESTING=true
|
||||
export INVENTREE_PLUGIN_TESTING_SETUP=true
|
||||
|
||||
pushd src/backend/InvenTree
|
||||
${python3.interpreter} ./manage.py check
|
||||
${python3.interpreter} ./manage.py migrate
|
||||
|
||||
${python3.interpreter} ./manage.py test --failfast
|
||||
popd
|
||||
|
||||
runHook postCheck
|
||||
'';
|
||||
|
||||
nativeCheckInputs = with python3.pkgs; [
|
||||
django-test-migrations
|
||||
pytest-django
|
||||
pytest-env
|
||||
pytestCheckHook
|
||||
invoke
|
||||
coverage
|
||||
pytest-cov
|
||||
pdfminer-six
|
||||
];
|
||||
passthru =
|
||||
let
|
||||
pythonPath = python3.pkgs.makePythonPath dependencies;
|
||||
in
|
||||
{
|
||||
inherit frontend;
|
||||
pythonPath = pythonPath;
|
||||
};
|
||||
|
||||
meta = {
|
||||
description = "Open Source Inventory Management System";
|
||||
homepage = "https://inventree.org/";
|
||||
changelog = "https://github.com/paperless-ngx/paperless-ngx/releases/tag/${src.tag}";
|
||||
license = lib.licenses.mit;
|
||||
platforms = lib.platforms.linux;
|
||||
mainProgram = "inventree";
|
||||
maintainers = with lib.maintainers; [
|
||||
kurogeek
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -12517,4 +12517,6 @@ with pkgs;
|
||||
gpac-unstable = callPackage ../by-name/gp/gpac/package.nix {
|
||||
releaseChannel = "unstable";
|
||||
};
|
||||
|
||||
inventree = callPackage ../by-name/in/inventree/package.nix { };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user