mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-09-28 10:50:15 +00:00
powerdns-admin: 0.4.2 -> 0.6.1 (#549053)
This commit is contained in:
@@ -132,13 +132,13 @@ let
|
||||
|
||||
# Login
|
||||
# Outputs 'Redirecting' if successful
|
||||
curl -sSfb session http://127.0.0.1:8000/login \
|
||||
curl -sSf -b session -c 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
|
||||
curl -sSf -b session -c session http://127.0.0.1:8000/dashboard/ | grep /admin/setting
|
||||
'';
|
||||
};
|
||||
unix = {
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
From 29b58e29c813d9bf0b31139a19b556614c28638e Mon Sep 17 00:00:00 2001
|
||||
From: Flakebi <flakebi@t-online.de>
|
||||
Date: Sat, 2 Dec 2023 16:26:22 +0100
|
||||
Subject: [PATCH 1/6] Fix flask 2.3 issue
|
||||
|
||||
'Blueprint' object has no attribute 'before_app_first_request'
|
||||
---
|
||||
powerdnsadmin/routes/index.py | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/powerdnsadmin/routes/index.py b/powerdnsadmin/routes/index.py
|
||||
index d56ce61..2176bd6 100644
|
||||
--- a/powerdnsadmin/routes/index.py
|
||||
+++ b/powerdnsadmin/routes/index.py
|
||||
@@ -46,7 +46,6 @@ index_bp = Blueprint('index',
|
||||
url_prefix='/')
|
||||
|
||||
|
||||
-@index_bp.before_app_first_request
|
||||
def register_modules():
|
||||
global google
|
||||
global github
|
||||
--
|
||||
2.42.0
|
||||
|
||||
@@ -1,34 +1,25 @@
|
||||
From c60a9658fe2ca429327680fbffb86f609d98c52c Mon Sep 17 00:00:00 2001
|
||||
From: Flakebi <flakebi@t-online.de>
|
||||
Date: Sat, 2 Dec 2023 16:27:49 +0100
|
||||
Subject: [PATCH 2/6] Remove cssrewrite filter
|
||||
|
||||
---
|
||||
powerdnsadmin/assets.py | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/powerdnsadmin/assets.py b/powerdnsadmin/assets.py
|
||||
index d46d431..3c582be 100644
|
||||
index b339c0e..6cf8087 100644
|
||||
--- a/powerdnsadmin/assets.py
|
||||
+++ b/powerdnsadmin/assets.py
|
||||
@@ -13,7 +13,7 @@ css_login = Bundle(
|
||||
@@ -50,7 +50,7 @@ class ModernBrowserCssFilter(Filter):
|
||||
css_login = Bundle(
|
||||
'node_modules/@fortawesome/fontawesome-free/css/all.css',
|
||||
'node_modules/icheck/skins/square/blue.css',
|
||||
'node_modules/admin-lte/dist/css/adminlte.css',
|
||||
- filters=('rcssmin', 'cssrewrite'),
|
||||
+ filters=('rcssmin'),
|
||||
- filters=(ModernBrowserCssFilter, 'rcssmin', 'cssrewrite'),
|
||||
+ filters=(ModernBrowserCssFilter, 'rcssmin'),
|
||||
output='generated/login.css')
|
||||
|
||||
js_login = Bundle(
|
||||
@@ -37,7 +37,7 @@ css_main = Bundle(
|
||||
@@ -66,7 +66,7 @@ css_main = Bundle(
|
||||
'node_modules/admin-lte/dist/css/adminlte.css',
|
||||
'node_modules/datatables.net-bs5/css/dataTables.bootstrap5.css',
|
||||
'custom/css/custom.css',
|
||||
'node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker.css',
|
||||
- filters=('rcssmin', 'cssrewrite'),
|
||||
+ filters=('rcssmin'),
|
||||
- filters=(ModernBrowserCssFilter, 'rcssmin', 'cssrewrite'),
|
||||
+ filters=(ModernBrowserCssFilter, 'rcssmin'),
|
||||
output='generated/main.css')
|
||||
|
||||
js_main = Bundle(
|
||||
--
|
||||
2.42.0
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
From 8c320a34bcca6dc2c1b423a1445235bf178b653e Mon Sep 17 00:00:00 2001
|
||||
From: Flakebi <flakebi@t-online.de>
|
||||
Date: Sat, 2 Dec 2023 16:31:02 +0100
|
||||
Subject: [PATCH 3/6] Fix flask-migrate 4.0 compatibility
|
||||
|
||||
See https://github.com/PowerDNS-Admin/PowerDNS-Admin/issues/1376
|
||||
---
|
||||
migrations/env.py | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/migrations/env.py b/migrations/env.py
|
||||
index 4742e14..739d753 100755
|
||||
--- a/migrations/env.py
|
||||
+++ b/migrations/env.py
|
||||
@@ -73,7 +73,6 @@ def run_migrations_online():
|
||||
context.configure(connection=connection,
|
||||
target_metadata=target_metadata,
|
||||
process_revision_directives=process_revision_directives,
|
||||
- render_as_batch=config.get_main_option('sqlalchemy.url').startswith('sqlite:'),
|
||||
**current_app.extensions['migrate'].configure_args)
|
||||
|
||||
try:
|
||||
--
|
||||
2.42.0
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
From 4b4ac26ef1cbb0b5b2354c251b216498325d0411 Mon Sep 17 00:00:00 2001
|
||||
From: Flakebi <flakebi@t-online.de>
|
||||
Date: Sat, 2 Dec 2023 16:31:50 +0100
|
||||
Subject: [PATCH 4/6] Fix flask-session and powerdns-admin compatibility
|
||||
|
||||
flask-session and powerdns-admin both try to add sqlalchemy to flask.
|
||||
Reuse the database for flask-session.
|
||||
---
|
||||
powerdnsadmin/__init__.py | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/powerdnsadmin/__init__.py b/powerdnsadmin/__init__.py
|
||||
index d447a00..653af33 100755
|
||||
--- a/powerdnsadmin/__init__.py
|
||||
+++ b/powerdnsadmin/__init__.py
|
||||
@@ -60,6 +60,7 @@ def create_app(config=None):
|
||||
if 'SESSION_TYPE' in os.environ:
|
||||
app.config['SESSION_TYPE'] = os.environ.get('SESSION_TYPE')
|
||||
|
||||
+ app.config['SESSION_SQLALCHEMY'] = models.base.db
|
||||
sess = Session(app)
|
||||
|
||||
# create sessions table if using sqlalchemy backend
|
||||
--
|
||||
2.42.0
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
diff --git a/powerdnsadmin/__init__.py b/powerdnsadmin/__init__.py
|
||||
index 660f96b..4d45c36 100755
|
||||
--- a/powerdnsadmin/__init__.py
|
||||
+++ b/powerdnsadmin/__init__.py
|
||||
@@ -72,10 +72,16 @@ def create_app(config=None):
|
||||
# SMTP
|
||||
app.mail = Mail(app)
|
||||
|
||||
+ from powerdnsadmin.routes.index import register_modules
|
||||
+
|
||||
# Load app's components
|
||||
assets.init_app(app)
|
||||
models.init_app(app)
|
||||
- routes.init_app(app)
|
||||
+
|
||||
+ with app.app_context():
|
||||
+ register_modules()
|
||||
+ routes.init_app(app)
|
||||
+
|
||||
services.init_app(app)
|
||||
|
||||
# Register filters
|
||||
diff --git a/powerdnsadmin/routes/index.py b/powerdnsadmin/routes/index.py
|
||||
index 0918261..870d824 100644
|
||||
--- a/powerdnsadmin/routes/index.py
|
||||
+++ b/powerdnsadmin/routes/index.py
|
||||
@@ -52,11 +52,16 @@ def register_modules():
|
||||
global azure
|
||||
global oidc
|
||||
global saml
|
||||
- google = google_oauth()
|
||||
- github = github_oauth()
|
||||
- azure = azure_oauth()
|
||||
- oidc = oidc_oauth()
|
||||
- saml = SAML()
|
||||
+
|
||||
+ try:
|
||||
+ google = google_oauth()
|
||||
+ github = github_oauth()
|
||||
+ azure = azure_oauth()
|
||||
+ oidc = oidc_oauth()
|
||||
+ saml = SAML()
|
||||
+ except Exception:
|
||||
+ # Database not ready yet, will initialize on first request
|
||||
+ pass
|
||||
|
||||
|
||||
@index_bp.before_request
|
||||
@@ -65,6 +70,9 @@ def before_request():
|
||||
g.user = current_user
|
||||
login_manager.anonymous_user = Anonymous
|
||||
|
||||
+ if google is None:
|
||||
+ register_modules()
|
||||
+
|
||||
# Check site is in maintenance mode
|
||||
maintenance = Setting().get('maintenance')
|
||||
if maintenance and current_user.is_authenticated and current_user.role.name not in [
|
||||
@@ -1,46 +0,0 @@
|
||||
diff --git a/powerdnsadmin/lib/utils.py b/powerdnsadmin/lib/utils.py
|
||||
index f8cc997..0de4c5c 100644
|
||||
--- a/powerdnsadmin/lib/utils.py
|
||||
+++ b/powerdnsadmin/lib/utils.py
|
||||
@@ -121,7 +121,7 @@ def display_record_name(data):
|
||||
if record_name == domain_name:
|
||||
return '@'
|
||||
else:
|
||||
- return re.sub('\.{}$'.format(domain_name), '', record_name)
|
||||
+ return re.sub(r'\.{}$'.format(domain_name), '', record_name)
|
||||
|
||||
|
||||
def display_master_name(data):
|
||||
diff --git a/powerdnsadmin/models/domain.py b/powerdnsadmin/models/domain.py
|
||||
index f0b9a30..84c6d1b 100644
|
||||
--- a/powerdnsadmin/models/domain.py
|
||||
+++ b/powerdnsadmin/models/domain.py
|
||||
@@ -482,24 +482,24 @@ class Domain(db.Model):
|
||||
if re.search('ip6.arpa', reverse_host_address):
|
||||
for i in range(1, 32, 1):
|
||||
address = re.search(
|
||||
- '((([a-f0-9]\.){' + str(i) + '})(?P<ipname>.+6.arpa)\.?)',
|
||||
+ r'((([a-f0-9]\.){' + str(i) + r'})(?P<ipname>.+6\.arpa)\.?)',
|
||||
reverse_host_address)
|
||||
if None != self.get_id_by_name(address.group('ipname')):
|
||||
c = i
|
||||
break
|
||||
return re.search(
|
||||
- '((([a-f0-9]\.){' + str(c) + '})(?P<ipname>.+6.arpa)\.?)',
|
||||
+ r'((([a-f0-9]\.){' + str(c) + r'})(?P<ipname>.+6\.arpa)\.?)',
|
||||
reverse_host_address).group('ipname')
|
||||
else:
|
||||
for i in range(1, 4, 1):
|
||||
address = re.search(
|
||||
- '((([0-9]+\.){' + str(i) + '})(?P<ipname>.+r.arpa)\.?)',
|
||||
+ r'((([0-9]+\.){' + str(i) + r'})(?P<ipname>.+r\.arpa)\.?)',
|
||||
reverse_host_address)
|
||||
if None != self.get_id_by_name(address.group('ipname')):
|
||||
c = i
|
||||
break
|
||||
return re.search(
|
||||
- '((([0-9]+\.){' + str(c) + '})(?P<ipname>.+r.arpa)\.?)',
|
||||
+ r'((([0-9]+\.){' + str(c) + r'})(?P<ipname>.+r\.arpa)\.?)',
|
||||
reverse_host_address).group('ipname')
|
||||
|
||||
def delete(self, domain_name):
|
||||
@@ -1,48 +0,0 @@
|
||||
diff --git a/powerdnsadmin/routes/index.py b/powerdnsadmin/routes/index.py
|
||||
index 23d88bb..edfab3f 100644
|
||||
--- a/powerdnsadmin/routes/index.py
|
||||
+++ b/powerdnsadmin/routes/index.py
|
||||
@@ -392,11 +392,38 @@ def login():
|
||||
return authenticate_user(user, 'Azure OAuth')
|
||||
|
||||
if 'oidc_token' in session:
|
||||
- user_data = json.loads(oidc.get('userinfo').text)
|
||||
- oidc_username = user_data[Setting().get('oidc_oauth_username')]
|
||||
- oidc_first_name = user_data[Setting().get('oidc_oauth_firstname')]
|
||||
- oidc_last_name = user_data[Setting().get('oidc_oauth_last_name')]
|
||||
- oidc_email = user_data[Setting().get('oidc_oauth_email')]
|
||||
+ try:
|
||||
+ oidc_metadata = oidc.load_server_metadata()
|
||||
+ except Exception as e:
|
||||
+ current_app.logger.warning(
|
||||
+ 'OIDC: unable to load server metadata ({}); '
|
||||
+ 'falling back to relative userinfo endpoint'.format(e))
|
||||
+ oidc_metadata = {}
|
||||
+
|
||||
+ userinfo_endpoint = oidc_metadata.get('userinfo_endpoint')
|
||||
+ try:
|
||||
+ if userinfo_endpoint:
|
||||
+ userinfo_resp = oidc.get(userinfo_endpoint, timeout=15)
|
||||
+ else:
|
||||
+ userinfo_resp = oidc.get('userinfo', timeout=15)
|
||||
+ userinfo_resp.raise_for_status()
|
||||
+ user_data = userinfo_resp.json()
|
||||
+ except Exception as e:
|
||||
+ current_app.logger.error('OIDC: failed to fetch userinfo: {}'.format(e))
|
||||
+ session.pop('oidc_token', None)
|
||||
+ return redirect(url_for('index.login'))
|
||||
+
|
||||
+ oidc_username = user_data.get(Setting().get('oidc_oauth_username'))
|
||||
+ oidc_first_name = user_data.get(Setting().get('oidc_oauth_firstname'), '')
|
||||
+ oidc_last_name = user_data.get(Setting().get('oidc_oauth_last_name'), '')
|
||||
+ oidc_email = user_data.get(Setting().get('oidc_oauth_email'), '')
|
||||
+
|
||||
+ if not oidc_username:
|
||||
+ current_app.logger.error(
|
||||
+ 'OIDC: username claim "{}" not present in userinfo'.format(
|
||||
+ Setting().get('oidc_oauth_username')))
|
||||
+ session.pop('oidc_token', None)
|
||||
+ return redirect(url_for('index.login'))
|
||||
|
||||
user = User.query.filter_by(username=oidc_username).first()
|
||||
if not user:
|
||||
@@ -1,30 +0,0 @@
|
||||
diff --git a/powerdnsadmin/models/user.py b/powerdnsadmin/models/user.py
|
||||
index 42f894f..f9d845e 100644
|
||||
--- a/powerdnsadmin/models/user.py
|
||||
+++ b/powerdnsadmin/models/user.py
|
||||
@@ -435,7 +435,7 @@ class User(db.Model):
|
||||
name='Administrator').first().id
|
||||
|
||||
if hasattr(self, "plain_text_password"):
|
||||
- if self.plain_text_password != None:
|
||||
+ if self.plain_text_password:
|
||||
self.password = self.get_hashed_password(
|
||||
self.plain_text_password)
|
||||
else:
|
||||
@@ -476,7 +476,7 @@ class User(db.Model):
|
||||
|
||||
# store new password hash (only if changed)
|
||||
if hasattr(self, "plain_text_password"):
|
||||
- if self.plain_text_password != None:
|
||||
+ if self.plain_text_password:
|
||||
user.password = self.get_hashed_password(
|
||||
self.plain_text_password).decode("utf-8")
|
||||
|
||||
@@ -495,7 +495,7 @@ class User(db.Model):
|
||||
user.lastname = self.lastname if self.lastname else user.lastname
|
||||
|
||||
if hasattr(self, "plain_text_password"):
|
||||
- if self.plain_text_password != None:
|
||||
+ if self.plain_text_password:
|
||||
user.password = self.get_hashed_password(
|
||||
self.plain_text_password).decode("utf-8")
|
||||
@@ -2,23 +2,29 @@
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
fetchYarnDeps,
|
||||
yarnConfigHook,
|
||||
yarn-berry_4-fetcher,
|
||||
nixosTests,
|
||||
writeText,
|
||||
runCommand,
|
||||
python3,
|
||||
}:
|
||||
|
||||
let
|
||||
pname = "powerdns-admin";
|
||||
version = "0.4.2";
|
||||
version = "0.6.1";
|
||||
src = fetchFromGitHub {
|
||||
owner = "PowerDNS-Admin";
|
||||
repo = "PowerDNS-Admin";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-q9mt8wjSNFb452Xsg+qhNOWa03KJkYVGAeCWVSzZCyk=";
|
||||
hash = "sha256-VhUz3Uw2MKN7rJgCrFd5nSN8FVTHM6LHCc01scMNjbc=";
|
||||
};
|
||||
|
||||
inherit (yarn-berry_4-fetcher) fetchYarnBerryDeps yarnBerryConfigHook;
|
||||
|
||||
yarnLock = runCommand "yarn-v9.lock" { } ''
|
||||
sed -e 's/^ version: 8$/ version: 9/' ${src}/yarn.lock > $out
|
||||
'';
|
||||
|
||||
python = python3;
|
||||
|
||||
pythonDeps = with python.pkgs; [
|
||||
@@ -69,36 +75,50 @@ let
|
||||
standard-imghdr
|
||||
];
|
||||
|
||||
all_patches = [
|
||||
./0001-Fix-flask-2.3-issue.patch
|
||||
];
|
||||
|
||||
assets = stdenv.mkDerivation {
|
||||
pname = "${pname}-assets";
|
||||
inherit version src;
|
||||
|
||||
offlineCache = fetchYarnDeps {
|
||||
yarnLock = "${src}/yarn.lock";
|
||||
hash = "sha256-rXIts+dgOuZQGyiSke1NIG7b4lFlR/Gfu3J6T3wP3aY=";
|
||||
offlineCache = fetchYarnBerryDeps {
|
||||
inherit yarnLock;
|
||||
hash = "sha256-VVew6/rjc0Uz6xM2komL9Sceym3vFrGnAqrdLtGxQVI=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
cp ${yarnLock} yarn.lock
|
||||
# flask-assets needs a real node_modules tree
|
||||
printf 'nodeLinker: node-modules\n' >> .yarnrc.yml
|
||||
'';
|
||||
|
||||
nativeBuildInputs = [
|
||||
yarnConfigHook
|
||||
yarnBerryConfigHook
|
||||
]
|
||||
++ pythonDeps;
|
||||
patches = all_patches ++ [
|
||||
|
||||
patches = [
|
||||
./0002-Remove-cssrewrite-filter.patch
|
||||
];
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
if [ -d node_modules ] && [ ! -d powerdnsadmin/static/node_modules ]; then
|
||||
mv node_modules powerdnsadmin/static/node_modules
|
||||
fi
|
||||
|
||||
SESSION_TYPE=filesystem FLASK_APP=./powerdnsadmin/__init__.py flask assets build
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
# https://github.com/PowerDNS-Admin/PowerDNS-Admin/blob/54b257768f600c5548a1c7e50eac49c40df49f92/docker/Dockerfile#L43
|
||||
mkdir $out
|
||||
cp -r powerdnsadmin/static/{generated,assets,img} $out
|
||||
find powerdnsadmin/static/node_modules -name webfonts -exec cp -r {} $out \; -printf "Copying %P\n"
|
||||
find powerdnsadmin/static/node_modules -name fonts -exec cp -r {} $out \; -printf "Copying %P\n"
|
||||
find powerdnsadmin/static/node_modules/icheck/skins/square -name '*.png' -exec cp {} $out/generated \;
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -128,15 +148,6 @@ stdenv.mkDerivation {
|
||||
exec python -m gunicorn.app.wsgiapp "powerdnsadmin:create_app()" "$@"
|
||||
'';
|
||||
|
||||
patches = all_patches ++ [
|
||||
./0003-Fix-flask-migrate-4.0-compatibility.patch
|
||||
./0004-Fix-flask-session-and-powerdns-admin-compatibility.patch
|
||||
./0005-Fix-app-context-and-register-modules.patch
|
||||
./0006-Fix-regex.patch
|
||||
./0007-Fix-oidc.patch
|
||||
./0008-Fix-profile-save-overwriting-password-with-empty-val.patch
|
||||
];
|
||||
|
||||
postPatch = ''
|
||||
rm -r powerdnsadmin/static powerdnsadmin/assets.py
|
||||
'';
|
||||
@@ -162,6 +173,8 @@ stdenv.mkDerivation {
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
__darwinAllowLocalNetworking = true;
|
||||
|
||||
passthru = {
|
||||
# PYTHONPATH of all dependencies used by the package
|
||||
pythonPath = python3.pkgs.makePythonPath pythonDeps;
|
||||
|
||||
Reference in New Issue
Block a user