init local package repo
This commit is contained in:
Executable
+48
@@ -0,0 +1,48 @@
|
||||
#!/bin/bash
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Venture Fund CRM — Database Backup Script
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/backup.sh # Backup to ./backups/
|
||||
# ./scripts/backup.sh /path/to/backups # Backup to custom dir
|
||||
#
|
||||
# Automate with cron:
|
||||
# crontab -e
|
||||
# 0 2 * * * /path/to/venture-crm/scripts/backup.sh >> /var/log/crm-backup.log 2>&1
|
||||
#
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
DB_PATH="$PROJECT_DIR/data/crm.db"
|
||||
BACKUP_DIR="${1:-$PROJECT_DIR/backups}"
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
BACKUP_FILE="$BACKUP_DIR/crm_backup_$TIMESTAMP.db"
|
||||
|
||||
# Create backup directory
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
if [ ! -f "$DB_PATH" ]; then
|
||||
echo "ERROR: Database not found at $DB_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Use SQLite's backup command for a safe, consistent backup
|
||||
# This works even if the server is running
|
||||
sqlite3 "$DB_PATH" ".backup '$BACKUP_FILE'"
|
||||
|
||||
# Get file size
|
||||
SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
|
||||
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Backup created: $BACKUP_FILE ($SIZE)"
|
||||
|
||||
# Clean up old backups (keep last 30)
|
||||
BACKUP_COUNT=$(ls -1 "$BACKUP_DIR"/crm_backup_*.db 2>/dev/null | wc -l)
|
||||
if [ "$BACKUP_COUNT" -gt 30 ]; then
|
||||
REMOVE_COUNT=$((BACKUP_COUNT - 30))
|
||||
ls -1t "$BACKUP_DIR"/crm_backup_*.db | tail -n "$REMOVE_COUNT" | xargs rm -f
|
||||
echo " Cleaned up $REMOVE_COUNT old backup(s). Keeping last 30."
|
||||
fi
|
||||
Executable
+71
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Create a new user for the Venture Fund CRM."""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import getpass
|
||||
|
||||
# Add parent directory to path
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'backend'))
|
||||
from server import get_db, hash_password, generate_id, init_db
|
||||
|
||||
def main():
|
||||
init_db()
|
||||
|
||||
print("\n Create New CRM User")
|
||||
print(" " + "=" * 30 + "\n")
|
||||
|
||||
username = input(" Username: ").strip()
|
||||
if not username:
|
||||
print(" Error: Username required")
|
||||
sys.exit(1)
|
||||
|
||||
email = input(" Email: ").strip()
|
||||
if not email:
|
||||
print(" Error: Email required")
|
||||
sys.exit(1)
|
||||
|
||||
full_name = input(" Full Name: ").strip()
|
||||
if not full_name:
|
||||
print(" Error: Full name required")
|
||||
sys.exit(1)
|
||||
|
||||
password = getpass.getpass(" Password: ")
|
||||
if len(password) < 6:
|
||||
print(" Error: Password must be at least 6 characters")
|
||||
sys.exit(1)
|
||||
|
||||
confirm = getpass.getpass(" Confirm Password: ")
|
||||
if password != confirm:
|
||||
print(" Error: Passwords don't match")
|
||||
sys.exit(1)
|
||||
|
||||
role = input(" Role (admin/manager/member) [member]: ").strip() or "member"
|
||||
if role not in ['admin', 'manager', 'member']:
|
||||
print(" Error: Invalid role")
|
||||
sys.exit(1)
|
||||
|
||||
conn = get_db()
|
||||
|
||||
# Check for existing
|
||||
existing = conn.execute("SELECT id FROM users WHERE username = ? OR email = ?",
|
||||
(username, email)).fetchone()
|
||||
if existing:
|
||||
print(f"\n Error: User with that username or email already exists")
|
||||
conn.close()
|
||||
sys.exit(1)
|
||||
|
||||
user_id = generate_id()
|
||||
conn.execute("""
|
||||
INSERT INTO users (id, username, email, password_hash, full_name, role)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
""", (user_id, username, email, hash_password(password), full_name, role))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
print(f"\n User '{username}' created successfully!")
|
||||
print(f" Role: {role}")
|
||||
print(f" ID: {user_id}\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Reset a user's password in the Venture Fund CRM."""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import getpass
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'backend'))
|
||||
from server import get_db, hash_password
|
||||
|
||||
def main():
|
||||
print("\n Reset User Password")
|
||||
print(" " + "=" * 30 + "\n")
|
||||
|
||||
username = input(" Username: ").strip()
|
||||
if not username:
|
||||
print(" Error: Username required")
|
||||
sys.exit(1)
|
||||
|
||||
conn = get_db()
|
||||
user = conn.execute("SELECT id, full_name FROM users WHERE username = ?", (username,)).fetchone()
|
||||
if not user:
|
||||
print(f" Error: User '{username}' not found")
|
||||
conn.close()
|
||||
sys.exit(1)
|
||||
|
||||
print(f" Found user: {user['full_name']}")
|
||||
|
||||
password = getpass.getpass(" New Password: ")
|
||||
if len(password) < 6:
|
||||
print(" Error: Password must be at least 6 characters")
|
||||
sys.exit(1)
|
||||
|
||||
confirm = getpass.getpass(" Confirm Password: ")
|
||||
if password != confirm:
|
||||
print(" Error: Passwords don't match")
|
||||
sys.exit(1)
|
||||
|
||||
conn.execute("UPDATE users SET password_hash = ? WHERE id = ?",
|
||||
(hash_password(password), user['id']))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
print(f"\n Password reset successfully for '{username}'!\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user