ndev-stack 0.3.15__tar.gz → 0.3.16__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/PKG-INFO +1 -1
  2. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/__init__.py +1 -1
  3. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/db.py +82 -6
  4. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/runtime/nginx_helper.py +1 -0
  5. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev_stack.egg-info/PKG-INFO +1 -1
  6. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/pyproject.toml +1 -1
  7. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/tests/test_opensuse_compat.py +14 -0
  8. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/README.md +0 -0
  9. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/__main__.py +0 -0
  10. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/cli.py +0 -0
  11. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/__init__.py +0 -0
  12. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/config.py +0 -0
  13. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/constants.py +0 -0
  14. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/distro.py +0 -0
  15. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/github.py +0 -0
  16. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/logger.py +0 -0
  17. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/manifest.py +0 -0
  18. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/modules/__init__.py +0 -0
  19. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/modules/base.py +0 -0
  20. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/modules/builtin/mailpit/manifest.json +0 -0
  21. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/modules/builtin/mailpit/module.py +0 -0
  22. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/modules/builtin/mongodb/manifest.json +0 -0
  23. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/modules/builtin/mongodb/module.py +0 -0
  24. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/modules/builtin/postgres/manifest.json +0 -0
  25. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/modules/builtin/postgres/module.py +0 -0
  26. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/modules/builtin/redis/manifest.json +0 -0
  27. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/modules/builtin/redis/module.py +0 -0
  28. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/modules/manager.py +0 -0
  29. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/common/utils.py +0 -0
  30. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/__init__.py +0 -0
  31. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/chroot/manager.py +0 -0
  32. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/chroot/packages.py +0 -0
  33. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/chroot/shell.py +0 -0
  34. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/cli.py +0 -0
  35. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/available.py +0 -0
  36. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/clean.py +0 -0
  37. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/ctl.py +0 -0
  38. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/current.py +0 -0
  39. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/doctor.py +0 -0
  40. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/grok.py +0 -0
  41. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/install.py +0 -0
  42. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/list.py +0 -0
  43. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/logs.py +0 -0
  44. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/mailpit.py +0 -0
  45. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/modules.py +0 -0
  46. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/mongodb.py +0 -0
  47. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/postgres.py +0 -0
  48. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/reload.py +0 -0
  49. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/restart.py +0 -0
  50. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/setup.py +0 -0
  51. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/start.py +0 -0
  52. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/status.py +0 -0
  53. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/stop.py +0 -0
  54. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/uninstall.py +0 -0
  55. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/update.py +0 -0
  56. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/upgrade.py +0 -0
  57. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/use.py +0 -0
  58. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/commands/vhost.py +0 -0
  59. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/php/builder.py +0 -0
  60. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/php/downloader.py +0 -0
  61. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/php/extensions.py +0 -0
  62. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/php/installer.py +0 -0
  63. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/php/resolver.py +0 -0
  64. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/php/templates.py +0 -0
  65. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/runtime/fpm.py +0 -0
  66. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/runtime/mailpit.py +0 -0
  67. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/runtime/pma.py +0 -0
  68. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/runtime/process.py +0 -0
  69. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/runtime/services.py +0 -0
  70. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/runtime/sockets.py +0 -0
  71. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/runtime/upgrade.py +0 -0
  72. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/linux/tui.py +0 -0
  73. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/main.py +0 -0
  74. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/tui.py +0 -0
  75. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/__init__.py +0 -0
  76. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/bin/shim.exe +0 -0
  77. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/cli.py +0 -0
  78. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/commands/__init__.py +0 -0
  79. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/__init__.py +0 -0
  80. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/db.py +0 -0
  81. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/elevate.py +0 -0
  82. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/ext.py +0 -0
  83. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/fcgi.py +0 -0
  84. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/grok.py +0 -0
  85. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/logs.py +0 -0
  86. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/mailpit.py +0 -0
  87. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/mkcert.py +0 -0
  88. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/paths.py +0 -0
  89. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/php.py +0 -0
  90. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/pma.py +0 -0
  91. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/redis_core.py +0 -0
  92. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/services.py +0 -0
  93. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/setup.py +0 -0
  94. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/shim.py +0 -0
  95. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/upgrade.py +0 -0
  96. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/core/vhost.py +0 -0
  97. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/templates/vhost.conf.tmpl +0 -0
  98. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/templates/vhost_ssl.conf.tmpl +0 -0
  99. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev/win/tui.py +0 -0
  100. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev_stack.egg-info/SOURCES.txt +0 -0
  101. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev_stack.egg-info/dependency_links.txt +0 -0
  102. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev_stack.egg-info/entry_points.txt +0 -0
  103. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev_stack.egg-info/requires.txt +0 -0
  104. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/ndev_stack.egg-info/top_level.txt +0 -0
  105. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/setup.cfg +0 -0
  106. {ndev_stack-0.3.15 → ndev_stack-0.3.16}/tests/test_shim.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ndev-stack
3
- Version: 0.3.15
3
+ Version: 0.3.16
4
4
  Summary: Cross-platform developer stack manager for PHP, FastCGI/PHP-FPM, MariaDB, Redis, PostgreSQL, MongoDB, Nginx, SSL, and Mailpit on Linux and Windows
5
5
  Author-email: Ankit Karan <ankit.karan99@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/ankitkaran99/ndev
@@ -1,7 +1,7 @@
1
1
  """
2
2
  ndev: Fast, cross-platform PHP developer environment for Windows and Linux.
3
3
  """
4
- __version__ = "0.3.15"
4
+ __version__ = "0.3.16"
5
5
 
6
6
  from . import common as common
7
7
  from .common.logger import logger as logger
@@ -3,9 +3,11 @@ import sys
3
3
  import shutil
4
4
  import subprocess
5
5
  import typer
6
+ from pathlib import Path
6
7
  from typing import Optional
7
8
  from rich.console import Console
8
9
  from ndev.common.logger import logger
10
+ from ndev.common.utils import which_binary
9
11
 
10
12
  console = Console()
11
13
 
@@ -13,7 +15,8 @@ db_app = typer.Typer(help="Manage MySQL databases and users", invoke_without_com
13
15
 
14
16
  # Shared options for commands
15
17
  def execute_sql_mysql(host: str, port: int, user: str, password: Optional[str], sql: str) -> subprocess.CompletedProcess:
16
- cmd = ["mysql", "-h", host, "-P", str(port), "-u", user, "--batch", "--skip-column-names"]
18
+ client = which_binary("mariadb") or which_binary("mysql") or "mysql"
19
+ cmd = [client, "-h", host, "-P", str(port), "-u", user, "--batch", "--skip-column-names"]
17
20
  if password:
18
21
  cmd.append(f"--password={password}")
19
22
  return subprocess.run(cmd, input=sql, capture_output=True, text=True)
@@ -328,9 +331,65 @@ def configure_mariadb_root_password(new_password: str = "root", sudo_password: O
328
331
  from ndev.linux.runtime.nginx_helper import run_privileged_command
329
332
  from ndev.common.utils import which_binary
330
333
 
334
+ client_bin = which_binary("mariadb") or which_binary("mysql") or "mariadb"
335
+
336
+ # 1. Ensure MariaDB service is active
337
+ try:
338
+ run_privileged_command(["systemctl", "start", "mariadb"], password=sudo_password, check=False)
339
+ except Exception:
340
+ pass
341
+
342
+ # 2. Detect MariaDB unix socket path
343
+ socket_candidates = [
344
+ Path("/run/mysql/mysql.sock"),
345
+ Path("/run/mysqld/mysqld.sock"),
346
+ Path("/var/run/mysqld/mysqld.sock"),
347
+ Path("/var/lib/mysql/mysql.sock"),
348
+ ]
349
+ socket_args: list[str] = []
350
+ for s in socket_candidates:
351
+ if s.exists():
352
+ socket_args = ["-S", str(s)]
353
+ break
354
+
355
+ # 3. Dual auth (unix_socket + password) attempt for localhost
356
+ dual_auth_sql = (
357
+ f"ALTER USER 'root'@'localhost' IDENTIFIED VIA mysql_native_password USING PASSWORD('{new_password}') OR unix_socket; "
358
+ "FLUSH PRIVILEGES;"
359
+ )
360
+ try:
361
+ run_privileged_command([client_bin] + socket_args + ["-u", "root", "-e", dual_auth_sql], password=sudo_password, check=False)
362
+ except Exception as e:
363
+ logger.debug(f"Dual auth attempt: {e}")
364
+
365
+ # 4. Standard root password & network user creation
366
+ batch_sql = (
367
+ f"ALTER USER 'root'@'localhost' IDENTIFIED BY '{new_password}'; "
368
+ f"CREATE USER IF NOT EXISTS 'root'@'127.0.0.1' IDENTIFIED BY '{new_password}'; "
369
+ f"ALTER USER 'root'@'127.0.0.1' IDENTIFIED BY '{new_password}'; "
370
+ f"CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED BY '{new_password}'; "
371
+ f"ALTER USER 'root'@'%' IDENTIFIED BY '{new_password}'; "
372
+ "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION; "
373
+ "GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1' WITH GRANT OPTION; "
374
+ "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION; "
375
+ "FLUSH PRIVILEGES;"
376
+ )
377
+
378
+ try:
379
+ run_privileged_command([client_bin] + socket_args + ["-u", "root", "-f", "-e", batch_sql], password=sudo_password, check=False)
380
+ except Exception as e:
381
+ logger.debug(f"Batch SQL config: {e}")
382
+
383
+ # Also try if root already has password set
384
+ try:
385
+ run_privileged_command([client_bin] + socket_args + ["-u", "root", f"--password={new_password}", "-f", "-e", batch_sql], password=sudo_password, check=False)
386
+ except Exception:
387
+ pass
388
+
389
+ # 5. Fallback individual statements
331
390
  sql_statements = [
332
- f"ALTER USER 'root'@'localhost' IDENTIFIED VIA mysql_native_password USING PASSWORD('{new_password}') OR unix_socket;",
333
391
  f"ALTER USER 'root'@'localhost' IDENTIFIED BY '{new_password}';",
392
+ f"SET PASSWORD FOR 'root'@'localhost' = PASSWORD('{new_password}');",
334
393
  f"CREATE USER IF NOT EXISTS 'root'@'127.0.0.1' IDENTIFIED BY '{new_password}';",
335
394
  f"ALTER USER 'root'@'127.0.0.1' IDENTIFIED BY '{new_password}';",
336
395
  f"CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED BY '{new_password}';",
@@ -341,16 +400,14 @@ def configure_mariadb_root_password(new_password: str = "root", sudo_password: O
341
400
  "FLUSH PRIVILEGES;",
342
401
  ]
343
402
 
344
- client_bin = which_binary("mariadb") or which_binary("mysql") or "mariadb"
345
-
346
403
  for sql in sql_statements:
347
404
  try:
348
- cmd = [client_bin, "-u", "root", "-e", sql]
405
+ cmd = [client_bin] + socket_args + ["-u", "root", "-e", sql]
349
406
  run_privileged_command(cmd, password=sudo_password, check=False)
350
407
  except Exception:
351
408
  pass
352
409
 
353
- # Verify if connection succeeds via TCP
410
+ # 6. Verify if connection succeeds via TCP
354
411
  for h in ["127.0.0.1", "localhost"]:
355
412
  try:
356
413
  test_cmd = [client_bin, "-h", h, "-P", "3306", "-u", "root", f"--password={new_password}", "-e", "SELECT 1;"]
@@ -369,6 +426,25 @@ def set_root_password_cmd(
369
426
  password: str = typer.Option("root", "--password", "-p", help="New root password (default: root)"),
370
427
  ):
371
428
  """Set or reset MariaDB root password and enable password login across localhost and 127.0.0.1."""
429
+ if os.geteuid() != 0:
430
+ console.print("[bold yellow]MariaDB root configuration requires administrator privileges. Elevating via sudo...[/bold yellow]")
431
+ cmd = [
432
+ "sudo",
433
+ sys.executable,
434
+ "-m",
435
+ "ndev",
436
+ "db",
437
+ "set-root-password",
438
+ "--password",
439
+ password,
440
+ ]
441
+ try:
442
+ res = subprocess.run(cmd)
443
+ raise typer.Exit(code=res.returncode)
444
+ except KeyboardInterrupt:
445
+ console.print("\n[red]Cancelled by user.[/red]")
446
+ raise typer.Exit(code=130)
447
+
372
448
  console.print(f"[bold yellow]Configuring MariaDB root access with password '{password}'...[/bold yellow]")
373
449
  ok = configure_mariadb_root_password(new_password=password)
374
450
  if ok:
@@ -7,6 +7,7 @@ from __future__ import annotations
7
7
 
8
8
  import os
9
9
  import re
10
+ import sys
10
11
  import socket
11
12
  import shutil
12
13
  import subprocess
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ndev-stack
3
- Version: 0.3.15
3
+ Version: 0.3.16
4
4
  Summary: Cross-platform developer stack manager for PHP, FastCGI/PHP-FPM, MariaDB, Redis, PostgreSQL, MongoDB, Nginx, SSL, and Mailpit on Linux and Windows
5
5
  Author-email: Ankit Karan <ankit.karan99@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/ankitkaran99/ndev
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ndev-stack"
7
- version = "0.3.15"
7
+ version = "0.3.16"
8
8
  description = "Cross-platform developer stack manager for PHP, FastCGI/PHP-FPM, MariaDB, Redis, PostgreSQL, MongoDB, Nginx, SSL, and Mailpit on Linux and Windows"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -559,6 +559,20 @@ class TestDatabaseCommands(unittest.TestCase):
559
559
  self.assertTrue(ok)
560
560
  mock_priv.assert_called()
561
561
 
562
+ def test_set_root_password_cmd_elevates_when_non_root(self):
563
+ import typer
564
+ from ndev.linux.commands.db import set_root_password_cmd
565
+ with patch("os.geteuid", return_value=1000):
566
+ with patch("subprocess.run") as mock_run:
567
+ mock_run.return_value = subprocess.CompletedProcess(args=[], returncode=0)
568
+ with self.assertRaises((SystemExit, typer.Exit)) as cm:
569
+ set_root_password_cmd(password="root")
570
+ exit_code = getattr(cm.exception, "exit_code", getattr(cm.exception, "code", 0))
571
+ self.assertEqual(exit_code, 0)
572
+ mock_run.assert_called_once()
573
+ self.assertIn("sudo", mock_run.call_args[0][0])
574
+ self.assertIn("set-root-password", mock_run.call_args[0][0])
575
+
562
576
 
563
577
  class TestTuiEnsureSudo(unittest.TestCase):
564
578
  def test_ensure_sudo_when_not_needed(self):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes