Reorganize repo: compartmentalize scripts by client/project

Move 150+ scripts from root and scripts/ into client/project directories:
- clients/dataforth/scripts/ (110 files: AD2, sync, SSH, DB, DOS scripts)
- clients/bg-builders/scripts/ (14 files: Lesley mgmt, Exchange, termination)
- clients/internal-infrastructure/scripts/ (10 files: GDAP, Gitea, backups)
- projects/msp-tools/scripts/ (9 files: CIPP, MSP onboarding, Datto)
- projects/gururmm-agent/scripts/ (3 files: API test, JWT, record counts)
- clients/glaztech/scripts/ (1 file: CentraStage removal)

Also reorganized:
- VPN scripts → infrastructure/vpn-configs/
- Retrieved API/JS files → api/
- Forum posts → projects/community-forum/forum-posts/
- SSH docs → clients/internal-infrastructure/docs/
- NWTOC/CTONW docs → projects/wrightstown-smarthome/docs/
- ACG website files → projects/internal/acg-website-2025/
- Dataforth docs → clients/dataforth/docs/
- schema-retrieved.sql → docs/database/

Deleted 24 tmp_*.ps1 one-off debug scripts (preserved in git history).
Root reduced from 220+ files to 62 items (docs + directories only).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-20 17:15:07 -07:00
parent 98ea867d2c
commit 5cbd49ce24
207 changed files with 49 additions and 547 deletions

View File

@@ -0,0 +1,98 @@
#!/usr/bin/env python3
"""
Check record counts in all ClaudeTools database tables
"""
import sys
from sqlalchemy import create_engine, text, inspect
# Database connection
DATABASE_URL = "mysql+pymysql://claudetools:CT_e8fcd5a3952030a79ed6debae6c954ed@172.16.3.30:3306/claudetools?charset=utf8mb4"
def get_table_counts():
"""Get row counts for all tables"""
engine = create_engine(DATABASE_URL)
with engine.connect() as conn:
# Get all table names
inspector = inspect(engine)
tables = inspector.get_table_names()
print("=" * 70)
print("ClaudeTools Database Record Counts")
print("=" * 70)
print(f"Database: claudetools @ 172.16.3.30:3306")
print(f"Total Tables: {len(tables)}")
print("=" * 70)
print()
# Count rows in each table
counts = {}
total_records = 0
for table in sorted(tables):
result = conn.execute(text(f"SELECT COUNT(*) FROM `{table}`"))
count = result.scalar()
counts[table] = count
total_records += count
# Group by category
categories = {
'Core': ['machines', 'clients', 'projects', 'sessions', 'tags'],
'MSP Work': ['work_items', 'tasks', 'billable_time', 'work_item_files'],
'Infrastructure': ['sites', 'infrastructure', 'services', 'networks', 'firewall_rules', 'm365_tenants', 'm365_licenses'],
'Credentials': ['credentials', 'credential_audit_logs', 'security_incidents'],
'Context Recall': ['conversation_contexts', 'context_snippets', 'project_states', 'decision_logs'],
'Learning': ['command_runs', 'file_changes', 'problem_solutions', 'failure_patterns', 'environmental_insights'],
'Integrations': ['msp_integrations', 'backup_jobs', 'backup_reports'],
'Junction': ['session_tags', 'session_work_items', 'client_contacts', 'project_repositories']
}
# Print by category
for category, table_list in categories.items():
category_tables = [t for t in table_list if t in counts]
if not category_tables:
continue
print(f"{category}:")
print("-" * 70)
category_total = 0
for table in category_tables:
count = counts[table]
category_total += count
status = "[OK]" if count > 0 else " "
print(f" {status} {table:.<50} {count:>10,}")
print(f" {'Subtotal':.<50} {category_total:>10,}")
print()
# Print any uncategorized tables
all_categorized = set()
for table_list in categories.values():
all_categorized.update(table_list)
uncategorized = [t for t in counts.keys() if t not in all_categorized]
if uncategorized:
print("Other Tables:")
print("-" * 70)
for table in uncategorized:
count = counts[table]
status = "[OK]" if count > 0 else " "
print(f" {status} {table:.<50} {count:>10,}")
print()
# Print summary
print("=" * 70)
print(f"TOTAL RECORDS: {total_records:,}")
print(f"Tables with data: {sum(1 for c in counts.values() if c > 0)}/{len(tables)}")
print("=" * 70)
return counts, total_records
if __name__ == "__main__":
try:
counts, total = get_table_counts()
sys.exit(0)
except Exception as e:
print(f"ERROR: {e}", file=sys.stderr)
import traceback
traceback.print_exc()
sys.exit(1)

View File

@@ -0,0 +1,28 @@
#!/usr/bin/env python3
"""
Create a JWT token for ClaudeTools API access
"""
import jwt
from datetime import datetime, timedelta, timezone
# Get the JWT secret from the RMM server's .env file
# This should match what's in /opt/claudetools/.env on 172.16.3.30
JWT_SECRET = "NdwgH6jsGR1WfPdUwR3u9i1NwNx3QthhLHBsRCfFxcg="
# Create token data
data = {
"sub": "import-script",
"scopes": ["admin", "import"],
"exp": datetime.now(timezone.utc) + timedelta(days=30)
}
# Create token
token = jwt.encode(data, JWT_SECRET, algorithm="HS256")
print(f"New JWT Token:")
print(token)
print()
print(f"Expires: {data['exp']}")
print()
print("Add this to .claude/context-recall-config.env:")
print(f"JWT_TOKEN={token}")

View File

@@ -0,0 +1,145 @@
#!/usr/bin/env python3
"""
GuruRMM API Access Test Script
Tests the newly created admin user credentials and verifies API access.
"""
import requests
import json
from datetime import datetime
# Configuration
API_BASE_URL = "http://172.16.3.30:3001"
EMAIL = "claude-api@azcomputerguru.com"
PASSWORD = "ClaudeAPI2026!@#"
def print_header(title):
"""Print a formatted header."""
print("\n" + "=" * 60)
print(f" {title}")
print("=" * 60 + "\n")
def print_success(message):
"""Print success message."""
print(f"[OK] {message}")
def print_error(message):
"""Print error message."""
print(f"[ERROR] {message}")
def test_login():
"""Test login and retrieve JWT token."""
print_header("Test 1: Login and Authentication")
try:
response = requests.post(
f"{API_BASE_URL}/api/auth/login",
json={"email": EMAIL, "password": PASSWORD},
timeout=10
)
if response.status_code != 200:
print_error(f"Login failed with status {response.status_code}")
print(f"Response: {response.text}")
return None
data = response.json()
token = data.get("token")
user = data.get("user")
if not token:
print_error("No token in response")
return None
print_success("Login successful")
print(f" User ID: {user.get('id')}")
print(f" Email: {user.get('email')}")
print(f" Name: {user.get('name')}")
print(f" Role: {user.get('role')}")
print(f" Token: {token[:50]}...")
return token
except requests.exceptions.RequestException as e:
print_error(f"Request failed: {e}")
return None
def test_authenticated_request(token, endpoint, name):
"""Test an authenticated API request."""
print_header(f"Test: {name}")
try:
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(
f"{API_BASE_URL}{endpoint}",
headers=headers,
timeout=10
)
if response.status_code != 200:
print_error(f"Request failed with status {response.status_code}")
print(f"Response: {response.text}")
return False
data = response.json()
count = len(data) if isinstance(data, list) else 1
print_success(f"Retrieved {count} record(s)")
# Print first record as sample
if isinstance(data, list) and data:
print("\nSample record:")
print(json.dumps(data[0], indent=2))
elif isinstance(data, dict):
print("\nResponse:")
print(json.dumps(data, indent=2)[:500] + "...")
return True
except requests.exceptions.RequestException as e:
print_error(f"Request failed: {e}")
return False
def main():
"""Main test runner."""
print_header("GuruRMM API Access Test")
print(f"Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"API Base URL: {API_BASE_URL}")
print(f"Test User: {EMAIL}")
# Test 1: Login
token = test_login()
if not token:
print_error("Login test failed. Aborting remaining tests.")
return 1
# Test 2: Sites endpoint
if not test_authenticated_request(token, "/api/sites", "List Sites"):
print_error("Sites test failed")
return 1
# Test 3: Agents endpoint
if not test_authenticated_request(token, "/api/agents", "List Agents"):
print_error("Agents test failed")
return 1
# Test 4: Clients endpoint
if not test_authenticated_request(token, "/api/clients", "List Clients"):
print_error("Clients test failed")
return 1
# Success summary
print_header("All Tests Passed!")
print("API Credentials:")
print(f" Email: {EMAIL}")
print(f" Password: {PASSWORD}")
print(f" Base URL: {API_BASE_URL}")
print(f" Production URL: https://rmm-api.azcomputerguru.com")
print("\nStatus: READY FOR INTEGRATION")
print()
return 0
if __name__ == "__main__":
exit(main())