ndev-stack 0.3.14__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.
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/PKG-INFO +1 -1
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/__init__.py +1 -1
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/db.py +138 -1
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/doctor.py +19 -1
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/setup.py +10 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/runtime/nginx_helper.py +1 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev_stack.egg-info/PKG-INFO +1 -1
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/pyproject.toml +1 -1
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/tests/test_opensuse_compat.py +25 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/README.md +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/__main__.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/cli.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/__init__.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/config.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/constants.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/distro.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/github.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/logger.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/manifest.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/modules/__init__.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/modules/base.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/modules/builtin/mailpit/manifest.json +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/modules/builtin/mailpit/module.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/modules/builtin/mongodb/manifest.json +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/modules/builtin/mongodb/module.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/modules/builtin/postgres/manifest.json +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/modules/builtin/postgres/module.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/modules/builtin/redis/manifest.json +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/modules/builtin/redis/module.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/modules/manager.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/common/utils.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/__init__.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/chroot/manager.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/chroot/packages.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/chroot/shell.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/cli.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/available.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/clean.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/ctl.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/current.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/grok.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/install.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/list.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/logs.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/mailpit.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/modules.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/mongodb.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/postgres.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/reload.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/restart.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/start.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/status.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/stop.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/uninstall.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/update.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/upgrade.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/use.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/commands/vhost.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/php/builder.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/php/downloader.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/php/extensions.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/php/installer.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/php/resolver.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/php/templates.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/runtime/fpm.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/runtime/mailpit.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/runtime/pma.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/runtime/process.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/runtime/services.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/runtime/sockets.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/runtime/upgrade.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/linux/tui.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/main.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/tui.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/__init__.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/bin/shim.exe +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/cli.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/commands/__init__.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/__init__.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/db.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/elevate.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/ext.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/fcgi.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/grok.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/logs.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/mailpit.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/mkcert.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/paths.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/php.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/pma.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/redis_core.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/services.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/setup.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/shim.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/upgrade.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/core/vhost.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/templates/vhost.conf.tmpl +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/templates/vhost_ssl.conf.tmpl +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev/win/tui.py +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev_stack.egg-info/SOURCES.txt +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev_stack.egg-info/dependency_links.txt +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev_stack.egg-info/entry_points.txt +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev_stack.egg-info/requires.txt +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/ndev_stack.egg-info/top_level.txt +0 -0
- {ndev_stack-0.3.14 → ndev_stack-0.3.16}/setup.cfg +0 -0
- {ndev_stack-0.3.14 → 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.
|
|
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
|
|
@@ -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
|
-
|
|
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)
|
|
@@ -317,3 +320,137 @@ def drop_user_cmd(
|
|
|
317
320
|
confirm_destructive(force, username, f"You are about to DROP user '{username}' permanently.")
|
|
318
321
|
execute_drop_user(host, port, user, password, username, user_host)
|
|
319
322
|
|
|
323
|
+
|
|
324
|
+
def configure_mariadb_root_password(new_password: str = "root", sudo_password: Optional[str] = None) -> bool:
|
|
325
|
+
"""
|
|
326
|
+
Configure MariaDB root account to allow password authentication (e.g. root/root)
|
|
327
|
+
across localhost, 127.0.0.1, and %.
|
|
328
|
+
Fixes ERROR 1698 (28000): Access denied for user 'root'@'localhost'
|
|
329
|
+
caused by default unix_socket authentication on Linux.
|
|
330
|
+
"""
|
|
331
|
+
from ndev.linux.runtime.nginx_helper import run_privileged_command
|
|
332
|
+
from ndev.common.utils import which_binary
|
|
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
|
|
390
|
+
sql_statements = [
|
|
391
|
+
f"ALTER USER 'root'@'localhost' IDENTIFIED BY '{new_password}';",
|
|
392
|
+
f"SET PASSWORD FOR 'root'@'localhost' = PASSWORD('{new_password}');",
|
|
393
|
+
f"CREATE USER IF NOT EXISTS 'root'@'127.0.0.1' IDENTIFIED BY '{new_password}';",
|
|
394
|
+
f"ALTER USER 'root'@'127.0.0.1' IDENTIFIED BY '{new_password}';",
|
|
395
|
+
f"CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED BY '{new_password}';",
|
|
396
|
+
f"ALTER USER 'root'@'%' IDENTIFIED BY '{new_password}';",
|
|
397
|
+
"GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;",
|
|
398
|
+
"GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1' WITH GRANT OPTION;",
|
|
399
|
+
"GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;",
|
|
400
|
+
"FLUSH PRIVILEGES;",
|
|
401
|
+
]
|
|
402
|
+
|
|
403
|
+
for sql in sql_statements:
|
|
404
|
+
try:
|
|
405
|
+
cmd = [client_bin] + socket_args + ["-u", "root", "-e", sql]
|
|
406
|
+
run_privileged_command(cmd, password=sudo_password, check=False)
|
|
407
|
+
except Exception:
|
|
408
|
+
pass
|
|
409
|
+
|
|
410
|
+
# 6. Verify if connection succeeds via TCP
|
|
411
|
+
for h in ["127.0.0.1", "localhost"]:
|
|
412
|
+
try:
|
|
413
|
+
test_cmd = [client_bin, "-h", h, "-P", "3306", "-u", "root", f"--password={new_password}", "-e", "SELECT 1;"]
|
|
414
|
+
res = subprocess.run(test_cmd, capture_output=True, text=True, timeout=5)
|
|
415
|
+
if res.returncode == 0:
|
|
416
|
+
return True
|
|
417
|
+
except Exception:
|
|
418
|
+
pass
|
|
419
|
+
|
|
420
|
+
return False
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
@db_app.command("set-root-password")
|
|
424
|
+
@db_app.command("reset-root")
|
|
425
|
+
def set_root_password_cmd(
|
|
426
|
+
password: str = typer.Option("root", "--password", "-p", help="New root password (default: root)"),
|
|
427
|
+
):
|
|
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
|
+
|
|
448
|
+
console.print(f"[bold yellow]Configuring MariaDB root access with password '{password}'...[/bold yellow]")
|
|
449
|
+
ok = configure_mariadb_root_password(new_password=password)
|
|
450
|
+
if ok:
|
|
451
|
+
console.print(f"[bold green]✓ MariaDB root password configured successfully! (user: root, password: {password})[/bold green]")
|
|
452
|
+
console.print(f"[dim]You can now connect via phpMyAdmin, Laravel, or CLI using user 'root' and password '{password}'.[/dim]")
|
|
453
|
+
else:
|
|
454
|
+
logger.error("Failed to configure MariaDB root password. Ensure MariaDB is running and you have administrator privileges.")
|
|
455
|
+
raise typer.Exit(code=1)
|
|
456
|
+
|
|
@@ -64,7 +64,25 @@ def doctor_cmd():
|
|
|
64
64
|
|
|
65
65
|
db_path = which_binary("mariadb") or which_binary("mysql") or which_binary("mysqld")
|
|
66
66
|
if db_path:
|
|
67
|
-
|
|
67
|
+
db_details = f"Found at {db_path}"
|
|
68
|
+
connected = False
|
|
69
|
+
client_bin = which_binary("mariadb") or which_binary("mysql") or db_path
|
|
70
|
+
for test_pwd in ["root", ""]:
|
|
71
|
+
try:
|
|
72
|
+
cmd = [client_bin, "-h", "127.0.0.1", "-P", "3306", "-u", "root", f"--password={test_pwd}", "-e", "SELECT 1;"]
|
|
73
|
+
r = subprocess.run(cmd, capture_output=True, timeout=2)
|
|
74
|
+
if r.returncode == 0:
|
|
75
|
+
connected = True
|
|
76
|
+
pwd_label = f"password: '{test_pwd}'" if test_pwd else "no password"
|
|
77
|
+
db_details += f" (127.0.0.1 root access: {pwd_label})"
|
|
78
|
+
break
|
|
79
|
+
except Exception:
|
|
80
|
+
pass
|
|
81
|
+
if not connected:
|
|
82
|
+
db_details += " (127.0.0.1 root access restricted: run 'ndev db set-root-password')"
|
|
83
|
+
table.add_row("MariaDB / MySQL", "[yellow]RESTRICTED[/yellow]", db_details)
|
|
84
|
+
else:
|
|
85
|
+
table.add_row("MariaDB / MySQL", "[green]OK[/green]", db_details)
|
|
68
86
|
else:
|
|
69
87
|
table.add_row("MariaDB / MySQL", "[yellow]NOT INSTALLED[/yellow]", f"Run 'ndev setup' or: {stack_install_cmd}")
|
|
70
88
|
|
|
@@ -141,6 +141,16 @@ def setup_cmd():
|
|
|
141
141
|
except Exception:
|
|
142
142
|
pass
|
|
143
143
|
|
|
144
|
+
# MariaDB Root User Authentication (root / root)
|
|
145
|
+
try:
|
|
146
|
+
from ndev.linux.commands.db import configure_mariadb_root_password
|
|
147
|
+
if configure_mariadb_root_password(new_password="root"):
|
|
148
|
+
console.print(" [bold green]✓[/bold green] Configured MariaDB root access (user: root, password: root).")
|
|
149
|
+
else:
|
|
150
|
+
console.print(" [yellow]Notice: MariaDB root access could not be automatically set to root/root.[/yellow]")
|
|
151
|
+
except Exception as e:
|
|
152
|
+
logger.warning(f"MariaDB root configuration notice: {e}")
|
|
153
|
+
|
|
144
154
|
# 4. Install Composer
|
|
145
155
|
local_bin = get_user_local_bin_dir()
|
|
146
156
|
composer_bin = local_bin / "composer"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ndev-stack
|
|
3
|
-
Version: 0.3.
|
|
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.
|
|
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"
|
|
@@ -549,6 +549,31 @@ class TestTuiSelectEventHandling(unittest.TestCase):
|
|
|
549
549
|
app._switch_php_version.assert_called_once_with("8.4.27")
|
|
550
550
|
|
|
551
551
|
|
|
552
|
+
class TestDatabaseCommands(unittest.TestCase):
|
|
553
|
+
def test_configure_mariadb_root_password(self):
|
|
554
|
+
from ndev.linux.commands.db import configure_mariadb_root_password
|
|
555
|
+
with patch("ndev.linux.runtime.nginx_helper.run_privileged_command") as mock_priv:
|
|
556
|
+
with patch("subprocess.run") as mock_run:
|
|
557
|
+
mock_run.return_value = subprocess.CompletedProcess(args=[], returncode=0)
|
|
558
|
+
ok = configure_mariadb_root_password(new_password="root")
|
|
559
|
+
self.assertTrue(ok)
|
|
560
|
+
mock_priv.assert_called()
|
|
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
|
+
|
|
576
|
+
|
|
552
577
|
class TestTuiEnsureSudo(unittest.TestCase):
|
|
553
578
|
def test_ensure_sudo_when_not_needed(self):
|
|
554
579
|
from ndev.linux.tui import NdevDashboard
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|