From b1e31c41f82334fcb3cee62d852e7d6a8d23abe2 Mon Sep 17 00:00:00 2001 From: soyouzpanda Date: Thu, 22 May 2025 21:45:10 +0200 Subject: [PATCH] lasuite-drive: init at 0.18.0 --- pkgs/by-name/la/lasuite-drive/frontend.nix | 48 ++++++ pkgs/by-name/la/lasuite-drive/mail.nix | 42 +++++ pkgs/by-name/la/lasuite-drive/package.nix | 152 ++++++++++++++++++ .../la/lasuite-drive/pyproject_build.patch | 24 +++ .../la/lasuite-drive/secure_settings.patch | 36 +++++ 5 files changed, 302 insertions(+) create mode 100644 pkgs/by-name/la/lasuite-drive/frontend.nix create mode 100644 pkgs/by-name/la/lasuite-drive/mail.nix create mode 100644 pkgs/by-name/la/lasuite-drive/package.nix create mode 100644 pkgs/by-name/la/lasuite-drive/pyproject_build.patch create mode 100644 pkgs/by-name/la/lasuite-drive/secure_settings.patch diff --git a/pkgs/by-name/la/lasuite-drive/frontend.nix b/pkgs/by-name/la/lasuite-drive/frontend.nix new file mode 100644 index 000000000000..5ed9033ec82e --- /dev/null +++ b/pkgs/by-name/la/lasuite-drive/frontend.nix @@ -0,0 +1,48 @@ +{ + src, + version, + meta, + stdenv, + fetchYarnDeps, + nodejs, + fixup-yarn-lock, + yarn, + yarnConfigHook, + yarnBuildHook, +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "lasuite-drive-frontend"; + inherit src version; + + sourceRoot = "${finalAttrs.src.name}/src/frontend"; + + offlineCache = fetchYarnDeps { + yarnLock = "${finalAttrs.src}/src/frontend/yarn.lock"; + hash = "sha256-yUKJp6yUTxpvkaA+YuQC3r1t4LBvuYMv1xesLewbK/U="; + }; + + nativeBuildInputs = [ + nodejs + fixup-yarn-lock + yarn + yarnConfigHook + yarnBuildHook + ]; + + strictDeps = true; + + installPhase = '' + runHook preInstall + + cp -r apps/drive/out/ $out + + runHook postInstall + ''; + + __structuredAttrs = true; + + meta = meta // { + description = "A collaborative file sharing and document management platform that scales. Built with Django and React. Opensource alternative to Sharepoint or Google Drive"; + }; +}) diff --git a/pkgs/by-name/la/lasuite-drive/mail.nix b/pkgs/by-name/la/lasuite-drive/mail.nix new file mode 100644 index 000000000000..e30e55cbaa34 --- /dev/null +++ b/pkgs/by-name/la/lasuite-drive/mail.nix @@ -0,0 +1,42 @@ +{ + src, + version, + meta, + stdenv, + fetchYarnDeps, + nodejs, + yarnConfigHook, + yarnBuildHook, +}: +stdenv.mkDerivation (finalAttrs: { + pname = "lasuite-drive-mail"; + inherit src version; + + sourceRoot = "${finalAttrs.src.name}/src/mail"; + + postPatch = '' + substituteInPlace bin/html-to-plain-text bin/mjml-to-html \ + --replace-fail \ + '../backend/core/templates/mail' \ + '${placeholder "out"}' + ''; + + offlineCache = fetchYarnDeps { + yarnLock = "${finalAttrs.src}/src/mail/yarn.lock"; + hash = "sha256-UPIb9QJk+zC8wYeBeDnmlGLhHDhsEOoT+qquFM1XyqU="; + }; + + nativeBuildInputs = [ + nodejs + yarnConfigHook + yarnBuildHook + ]; + + dontInstall = true; + + __structuredAttrs = true; + + meta = meta // { + description = "HTML mail templates for LaSuite Drive"; + }; +}) diff --git a/pkgs/by-name/la/lasuite-drive/package.nix b/pkgs/by-name/la/lasuite-drive/package.nix new file mode 100644 index 000000000000..7f608fb95846 --- /dev/null +++ b/pkgs/by-name/la/lasuite-drive/package.nix @@ -0,0 +1,152 @@ +{ + callPackage, + lib, + python3, + stdenv, + fetchFromGitHub, +}: +let + version = "0.18.0"; + + src = fetchFromGitHub { + owner = "suitenumerique"; + repo = "drive"; + tag = "v${version}"; + hash = "sha256-JoOHbwZR4salfLB9Gg7kfRMDcDA/Srn8qwUqLAZtsz8="; + }; + + meta = { + homepage = "https://github.com/suitenumerique/drive"; + changelog = "https://github.com/suitenumerique/drive/blob/${src.tag}/CHANGELOG.md"; + license = lib.licenses.mit; + maintainers = with lib.maintainers; [ soyouzpanda ]; + platforms = lib.platforms.linux; + }; + + mail = callPackage ./mail.nix { inherit src version meta; }; + frontend = callPackage ./frontend.nix { inherit src version meta; }; + + python = python3.override { + self = python; + packageOverrides = (self: super: { django = super.django_5; }); + }; + +in +python.pkgs.buildPythonApplication (finalAttrs: { + pname = "lasuite-drive"; + pyproject = true; + inherit version src; + + sourceRoot = "${finalAttrs.src.name}/src/backend"; + + patches = [ + # Support configuration throught environment variables for SECURE_* + ./secure_settings.patch + # Fix some build fields on pyproject + ./pyproject_build.patch + ]; + + build-system = with python.pkgs; [ uv-build ]; + + dependencies = + with python.pkgs; + [ + boto3 + brotli + celery + defusedxml + dj-database-url + django + django-configurations + django-cors-headers + django-countries + django-debug-toolbar + django-extensions + django-filter + django-lasuite + django-ltree + django-parler + django-pydantic-field + django-redis + django-storages + django-timezone-field + djangorestframework + djangorestframework-api-key + dockerflow + drf-spectacular + drf-spectacular-sidecar + drf-standardized-errors + easy-thumbnails + factory-boy + gunicorn + jsonschema + markdown + mozilla-django-oidc + nested-multipart-parser + posthog + psycopg + pydantic + pyjwt + python-magic + redis + requests + sentry-sdk + url-normalize + whitenoise + ] + ++ celery.optional-dependencies.redis + ++ django-storages.optional-dependencies.s3; + + pythonRelaxDeps = true; + + postPatch = '' + # Put assets inside a data directory + # so uv will copy the assets directory + # entirely + mkdir data + mv assets data + '' + + (lib.optionalString stdenv.hostPlatform.isDarwin '' + substituteInPlace impress/settings.py \ + --replace-fail \ + "gethostname()" \ + "gethostname() + '.local'" + ''); + __darwinAllowLocalNetworking = true; + + postBuild = '' + export DATA_DIR=$(pwd)/data + ${python.pythonOnBuildForHost.interpreter} manage.py collectstatic --no-input --clear + ''; + + postInstall = + let + pythonPath = python.pkgs.makePythonPath finalAttrs.passthru.dependencies; + in + '' + mkdir -p $out/{bin,share} + cp ./manage.py $out/bin/.manage.py + cp -r data/static $out/share + chmod +x $out/bin/.manage.py + makeWrapper $out/bin/.manage.py $out/bin/drive \ + --prefix PYTHONPATH : "${pythonPath}" + makeWrapper ${lib.getExe python.pkgs.celery} $out/bin/celery \ + --prefix PYTHONPATH : "${pythonPath}:$out/${python.sitePackages}" + makeWrapper ${lib.getExe python.pkgs.gunicorn} $out/bin/gunicorn \ + --prefix PYTHONPATH : "${pythonPath}:$out/${python.sitePackages}" + + mkdir -p $out/${python.sitePackages}/core/templates + ln -sv ${mail}/ $out/${python.sitePackages}/core/templates/mail + ''; + + passthru = { + inherit mail frontend; + }; + + __structuredAttrs = true; + + meta = meta // { + description = "A collaborative file sharing and document management platform that scales. Built with Django and React. Opensource alternative to Sharepoint or Google Drive"; + mainProgram = "drive"; + }; +}) diff --git a/pkgs/by-name/la/lasuite-drive/pyproject_build.patch b/pkgs/by-name/la/lasuite-drive/pyproject_build.patch new file mode 100644 index 000000000000..062b1e6b4b59 --- /dev/null +++ b/pkgs/by-name/la/lasuite-drive/pyproject_build.patch @@ -0,0 +1,24 @@ +diff --git a/pyproject.toml b/pyproject.toml +index ba8f5362..ddc40c83 100644 +--- a/pyproject.toml ++++ b/pyproject.toml +@@ -2,7 +2,7 @@ + # drive package + # + [build-system] +-requires = ["uv_build>=0.11.7,<0.12.0"] ++requires = ["uv_build"] + build-backend = "uv_build" + + [project] +@@ -102,6 +102,9 @@ constraint-dependencies = [ + + [tool.uv.build-backend] + module-root = "" ++module-name = ["core", "demo", "drive", "e2e", "wopi"] ++data = ["data"] ++namespace = true + source-exclude = [ + "**/tests/**", + "**/test_*.py", + diff --git a/pkgs/by-name/la/lasuite-drive/secure_settings.patch b/pkgs/by-name/la/lasuite-drive/secure_settings.patch new file mode 100644 index 000000000000..9eb2b43f345c --- /dev/null +++ b/pkgs/by-name/la/lasuite-drive/secure_settings.patch @@ -0,0 +1,36 @@ +diff --git a/drive/settings.py b/drive/settings.py +index 82f4d31..3d66c23 100755 +--- a/drive/settings.py ++++ b/drive/settings.py +@@ -775,19 +775,24 @@ class Production(Base): + # + # In other cases, you should comment the following line to avoid security issues. + # SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") +- SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") +- SECURE_HSTS_SECONDS = 60 +- SECURE_HSTS_PRELOAD = True +- SECURE_HSTS_INCLUDE_SUBDOMAINS = True +- SECURE_SSL_REDIRECT = True ++ SECURE_PROXY_SSL_HEADER = values.TupleValue(("HTTP_X_FORWARDED_PROTO", "https"), ++ environ_name="SECURE_PROXY_SSL_HEADER") ++ SECURE_HSTS_SECONDS = values.IntegerValue( ++ 60, environ_name="SECURE_HSTS_SECONDS") ++ SECURE_HSTS_PRELOAD = values.BooleanValue( ++ True, environ_name="SECURE_HSTS_PRELOAD") ++ SECURE_HSTS_INCLUDE_SUBDOMAINS = values.BooleanValue( ++ True, environ_name="SECURE_HSTS_INCLUDE_SUBDOMAINS") ++ SECURE_SSL_REDIRECT = values.BooleanValue( ++ True, environ_name="SECURE_SSL_REDIRECT") + SECURE_REDIRECT_EXEMPT = [ + "^__lbheartbeat__", + "^__heartbeat__", + ] + + # Modern browsers require to have the `secure` attribute on cookies with `Samesite=none` +- CSRF_COOKIE_SECURE = True +- SESSION_COOKIE_SECURE = True ++ CSRF_COOKIE_SECURE = values.BooleanValue(True, environ_name="CSRF_COOKIE_SECURE") ++ SESSION_COOKIE_SECURE = values.BooleanValue(True, environ_name="SESSION_COOKIE_SECURE") + + # Privacy + SECURE_REFERRER_POLICY = "same-origin"