Merge pull request #227642 from Flakebi/powerdns-admin2

powerdns-admin: 0.3.0 -> 0.4.1
This commit is contained in:
Ryan Lahfa 2023-05-22 09:30:24 +02:00 committed by GitHub
commit 0e662e669a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 1232 additions and 767 deletions

View file

@ -78,7 +78,8 @@ in
environment.PYTHONPATH = pkgs.powerdns-admin.pythonPath; environment.PYTHONPATH = pkgs.powerdns-admin.pythonPath;
serviceConfig = { serviceConfig = {
ExecStart = "${pkgs.powerdns-admin}/bin/powerdns-admin --pid /run/powerdns-admin/pid ${escapeShellArgs cfg.extraArgs}"; ExecStart = "${pkgs.powerdns-admin}/bin/powerdns-admin --pid /run/powerdns-admin/pid ${escapeShellArgs cfg.extraArgs}";
ExecStartPre = "${pkgs.coreutils}/bin/env FLASK_APP=${pkgs.powerdns-admin}/share/powerdnsadmin/__init__.py ${pkgs.python3Packages.flask}/bin/flask db upgrade -d ${pkgs.powerdns-admin}/share/migrations"; # Set environment variables only for starting flask database upgrade
ExecStartPre = "${pkgs.coreutils}/bin/env FLASK_APP=${pkgs.powerdns-admin}/share/powerdnsadmin/__init__.py SESSION_TYPE= ${pkgs.python3Packages.flask}/bin/flask db upgrade -d ${pkgs.powerdns-admin}/share/migrations";
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
ExecStop = "${pkgs.coreutils}/bin/kill -TERM $MAINPID"; ExecStop = "${pkgs.coreutils}/bin/kill -TERM $MAINPID";
PIDFile = "/run/powerdns-admin/pid"; PIDFile = "/run/powerdns-admin/pid";

View file

@ -10,6 +10,7 @@ let
defaultConfig = '' defaultConfig = ''
BIND_ADDRESS = '127.0.0.1' BIND_ADDRESS = '127.0.0.1'
PORT = 8000 PORT = 8000
CAPTCHA_ENABLE = False
''; '';
makeAppTest = name: configs: makeTest { makeAppTest = name: configs: makeTest {
@ -98,7 +99,30 @@ let
tcp = { tcp = {
services.powerdns-admin.extraArgs = [ "-b" "127.0.0.1:8000" ]; services.powerdns-admin.extraArgs = [ "-b" "127.0.0.1:8000" ];
system.build.testScript = '' system.build.testScript = ''
set -euxo pipefail
curl -sSf http://127.0.0.1:8000/ curl -sSf http://127.0.0.1:8000/
# Create account to check that the database migrations ran
csrf_token="$(curl -sSfc session http://127.0.0.1:8000/register | grep _csrf_token | cut -d\" -f6)"
# Outputs 'Redirecting' if successful
curl -sSfb session http://127.0.0.1:8000/register \
-F "_csrf_token=$csrf_token" \
-F "firstname=first" \
-F "lastname=last" \
-F "email=a@example.com" \
-F "username=user" \
-F "password=password" \
-F "rpassword=password" | grep Redirecting
# Login
# Outputs 'Redirecting' if successful
curl -sSfb session http://127.0.0.1:8000/login \
-F "_csrf_token=$csrf_token" \
-F "username=user" \
-F "password=password" | grep Redirecting
# Check that we are logged in, this redirects to /admin/setting/pdns if we are
curl -sSfb session http://127.0.0.1:8000/dashboard/ | grep /admin/setting
''; '';
}; };
unix = { unix = {

View file

@ -1,53 +1,55 @@
{ lib, stdenv, fetchFromGitHub, mkYarnPackage, nixosTests, writeText, python3 }: { lib, stdenv, fetchFromGitHub, mkYarnPackage, nixosTests, writeText, python3 }:
let let
version = "0.3.0"; version = "0.4.1";
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "ngoduykhanh"; owner = "PowerDNS-Admin";
repo = "PowerDNS-Admin"; repo = "PowerDNS-Admin";
rev = "v${version}"; rev = "v${version}";
hash = "sha256-e11u0jdJr+2TDXvBAPlDfnuuDwSfBq+JtvnDUTNKp/c="; hash = "sha256-AwqEcAPD1SF1Ma3wtH03mXlTywM0Q19hciCmTtlr3gk=";
}; };
python = python3; python = python3;
pythonDeps = with python.pkgs; [ pythonDeps = with python.pkgs; [
flask flask_assets flask-login flask-sqlalchemy flask_migrate flask-seasurf flask_mail flask-session flask-sslify flask flask_assets flask-login flask-sqlalchemy flask_migrate flask-seasurf flask_mail flask-session flask-session-captcha flask-sslify
mysqlclient psycopg2 sqlalchemy mysqlclient psycopg2 sqlalchemy
cffi configobj cryptography bcrypt requests python-ldap pyotp qrcode dnspython certifi cffi configobj cryptography bcrypt requests python-ldap pyotp qrcode dnspython
gunicorn python3-saml pytz cssmin rjsmin authlib bravado-core gunicorn itsdangerous python3-saml pytz rcssmin rjsmin authlib bravado-core
lima pytimeparse pyyaml jinja2 itsdangerous werkzeug lima lxml passlib pyasn1 pytimeparse pyyaml jinja2 itsdangerous webcolors werkzeug zipp zxcvbn
]; ];
assets = mkYarnPackage { assets = mkYarnPackage {
inherit src version; inherit src version;
packageJSON = ./package.json; packageJSON = ./package.json;
yarnNix = ./yarndeps.nix; yarnNix = ./yarndeps.nix;
# Copied from package.json, see also
# https://github.com/NixOS/nixpkgs/pull/214952
packageResolutions = {
"@fortawesome/fontawesome-free" = "6.3.0";
};
nativeBuildInputs = pythonDeps; nativeBuildInputs = pythonDeps;
patchPhase = '' patchPhase = ''
sed -i -r -e "s|'cssmin',\s?'cssrewrite'|'cssmin'|g" powerdnsadmin/assets.py sed -i -r -e "s|'rcssmin',\s?'cssrewrite'|'rcssmin'|g" powerdnsadmin/assets.py
''; '';
buildPhase = '' buildPhase = ''
# The build process expects the directory to be writable # The build process expects the directory to be writable
# with node_modules at a specific path # with node_modules at a specific path
# https://github.com/ngoduykhanh/PowerDNS-Admin/blob/master/.yarnrc # https://github.com/PowerDNS-Admin/PowerDNS-Admin/blob/master/.yarnrc
approot=deps/powerdns-admin-assets approot=deps/powerdns-admin-assets
ln -s $node_modules $approot/powerdnsadmin/static/node_modules ln -s $node_modules $approot/powerdnsadmin/static/node_modules
FLASK_APP=$approot/powerdnsadmin/__init__.py flask assets build SESSION_TYPE=filesystem FLASK_APP=$approot/powerdnsadmin/__init__.py flask assets build
''; '';
installPhase = '' installPhase = ''
# https://github.com/ngoduykhanh/PowerDNS-Admin/blob/54b257768f600c5548a1c7e50eac49c40df49f92/docker/Dockerfile#L43 # https://github.com/PowerDNS-Admin/PowerDNS-Admin/blob/54b257768f600c5548a1c7e50eac49c40df49f92/docker/Dockerfile#L43
mkdir $out mkdir $out
cp -r $approot/powerdnsadmin/static/{generated,assets,img} $out cp -r $approot/powerdnsadmin/static/{generated,assets,img} $out
find $node_modules -name webfonts -exec cp -r {} $out \;
find $node_modules -name fonts -exec cp -r {} $out \;
find $node_modules/icheck/skins/square -name '*.png' -exec cp {} $out/generated \; find $node_modules/icheck/skins/square -name '*.png' -exec cp {} $out/generated \;
mkdir $out/fonts
cp $node_modules/ionicons/dist/fonts/* $out/fonts
cp $node_modules/bootstrap/dist/fonts/* $out/fonts
cp $node_modules/font-awesome/fonts/* $out/fonts
''; '';
distPhase = "true"; distPhase = "true";
}; };
@ -61,7 +63,7 @@ let
assets.register('js_main', 'generated/main.js') assets.register('js_main', 'generated/main.js')
assets.register('css_main', 'generated/main.css') assets.register('css_main', 'generated/main.css')
''; '';
in stdenv.mkDerivation rec { in stdenv.mkDerivation {
pname = "powerdns-admin"; pname = "powerdns-admin";
inherit src version; inherit src version;
@ -81,7 +83,13 @@ in stdenv.mkDerivation rec {
postPatch = '' postPatch = ''
rm -r powerdnsadmin/static powerdnsadmin/assets.py rm -r powerdnsadmin/static powerdnsadmin/assets.py
sed -i "s/id:/'id':/" migrations/versions/787bdba9e147_init_db.py # flask-migrate 4.0 compatibility: https://github.com/PowerDNS-Admin/PowerDNS-Admin/issues/1376
substituteInPlace migrations/env.py --replace "render_as_batch=config.get_main_option('sqlalchemy.url').startswith('sqlite:')," ""
# flask-session and powerdns-admin both try to add sqlalchemy to flask.
# Reuse the database for flask-session
substituteInPlace powerdnsadmin/__init__.py --replace "sess = Session(app)" "app.config['SESSION_SQLALCHEMY'] = models.base.db; sess = Session(app)"
# Routes creates session database tables, so it needs a context
substituteInPlace powerdnsadmin/__init__.py --replace "routes.init_app(app)" "with app.app_context(): routes.init_app(app)"
''; '';
installPhase = '' installPhase = ''
@ -113,7 +121,7 @@ in stdenv.mkDerivation rec {
meta = with lib; { meta = with lib; {
description = "A PowerDNS web interface with advanced features"; description = "A PowerDNS web interface with advanced features";
homepage = "https://github.com/ngoduykhanh/PowerDNS-Admin"; homepage = "https://github.com/PowerDNS-Admin/PowerDNS-Admin";
license = licenses.mit; license = licenses.mit;
maintainers = with maintainers; [ Flakebi zhaofengli ]; maintainers = with maintainers; [ Flakebi zhaofengli ];
}; };

View file

@ -1,17 +1,24 @@
{ {
"dependencies": { "dependencies": {
"admin-lte": "2.4.9", "@fortawesome/fontawesome-free": "6.3.0",
"bootstrap": "^3.4.1", "admin-lte": "3.2.0",
"bootstrap-datepicker": "^1.8.0", "bootstrap": "4.6.2",
"bootstrap-datepicker": "^1.9.0",
"bootstrap-validator": "^0.11.9", "bootstrap-validator": "^0.11.9",
"datatables.net-plugins": "^1.10.19", "datatables.net-plugins": "^1.13.1",
"icheck": "^1.0.2", "icheck": "^1.0.2",
"jquery-slimscroll": "^1.3.8", "jquery-slimscroll": "^1.3.8",
"jquery-ui-dist": "^1.12.1", "jquery-sparkline": "^2.4.0",
"jquery-ui-dist": "^1.13.2",
"jquery.quicksearch": "^2.4.0", "jquery.quicksearch": "^2.4.0",
"jtimeout": "^3.1.0", "jquery-validation": "^1.19.5",
"jtimeout": "^3.2.0",
"knockout": "^3.5.1",
"multiselect": "^0.9.12" "multiselect": "^0.9.12"
}, },
"resolutions": {
"admin-lte/@fortawesome/fontawesome-free": "6.3.0"
},
"name": "powerdns-admin-assets", "name": "powerdns-admin-assets",
"version": "0.3.0" "version": "0.4.1"
} }

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,37 @@
{ lib
, fetchFromGitHub
, buildPythonPackage
, nose
, pillow
, wheezy-captcha
}:
buildPythonPackage rec {
pname = "captcha";
version = "0.4";
format = "setuptools";
src = fetchFromGitHub {
owner = "lepture";
repo = pname;
rev = "v${version}";
hash = "sha256-uxUjoACN65Cx5LMKpT+bZhKpf2JRSaEyysnYUgZntp8=";
};
propagatedBuildInputs = [ pillow ];
pythonImportsCheck = [ "captcha" ];
nativeCheckInputs = [ nose wheezy-captcha ];
checkPhase = ''
nosetests -s
'';
meta = with lib; {
description = "A captcha library that generates audio and image CAPTCHAs";
homepage = "https://github.com/lepture/captcha";
license = licenses.bsd3;
maintainers = with maintainers; [ Flakebi ];
};
}

View file

@ -0,0 +1,38 @@
{ lib
, fetchFromGitHub
, buildPythonPackage
, flask
, flask-sessionstore
, flask-sqlalchemy
, captcha
, pytestCheckHook
}:
buildPythonPackage rec {
pname = "flask-session-captcha";
version = "1.3.0";
format = "setuptools";
src = fetchFromGitHub {
owner = "Tethik";
repo = pname;
rev = "v${version}";
hash = "sha256-V0f3mXCfqwH2l3OtJKOHGdrlKAFxs2ynqXvNve7Amkc=";
};
propagatedBuildInputs = [ flask flask-sessionstore captcha ];
pythonImportsCheck = [ "flask_session_captcha" ];
nativeCheckInputs = [ flask-sqlalchemy pytestCheckHook ];
# RuntimeError: Working outside of application context.
doCheck = false;
meta = with lib; {
description = "A captcha implemention for flask";
homepage = "https://github.com/Tethik/flask-session-captcha";
license = licenses.mit;
maintainers = with maintainers; [ Flakebi ];
};
}

View file

@ -0,0 +1,35 @@
{ lib
, fetchPypi
, buildPythonPackage
, flask
, nose
}:
buildPythonPackage rec {
pname = "flask-sessionstore";
version = "0.4.5";
format = "setuptools";
src = fetchPypi {
pname = "Flask-Sessionstore";
inherit version;
hash = "sha256-AQ3jWrnw2UI8L3nFEx4AhDwGP4R8Tr7iBMsDS5jLQPQ=";
};
propagatedBuildInputs = [ flask ];
pythonImportsCheck = [ "flask_sessionstore" ];
nativeCheckInputs = [ nose ];
checkPhase = ''
nosetests -s
'';
meta = with lib; {
description = "Session Storage Backends for Flask";
homepage = "https://github.com/mcrowson/flask-sessionstore";
license = licenses.bsd3;
maintainers = with maintainers; [ Flakebi ];
};
}

View file

@ -0,0 +1,27 @@
{ lib
, buildPythonPackage
, fetchPypi
, pillow
}:
buildPythonPackage rec {
pname = "wheezy.captcha";
version = "3.0.2";
format = "setuptools";
src = fetchPypi {
inherit pname version;
hash = "sha256-PdtOhoVOopQsX2raPqh0P8meM8/MysgKsIe27HNtl3s=";
};
propagatedBuildInputs = [ pillow ];
pythonImportsCheck = [ "wheezy.captcha" ];
meta = with lib; {
homepage = "https://wheezycaptcha.readthedocs.io/en/latest/";
description = "A lightweight CAPTCHA library";
license = licenses.mit;
maintainers = with maintainers; [ Flakebi ];
};
}

View file

@ -1623,6 +1623,8 @@ self: super: with self; {
inherit (pkgs) capstone; inherit (pkgs) capstone;
}; };
captcha = callPackage ../development/python-modules/captcha { };
capturer = callPackage ../development/python-modules/capturer { }; capturer = callPackage ../development/python-modules/capturer { };
carbon = callPackage ../development/python-modules/carbon { }; carbon = callPackage ../development/python-modules/carbon { };
@ -3679,6 +3681,10 @@ self: super: with self; {
flask-session = callPackage ../development/python-modules/flask-session { }; flask-session = callPackage ../development/python-modules/flask-session { };
flask-session-captcha = callPackage ../development/python-modules/flask-session-captcha { };
flask-sessionstore = callPackage ../development/python-modules/flask-sessionstore { };
flask-security-too = callPackage ../development/python-modules/flask-security-too { }; flask-security-too = callPackage ../development/python-modules/flask-security-too { };
flask-silk = callPackage ../development/python-modules/flask-silk { }; flask-silk = callPackage ../development/python-modules/flask-silk { };
@ -12929,6 +12935,8 @@ self: super: with self; {
wheel-inspect = callPackage ../development/python-modules/wheel-inspect { }; wheel-inspect = callPackage ../development/python-modules/wheel-inspect { };
wheezy-captcha = callPackage ../development/python-modules/wheezy-captcha { };
wheezy-template = callPackage ../development/python-modules/wheezy-template { }; wheezy-template = callPackage ../development/python-modules/wheezy-template { };
whichcraft = callPackage ../development/python-modules/whichcraft { }; whichcraft = callPackage ../development/python-modules/whichcraft { };