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;
serviceConfig = {
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";
ExecStop = "${pkgs.coreutils}/bin/kill -TERM $MAINPID";
PIDFile = "/run/powerdns-admin/pid";

View file

@ -10,6 +10,7 @@ let
defaultConfig = ''
BIND_ADDRESS = '127.0.0.1'
PORT = 8000
CAPTCHA_ENABLE = False
'';
makeAppTest = name: configs: makeTest {
@ -98,7 +99,30 @@ let
tcp = {
services.powerdns-admin.extraArgs = [ "-b" "127.0.0.1:8000" ];
system.build.testScript = ''
set -euxo pipefail
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 = {

View file

@ -1,53 +1,55 @@
{ lib, stdenv, fetchFromGitHub, mkYarnPackage, nixosTests, writeText, python3 }:
let
version = "0.3.0";
version = "0.4.1";
src = fetchFromGitHub {
owner = "ngoduykhanh";
owner = "PowerDNS-Admin";
repo = "PowerDNS-Admin";
rev = "v${version}";
hash = "sha256-e11u0jdJr+2TDXvBAPlDfnuuDwSfBq+JtvnDUTNKp/c=";
hash = "sha256-AwqEcAPD1SF1Ma3wtH03mXlTywM0Q19hciCmTtlr3gk=";
};
python = python3;
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
cffi configobj cryptography bcrypt requests python-ldap pyotp qrcode dnspython
gunicorn python3-saml pytz cssmin rjsmin authlib bravado-core
lima pytimeparse pyyaml jinja2 itsdangerous werkzeug
certifi cffi configobj cryptography bcrypt requests python-ldap pyotp qrcode dnspython
gunicorn itsdangerous python3-saml pytz rcssmin rjsmin authlib bravado-core
lima lxml passlib pyasn1 pytimeparse pyyaml jinja2 itsdangerous webcolors werkzeug zipp zxcvbn
];
assets = mkYarnPackage {
inherit src version;
packageJSON = ./package.json;
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;
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 = ''
# The build process expects the directory to be writable
# 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
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 = ''
# 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
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 \;
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";
};
@ -61,7 +63,7 @@ let
assets.register('js_main', 'generated/main.js')
assets.register('css_main', 'generated/main.css')
'';
in stdenv.mkDerivation rec {
in stdenv.mkDerivation {
pname = "powerdns-admin";
inherit src version;
@ -81,7 +83,13 @@ in stdenv.mkDerivation rec {
postPatch = ''
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 = ''
@ -113,7 +121,7 @@ in stdenv.mkDerivation rec {
meta = with lib; {
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;
maintainers = with maintainers; [ Flakebi zhaofengli ];
};

View file

@ -1,17 +1,24 @@
{
"dependencies": {
"admin-lte": "2.4.9",
"bootstrap": "^3.4.1",
"bootstrap-datepicker": "^1.8.0",
"@fortawesome/fontawesome-free": "6.3.0",
"admin-lte": "3.2.0",
"bootstrap": "4.6.2",
"bootstrap-datepicker": "^1.9.0",
"bootstrap-validator": "^0.11.9",
"datatables.net-plugins": "^1.10.19",
"datatables.net-plugins": "^1.13.1",
"icheck": "^1.0.2",
"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",
"jtimeout": "^3.1.0",
"jquery-validation": "^1.19.5",
"jtimeout": "^3.2.0",
"knockout": "^3.5.1",
"multiselect": "^0.9.12"
},
"resolutions": {
"admin-lte/@fortawesome/fontawesome-free": "6.3.0"
},
"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;
};
captcha = callPackage ../development/python-modules/captcha { };
capturer = callPackage ../development/python-modules/capturer { };
carbon = callPackage ../development/python-modules/carbon { };
@ -3679,6 +3681,10 @@ self: super: with self; {
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-silk = callPackage ../development/python-modules/flask-silk { };
@ -12929,6 +12935,8 @@ self: super: with self; {
wheel-inspect = callPackage ../development/python-modules/wheel-inspect { };
wheezy-captcha = callPackage ../development/python-modules/wheezy-captcha { };
wheezy-template = callPackage ../development/python-modules/wheezy-template { };
whichcraft = callPackage ../development/python-modules/whichcraft { };