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.5";
18 yarnSha256 = "sha256-rEKMUZksmR2jPwtXy6drNwAJktK/3Dee6EZVFHPngWs=";
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-o8jPqp4jLF/lZ0frCzPDCSxCy51Nt0mbdeNB44ZwNHI=";
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 boto3>=1.28.0 and cryptography>=41 has been merged to master
67 substituteInPlace requirements.txt \
68 --replace "boto3>=1.28.*" "boto3>=1.26.*"
69 substituteInPlace requirements.txt \
70 --replace "botocore>=1.31.*" "botocore>=1.29.*"
71 substituteInPlace requirements.txt \
72 --replace "cryptography>=41.0.*" "cryptography>=40.0.*"
73 # fix extra_require error with "*" in match
74 sed 's|*|0|g' -i requirements.txt
75 substituteInPlace pkg/pip/setup_pip.py \
76 --replace "req = req.replace('psycopg[c]', 'psycopg[binary]')" "req = req"
77 ${lib.optionalString (!server-mode) ''
78 substituteInPlace web/config.py \
79 --replace "SERVER_MODE = True" "SERVER_MODE = False"
80 ''}
81 '';
82
83 preBuild = ''
84 # Adapted from pkg/pip/build.sh
85 echo Creating required directories...
86 mkdir -p pip-build/pgadmin4/docs
87
88 echo Building the documentation
89 cd docs/en_US
90 sphinx-build -W -b html -d _build/doctrees . _build/html
91
92 # Build the clean tree
93 cd ..
94 cp -r * ../pip-build/pgadmin4/docs
95 for DIR in `ls -d ??_??/`
96 do
97 if [ -d ''${DIR}_build/html ]; then
98 mkdir -p ../pip-build/pgadmin4/docs/''${DIR}_build
99 cp -R ''${DIR}_build/html ../pip-build/pgadmin4/docs/''${DIR}_build
100 fi
101 done
102 cd ../
103
104 # mkYarnModules and mkYarnPackage have problems running the webpacker
105 echo Building the web frontend...
106 cd web
107 export HOME="$TMPDIR"
108 yarn config --offline set yarn-offline-mirror "${offlineCache}"
109 # replace with converted yarn.lock file
110 rm yarn.lock
111 cp ${./yarn.lock} yarn.lock
112 chmod +w yarn.lock
113 fixup_yarn_lock yarn.lock
114 yarn install --offline --frozen-lockfile --ignore-platform --ignore-scripts --no-progress --non-interactive
115 patchShebangs node_modules/
116 yarn webpacker
117 cp -r * ../pip-build/pgadmin4
118 # save some disk space
119 rm -rf ../pip-build/pgadmin4/node_modules
120
121 cd ..
122
123 echo Creating distro config...
124 echo HELP_PATH = \'../../docs/en_US/_build/html/\' > pip-build/pgadmin4/config_distro.py
125 echo MINIFY_HTML = False >> pip-build/pgadmin4/config_distro.py
126
127 echo Creating manifest...
128 echo recursive-include pgadmin4 \* > pip-build/MANIFEST.in
129
130 echo Building wheel...
131 cd pip-build
132 # copy non-standard setup.py to local directory
133 # so setuptools-build-hook can call it
134 cp -v ../pkg/pip/setup_pip.py setup.py
135 '';
136
137 nativeBuildInputs = with pythonPackages; [ cython pip sphinx yarn fixup_yarn_lock nodejs ];
138 buildInputs = [
139 zlib
140 pythonPackages.wheel
141 ];
142
143 propagatedBuildInputs = with pythonPackages; [
144 flask
145 flask-gravatar
146 flask-login
147 flask-mail
148 flask-migrate
149 flask-sqlalchemy
150 flask-wtf
151 flask-compress
152 passlib
153 pytz
154 simplejson
155 sqlparse
156 wtforms
157 flask-paranoid
158 psutil
159 psycopg
160 python-dateutil
161 sqlalchemy
162 itsdangerous
163 flask-security-too
164 bcrypt
165 cryptography
166 sshtunnel
167 ldap3
168 flask-babelex
169 flask-babel
170 gssapi
171 flask-socketio
172 eventlet
173 httpagentparser
174 user-agents
175 wheel
176 authlib
177 qrcode
178 pillow
179 pyotp
180 botocore
181 boto3
182 azure-mgmt-subscription
183 azure-mgmt-rdbms
184 azure-mgmt-resource
185 azure-identity
186 sphinxcontrib-youtube
187 dnspython
188 greenlet
189 speaklater3
190 google-auth-oauthlib
191 google-api-python-client
192 keyring
193 ];
194
195 passthru.tests = {
196 inherit (nixosTests) pgadmin4;
197 };
198
199 nativeCheckInputs = [
200 postgresqlTestHook
201 postgresql
202 pythonPackages.testscenarios
203 pythonPackages.selenium
204 ];
205
206 checkPhase = ''
207 runHook preCheck
208
209 ## Setup ##
210
211 # pgadmin needs a home directory to save the configuration
212 export HOME=$TMPDIR
213 cd pgadmin4
214
215 # set configuration for postgresql test
216 # also ensure Server Mode is set to false. If not, the tests will fail, since pgadmin expects read/write permissions
217 # in /var/lib/pgadmin and /var/log/pgadmin
218 # see https://github.com/pgadmin-org/pgadmin4/blob/fd1c26408bbf154fa455a49ee5c12895933833a3/web/regression/runtests.py#L217-L226
219 cp -v regression/test_config.json.in regression/test_config.json
220 substituteInPlace regression/test_config.json --replace "localhost" "$PGHOST"
221 substituteInPlace regression/runtests.py --replace "builtins.SERVER_MODE = None" "builtins.SERVER_MODE = False"
222
223 ## Browser test ##
224
225 # don't bother to test kerberos authentication
226 python regression/runtests.py --pkg browser --exclude browser.tests.test_kerberos_with_mocking
227
228 ## Reverse engineered SQL test ##
229
230 python regression/runtests.py --pkg resql
231
232 runHook postCheck
233 '';
234
235 meta = with lib; {
236 description = "Administration and development platform for PostgreSQL${optionalString (!server-mode) ". Desktop Mode"}";
237 longDescription = ''
238 pgAdmin 4 is designed to meet the needs of both novice and experienced Postgres users alike,
239 providing a powerful graphical interface that simplifies the creation, maintenance and use of database objects.
240 ${if server-mode then ''
241 This version is build with SERVER_MODE set to True (the default). It will require access to `/var/lib/pgadmin`
242 and `/var/log/pgadmin`. This is the default version for the NixOS module `services.pgadmin`.
243 This should NOT be used in combination with the `pgadmin4-desktopmode` package as they will interfere.
244 '' else ''
245 This version is build with SERVER_MODE set to False. It will require access to `~/.pgadmin/`. This version is suitable
246 for single-user deployment or where access to `/var/lib/pgadmin` cannot be granted or the NixOS module cannot be used.
247 This should NOT be used in combination with the NixOS module `pgadmin` as they will interfere.
248 ''}
249 '';
250 homepage = "https://www.pgadmin.org/";
251 license = licenses.mit;
252 changelog = "https://www.pgadmin.org/docs/pgadmin4/latest/release_notes_${lib.versions.major version}_${lib.versions.minor version}.html";
253 maintainers = with maintainers; [ gador ];
254 mainProgram = "pgadmin4";
255 };
256}