1{ lib
2, python3
3, fetchFromGitHub
4, fetchYarnDeps
5, zlib
6, nixosTests
7, postgresqlTestHook
8, postgresql
9, yarn
10, fixup_yarn_lock
11, nodejs
12, server-mode ? true
13}:
14
15let
16 pname = "pgadmin";
17 version = "7.2";
18 yarnSha256 = "sha256-9iuD0cy0PEtx9Jc626LtE0sAOtP451TGlFKGtC8Tjs4=";
19
20 src = fetchFromGitHub {
21 owner = "pgadmin-org";
22 repo = "pgadmin4";
23 rev = "REL-${lib.versions.major version}_${lib.versions.minor version}";
24 hash = "sha256-RefEuP/Oh4X6knnIBnPrlITXFHbbL2U9yfvc4Ng6VJ4=";
25 };
26
27 # keep the scope, as it is used throughout the derivation and tests
28 # this also makes potential future overrides easier
29 pythonPackages = python3.pkgs.overrideScope (final: prev: rec { });
30
31 offlineCache = fetchYarnDeps {
32 yarnLock = ./yarn.lock;
33 hash = yarnSha256;
34 };
35
36in
37
38pythonPackages.buildPythonApplication rec {
39 inherit pname version src;
40
41 # from Dockerfile
42 CPPFLAGS = "-DPNG_ARM_NEON_OPT=0";
43
44 format = "setuptools";
45
46 patches = [
47 # Expose setup.py for later use
48 ./expose-setup.py.patch
49 # check for permission of /etc/pgadmin/config_system and don't fail
50 ./check-system-config-dir.patch
51 ];
52
53 postPatch = ''
54 # patching Makefile, so it doesn't try to build sphinx documentation here
55 # (will do so later)
56 substituteInPlace Makefile \
57 --replace 'LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 $(MAKE) -C docs/en_US -f Makefile.sphinx html' "true"
58
59 # fix document which refers a non-existing document and fails
60 substituteInPlace docs/en_US/contributions.rst \
61 --replace "code_snippets" ""
62 patchShebangs .
63
64 # relax dependencies
65 sed 's|==|>=|g' -i requirements.txt
66 #TODO: Can be removed once cryptography>=40 has been merged to master
67 substituteInPlace requirements.txt \
68 --replace "cryptography>=40.0.*" "cryptography>=39.0.*"
69 # fix extra_require error with "*" in match
70 sed 's|*|0|g' -i requirements.txt
71 substituteInPlace pkg/pip/setup_pip.py \
72 --replace "req = req.replace('psycopg[c]', 'psycopg[binary]')" "req = req"
73 ${lib.optionalString (!server-mode) ''
74 substituteInPlace web/config.py \
75 --replace "SERVER_MODE = True" "SERVER_MODE = False"
76 ''}
77 '';
78
79 preBuild = ''
80 # Adapted from pkg/pip/build.sh
81 echo Creating required directories...
82 mkdir -p pip-build/pgadmin4/docs
83
84 echo Building the documentation
85 cd docs/en_US
86 sphinx-build -W -b html -d _build/doctrees . _build/html
87
88 # Build the clean tree
89 cd ..
90 cp -r * ../pip-build/pgadmin4/docs
91 for DIR in `ls -d ??_??/`
92 do
93 if [ -d ''${DIR}_build/html ]; then
94 mkdir -p ../pip-build/pgadmin4/docs/''${DIR}_build
95 cp -R ''${DIR}_build/html ../pip-build/pgadmin4/docs/''${DIR}_build
96 fi
97 done
98 cd ../
99
100 # mkYarnModules and mkYarnPackage have problems running the webpacker
101 echo Building the web frontend...
102 cd web
103 export HOME="$TMPDIR"
104 yarn config --offline set yarn-offline-mirror "${offlineCache}"
105 # replace with converted yarn.lock file
106 rm yarn.lock
107 cp ${./yarn.lock} yarn.lock
108 chmod +w yarn.lock
109 fixup_yarn_lock yarn.lock
110 yarn install --offline --frozen-lockfile --ignore-platform --ignore-scripts --no-progress --non-interactive
111 patchShebangs node_modules/
112 yarn webpacker
113 cp -r * ../pip-build/pgadmin4
114 # save some disk space
115 rm -rf ../pip-build/pgadmin4/node_modules
116
117 cd ..
118
119 echo Creating distro config...
120 echo HELP_PATH = \'../../docs/en_US/_build/html/\' > pip-build/pgadmin4/config_distro.py
121 echo MINIFY_HTML = False >> pip-build/pgadmin4/config_distro.py
122
123 echo Creating manifest...
124 echo recursive-include pgadmin4 \* > pip-build/MANIFEST.in
125
126 echo Building wheel...
127 cd pip-build
128 # copy non-standard setup.py to local directory
129 # so setuptools-build-hook can call it
130 cp -v ../pkg/pip/setup_pip.py setup.py
131 '';
132
133 nativeBuildInputs = with pythonPackages; [ cython pip sphinx yarn fixup_yarn_lock nodejs ];
134 buildInputs = [
135 zlib
136 pythonPackages.wheel
137 ];
138
139 propagatedBuildInputs = with pythonPackages; [
140 flask
141 flask-gravatar
142 flask-login
143 flask_mail
144 flask_migrate
145 flask-sqlalchemy
146 flask-wtf
147 flask-compress
148 passlib
149 pytz
150 simplejson
151 sqlparse
152 wtforms
153 flask-paranoid
154 psutil
155 psycopg
156 python-dateutil
157 sqlalchemy
158 itsdangerous
159 flask-security-too
160 bcrypt
161 cryptography
162 sshtunnel
163 ldap3
164 flask-babelex
165 flask-babel
166 gssapi
167 flask-socketio
168 eventlet
169 httpagentparser
170 user-agents
171 wheel
172 authlib
173 qrcode
174 pillow
175 pyotp
176 botocore
177 boto3
178 azure-mgmt-subscription
179 azure-mgmt-rdbms
180 azure-mgmt-resource
181 azure-identity
182 sphinxcontrib-youtube
183 dnspython
184 greenlet
185 speaklater3
186 google-auth-oauthlib
187 google-api-python-client
188 keyring
189 ];
190
191 passthru.tests = {
192 inherit (nixosTests) pgadmin4;
193 };
194
195 nativeCheckInputs = [
196 postgresqlTestHook
197 postgresql
198 pythonPackages.testscenarios
199 pythonPackages.selenium
200 ];
201
202 checkPhase = ''
203 runHook preCheck
204
205 ## Setup ##
206
207 # pgadmin needs a home directory to save the configuration
208 export HOME=$TMPDIR
209 cd pgadmin4
210
211 # set configuration for postgresql test
212 # also ensure Server Mode is set to false. If not, the tests will fail, since pgadmin expects read/write permissions
213 # in /var/lib/pgadmin and /var/log/pgadmin
214 # see https://github.com/pgadmin-org/pgadmin4/blob/fd1c26408bbf154fa455a49ee5c12895933833a3/web/regression/runtests.py#L217-L226
215 cp -v regression/test_config.json.in regression/test_config.json
216 substituteInPlace regression/test_config.json --replace "localhost" "$PGHOST"
217 substituteInPlace regression/runtests.py --replace "builtins.SERVER_MODE = None" "builtins.SERVER_MODE = False"
218
219 ## Browser test ##
220
221 # don't bother to test kerberos authentication
222 python regression/runtests.py --pkg browser --exclude browser.tests.test_kerberos_with_mocking
223
224 ## Reverse engineered SQL test ##
225
226 python regression/runtests.py --pkg resql
227
228 runHook postCheck
229 '';
230
231 meta = with lib; {
232 description = "Administration and development platform for PostgreSQL${optionalString (!server-mode) ". Desktop Mode"}";
233 longDescription = ''
234 pgAdmin 4 is designed to meet the needs of both novice and experienced Postgres users alike,
235 providing a powerful graphical interface that simplifies the creation, maintenance and use of database objects.
236 ${if server-mode then ''
237 This version is build with SERVER_MODE set to True (the default). It will require access to `/var/lib/pgadmin`
238 and `/var/log/pgadmin`. This is the default version for the NixOS module `services.pgadmin`.
239 This should NOT be used in combination with the `pgadmin4-desktopmode` package as they will interfere.
240 '' else ''
241 This version is build with SERVER_MODE set to False. It will require access to `~/.pgadmin/`. This version is suitable
242 for single-user deployment or where access to `/var/lib/pgadmin` cannot be granted or the NixOS module cannot be used.
243 This should NOT be used in combination with the NixOS module `pgadmin` as they will interfere.
244 ''}
245 '';
246 homepage = "https://www.pgadmin.org/";
247 license = licenses.mit;
248 changelog = "https://www.pgadmin.org/docs/pgadmin4/latest/release_notes_${lib.versions.major version}_${lib.versions.minor version}.html";
249 maintainers = with maintainers; [ gador ];
250 mainProgram = "pgadmin4";
251 };
252}