about summary refs log tree commit diff
path: root/pkgs/applications/networking/powerdns-admin/default.nix
blob: 731e0873f68140923bd6ab5f1912bb36d3b03b25 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
{ lib, stdenv, fetchFromGitHub, mkYarnPackage, nixosTests, writeText, python3 }:

let
  version = "0.3.0";
  src = fetchFromGitHub {
    owner = "ngoduykhanh";
    repo = "PowerDNS-Admin";
    rev = "v${version}";
    hash = "sha256-e11u0jdJr+2TDXvBAPlDfnuuDwSfBq+JtvnDUTNKp/c=";
  };

  python = python3.override {
    packageOverrides = self: super: {
      # The bravado-core dependency is incompatible with jschonschema 4.0:
      # https://github.com/Yelp/bravado-core/pull/385
      jsonschema = super.jsonschema.overridePythonAttrs (oldAttrs: rec {
        version = "3.2.0";

        src = oldAttrs.src.override {
          inherit version;
          hash = "sha256-yKhbKNN3zHc35G4tnytPRO48Dh3qxr9G3e/HGH0weXo=";
          sha256 = "";
        };

        SETUPTOOLS_SCM_PRETEND_VERSION = version;

        doCheck = false;
      });
    };
  };

  pythonDeps = with python.pkgs; [
    flask flask_assets flask_login flask_sqlalchemy flask_migrate flask-seasurf flask_mail flask-session flask-sslify
    mysqlclient psycopg2 sqlalchemy
    cffi configobj cryptography bcrypt requests ldap pyotp qrcode dnspython
    gunicorn python3-saml pytz cssmin rjsmin authlib bravado-core
    lima pytimeparse pyyaml jinja2 itsdangerous werkzeug
  ];

  assets = mkYarnPackage {
    inherit src version;
    packageJSON = ./package.json;
    yarnNix = ./yarndeps.nix;

    nativeBuildInputs = pythonDeps;
    patchPhase = ''
      sed -i -r -e "s|'cssmin',\s?'cssrewrite'|'cssmin'|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

      approot=deps/powerdns-admin-assets

      ln -s $node_modules $approot/powerdnsadmin/static/node_modules
      FLASK_APP=$approot/powerdnsadmin/__init__.py flask assets build
    '';
    installPhase = ''
      # https://github.com/ngoduykhanh/PowerDNS-Admin/blob/54b257768f600c5548a1c7e50eac49c40df49f92/docker/Dockerfile#L43
      mkdir $out
      cp -r $approot/powerdnsadmin/static/{generated,assets,img} $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";
  };

  assetsPy = writeText "assets.py" ''
    from flask_assets import Environment
    assets = Environment()
    assets.register('js_login', 'generated/login.js')
    assets.register('js_validation', 'generated/validation.js')
    assets.register('css_login', 'generated/login.css')
    assets.register('js_main', 'generated/main.js')
    assets.register('css_main', 'generated/main.css')
  '';
in stdenv.mkDerivation rec {
  pname = "powerdns-admin";

  inherit src version;

  nativeBuildInputs = [ python.pkgs.wrapPython ];

  pythonPath = pythonDeps;

  gunicornScript = ''
    #!/bin/sh
    if [ ! -z $CONFIG ]; then
      exec python -m gunicorn.app.wsgiapp "powerdnsadmin:create_app(config='$CONFIG')" "$@"
    fi

    exec python -m gunicorn.app.wsgiapp "powerdnsadmin:create_app()" "$@"
  '';

  postPatch = ''
    rm -r powerdnsadmin/static powerdnsadmin/assets.py
    sed -i "s/id:/'id':/" migrations/versions/787bdba9e147_init_db.py
  '';

  installPhase = ''
    runHook preInstall

    # Nasty hack: call wrapPythonPrograms to set program_PYTHONPATH (see tribler)
    wrapPythonPrograms

    mkdir -p $out/share $out/bin
    cp -r migrations powerdnsadmin $out/share/

    ln -s ${assets} $out/share/powerdnsadmin/static
    ln -s ${assetsPy} $out/share/powerdnsadmin/assets.py

    echo "$gunicornScript" > $out/bin/powerdns-admin
    chmod +x $out/bin/powerdns-admin
    wrapProgram $out/bin/powerdns-admin \
      --set PATH ${python.pkgs.python}/bin \
      --set PYTHONPATH $out/share:$program_PYTHONPATH

    runHook postInstall
  '';

  passthru = {
    # PYTHONPATH of all dependencies used by the package
    pythonPath = python3.pkgs.makePythonPath pythonDeps;
    tests = nixosTests.powerdns-admin;
  };

  meta = with lib; {
    description = "A PowerDNS web interface with advanced features";
    homepage = "https://github.com/ngoduykhanh/PowerDNS-Admin";
    license = licenses.mit;
    maintainers = with maintainers; [ Flakebi zhaofengli ];
  };
}