feat(init): add preview_changes method to show read-only schema init diff
Adds preview_changes method to utils/neo4j-schema-init.py. Performs read-only queries against the live database to compare current state against the v2.3.0 schema spec. Reports expected constraints, indexes, and sample nodes/relationships by team.
This commit is contained in:
@@ -123,21 +123,65 @@ EXPECTED_INDEX_SAMPLES = [
|
||||
]
|
||||
|
||||
|
||||
def _mask_password(pw):
|
||||
"""Mask a password for display: keep first and last char, hide the middle."""
|
||||
if not pw:
|
||||
return "(empty)"
|
||||
if len(pw) <= 2:
|
||||
return "*" * len(pw)
|
||||
return f"{pw[0]}{'*' * (len(pw) - 2)}{pw[-1]} ({len(pw)} chars)"
|
||||
|
||||
|
||||
def get_credentials(args):
|
||||
uri = args.uri or os.environ.get("NEO4J_URI")
|
||||
if not uri:
|
||||
uri = input("Neo4j URI [bolt://localhost:7687]: ").strip() or "bolt://localhost:7687"
|
||||
"""
|
||||
Collect Neo4j credentials by prompting for each value sequentially.
|
||||
|
||||
user = args.user or os.environ.get("NEO4J_USER")
|
||||
if not user:
|
||||
user = input("Neo4j username [neo4j]: ").strip() or "neo4j"
|
||||
For each of URI, username, password: show the current default (from CLI
|
||||
arg, env var, or built-in fallback) in brackets; user hits Enter to
|
||||
accept or types a new value to override. Password prompt uses getpass
|
||||
so it isn't echoed and doesn't land in shell history.
|
||||
|
||||
password = os.environ.get("NEO4J_PASSWORD")
|
||||
Finally, print a summary (password masked) and ask for final confirmation.
|
||||
If the user declines, exit cleanly without touching the database.
|
||||
"""
|
||||
print()
|
||||
print("─" * 60)
|
||||
print(" Neo4j Connection")
|
||||
print("─" * 60)
|
||||
|
||||
# URI
|
||||
uri_default = args.uri or os.environ.get("NEO4J_URI") or "bolt://localhost:7687"
|
||||
uri = input(f" Neo4j URI [{uri_default}]: ").strip() or uri_default
|
||||
|
||||
# Username
|
||||
user_default = args.user or os.environ.get("NEO4J_USER") or "neo4j"
|
||||
user = input(f" Neo4j username [{user_default}]: ").strip() or user_default
|
||||
|
||||
# Password (always via getpass, never echoed)
|
||||
env_password = os.environ.get("NEO4J_PASSWORD")
|
||||
if env_password:
|
||||
prompt = " Neo4j password [from $NEO4J_PASSWORD, Enter to accept]: "
|
||||
else:
|
||||
prompt = " Neo4j password: "
|
||||
password = getpass.getpass(prompt) or env_password or ""
|
||||
if not password:
|
||||
password = getpass.getpass("Neo4j password: ")
|
||||
if not password:
|
||||
print("ERROR: Password is required")
|
||||
sys.exit(1)
|
||||
print("ERROR: Password is required")
|
||||
sys.exit(1)
|
||||
|
||||
# Summary + confirm
|
||||
print()
|
||||
print("─" * 60)
|
||||
print(" Connection summary")
|
||||
print("─" * 60)
|
||||
print(f" URI: {uri}")
|
||||
print(f" User: {user}")
|
||||
print(f" Password: {_mask_password(password)}")
|
||||
print("─" * 60)
|
||||
print(" Validation is read-only — no graph data will be modified.")
|
||||
confirm = input("Proceed with these credentials? [Y/n]: ").strip().lower()
|
||||
if confirm and confirm not in ("y", "yes"):
|
||||
print("Cancelled by user.")
|
||||
sys.exit(0)
|
||||
|
||||
return uri, user, password
|
||||
|
||||
|
||||
Reference in New Issue
Block a user