mirror of
https://github.com/myronblair/jarvis
synced 2026-07-28 08:43:00 -05:00
Compare commits
3 Commits
18783dc137
...
3d16061709
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d16061709 | |||
| 80588efa7a | |||
| f7309a15fc |
File diff suppressed because it is too large
Load Diff
@@ -54,7 +54,7 @@ function update_agent_seen(string $agentId, string $status = 'online', ?string $
|
|||||||
// ── Auth (all actions except register) ───────────────────────────────────────
|
// ── Auth (all actions except register) ───────────────────────────────────────
|
||||||
|
|
||||||
$agentKey = $_SERVER['HTTP_X_AGENT_KEY'] ?? '';
|
$agentKey = $_SERVER['HTTP_X_AGENT_KEY'] ?? '';
|
||||||
$browserActions = ['list', 'status', 'myip'];
|
$browserActions = ['list', 'status', 'myip', 'regkey'];
|
||||||
|
|
||||||
if ($agentAction !== 'register') {
|
if ($agentAction !== 'register') {
|
||||||
if (in_array($agentAction, $browserActions)) {
|
if (in_array($agentAction, $browserActions)) {
|
||||||
@@ -212,6 +212,10 @@ switch ($agentAction) {
|
|||||||
);
|
);
|
||||||
agent_ok();
|
agent_ok();
|
||||||
|
|
||||||
|
// ── REGKEY (browser: session-authed fetch of registration key) ───────────
|
||||||
|
case 'regkey':
|
||||||
|
agent_ok(['registration_key' => AGENT_REGISTRATION_KEY]);
|
||||||
|
|
||||||
// ── LIST (admin: get all agents status) ──────────────────────────────────
|
// ── LIST (admin: get all agents status) ──────────────────────────────────
|
||||||
case 'list':
|
case 'list':
|
||||||
// Mark agents offline if last_seen > 2 minutes ago
|
// Mark agents offline if last_seen > 2 minutes ago
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
// Network scan push endpoint — called by PVE1 cron with nmap results
|
// Network scan push endpoint — called by PVE1 cron with nmap results
|
||||||
// Authenticates via X-Registration-Key header (same key as agent installer)
|
// Authenticates via X-Registration-Key header (same key as agent installer)
|
||||||
|
|
||||||
define('NETSCAN_KEY', 'f846a9aaf7ce9a61742c63c87c4186052a71d2a580c65518');
|
define('NETSCAN_KEY', AGENT_REGISTRATION_KEY);
|
||||||
|
|
||||||
if ($method !== 'POST') {
|
if ($method !== 'POST') {
|
||||||
echo json_encode(['error' => 'POST only']); exit;
|
echo json_encode(['error' => 'POST only']); exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$reqKey = $_SERVER['HTTP_X_REGISTRATION_KEY'] ?? '';
|
$reqKey = $_SERVER['HTTP_X_REGISTRATION_KEY'] ?? '';
|
||||||
if ($reqKey !== NETSCAN_KEY) {
|
if (!hash_equals(NETSCAN_KEY, $reqKey)) {
|
||||||
http_response_code(401);
|
http_response_code(401);
|
||||||
echo json_encode(['error' => 'Unauthorized']); exit;
|
echo json_encode(['error' => 'Unauthorized']); exit;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Copy to /etc/jarvis/db.env (root:root 0600). Sourced by the root cron scripts
|
||||||
|
# (jarvis-backup.sh, jarvis-deploy.sh, jarvis-watchdog.sh).
|
||||||
|
JARVIS_DB_PASS=your-db-password
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
[ -r /etc/jarvis/db.env ] && . /etc/jarvis/db.env
|
||||||
# JARVIS backup — DB dump + all files needed to actually restore JARVIS, as tar.gz
|
# JARVIS backup — DB dump + all files needed to actually restore JARVIS, as tar.gz
|
||||||
# Fixed 2026-07-07: this only ever backed up the MySQL database. If this VM were
|
# Fixed 2026-07-07: this only ever backed up the MySQL database. If this VM were
|
||||||
# lost, the DB alone is useless without the application code, the reactor daemon,
|
# lost, the DB alone is useless without the application code, the reactor daemon,
|
||||||
@@ -9,7 +10,7 @@ LOG="$BACKUP_DIR/backup.log"
|
|||||||
LOCK="$BACKUP_DIR/backup.lock"
|
LOCK="$BACKUP_DIR/backup.lock"
|
||||||
DB_NAME="jarvis_db"
|
DB_NAME="jarvis_db"
|
||||||
DB_USER="jarvis_user"
|
DB_USER="jarvis_user"
|
||||||
DB_PASS="J4rv1s_Pr0t0c0l_2026!"
|
DB_PASS="${JARVIS_DB_PASS:?DB pass unset - see /etc/jarvis/db.env}"
|
||||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||||
OUTFILE="$BACKUP_DIR/jarvis_backup_${TIMESTAMP}.tar.gz"
|
OUTFILE="$BACKUP_DIR/jarvis_backup_${TIMESTAMP}.tar.gz"
|
||||||
TMPDIR=$(mktemp -d)
|
TMPDIR=$(mktemp -d)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
[ -r /etc/jarvis/db.env ] && . /etc/jarvis/db.env
|
||||||
# JARVIS Auto-Deploy Runner — processes GitHub webhook queue every minute.
|
# JARVIS Auto-Deploy Runner — processes GitHub webhook queue every minute.
|
||||||
# Validates PHP syntax before deploying; auto-reverts on bad code.
|
# Validates PHP syntax before deploying; auto-reverts on bad code.
|
||||||
# Restarts OLS after JARVIS deploys to pick up PHP changes.
|
# Restarts OLS after JARVIS deploys to pick up PHP changes.
|
||||||
@@ -64,7 +65,7 @@ while IFS= read -r path; do
|
|||||||
fi
|
fi
|
||||||
# Insert alert into JARVIS DB
|
# Insert alert into JARVIS DB
|
||||||
BAD_ESCAPED=$(printf '%s' "$BAD_FILE" | sed "s/'/\\\\\\'/g")
|
BAD_ESCAPED=$(printf '%s' "$BAD_FILE" | sed "s/'/\\\\\\'/g")
|
||||||
mysql -u jarvis_user -pJ4rv1s_Pr0t0c0l_2026! jarvis_db -se \
|
mysql -u jarvis_user -p"$JARVIS_DB_PASS" jarvis_db -se \
|
||||||
"INSERT INTO alerts (alert_type,title,message,severity)
|
"INSERT INTO alerts (alert_type,title,message,severity)
|
||||||
VALUES ('deploy_fail','Deploy reverted: syntax error',
|
VALUES ('deploy_fail','Deploy reverted: syntax error',
|
||||||
'PHP syntax error in $BAD_ESCAPED. Commit $AFTER was reverted and force-pushed to GitHub.','critical');" 2>/dev/null
|
'PHP syntax error in $BAD_ESCAPED. Commit $AFTER was reverted and force-pushed to GitHub.','critical');" 2>/dev/null
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
[ -r /etc/jarvis/db.env ] && . /etc/jarvis/db.env
|
||||||
# JARVIS Self-Healing Watchdog — runs every 5 min via root cron
|
# JARVIS Self-Healing Watchdog — runs every 5 min via root cron
|
||||||
# Checks: lsws, mysql, redis, JARVIS HTTP, disk, memory
|
# Checks: lsws, mysql, redis, JARVIS HTTP, disk, memory
|
||||||
# Auto-heals: restarts failed services, restarts offline Proxmox VM agents
|
# Auto-heals: restarts failed services, restarts offline Proxmox VM agents
|
||||||
# Logs to: /home/jarvis.orbishosting.com/logs/watchdog.log
|
# Logs to: /home/jarvis.orbishosting.com/logs/watchdog.log
|
||||||
|
|
||||||
LOG=/home/jarvis.orbishosting.com/logs/watchdog.log
|
LOG=/home/jarvis.orbishosting.com/logs/watchdog.log
|
||||||
MYSQL="mysql -u jarvis_user -pJ4rv1s_Pr0t0c0l_2026! jarvis_db -se"
|
MYSQL="mysql -u jarvis_user -p$JARVIS_DB_PASS jarvis_db -se"
|
||||||
TS() { date '+%Y-%m-%d %H:%M:%S'; }
|
TS() { date '+%Y-%m-%d %H:%M:%S'; }
|
||||||
|
|
||||||
log() { echo "[$(TS)] $1" >> "$LOG"; }
|
log() { echo "[$(TS)] $1" >> "$LOG"; }
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# JARVIS Arc Reactor — required secrets. Copy to /etc/jarvis-arc/reactor.env
|
||||||
|
# (root:www-data 0640), loaded by systemd EnvironmentFile. Not committed.
|
||||||
|
JARVIS_DB_PASS=your-db-password
|
||||||
|
CLAUDE_API_KEY=sk-ant-...
|
||||||
|
GROQ_API_KEY=gsk_...
|
||||||
|
GMAIL_PASS=your-gmail-app-password
|
||||||
|
ICLOUD_PASS=your-icloud-app-password
|
||||||
+5
-5
@@ -39,24 +39,24 @@ VERSION = "9.0.0"
|
|||||||
DB_HOST = "localhost"
|
DB_HOST = "localhost"
|
||||||
DB_PORT = 3306
|
DB_PORT = 3306
|
||||||
DB_USER = "jarvis_user"
|
DB_USER = "jarvis_user"
|
||||||
DB_PASS = "J4rv1s_Pr0t0c0l_2026!"
|
DB_PASS = os.environ.get("JARVIS_DB_PASS", "")
|
||||||
DB_NAME = "jarvis_db"
|
DB_NAME = "jarvis_db"
|
||||||
LOG_FILE = "/var/log/jarvis/arc_reactor.log"
|
LOG_FILE = "/var/log/jarvis/arc_reactor.log"
|
||||||
POLL_INTERVAL = 3
|
POLL_INTERVAL = 3
|
||||||
HEARTBEAT_INTERVAL = 30
|
HEARTBEAT_INTERVAL = 30
|
||||||
|
|
||||||
CLAUDE_API_KEY = "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"
|
CLAUDE_API_KEY = os.environ.get("CLAUDE_API_KEY", "")
|
||||||
CLAUDE_MODEL = "claude-sonnet-4-6"
|
CLAUDE_MODEL = "claude-sonnet-4-6"
|
||||||
GROQ_API_KEY = "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"
|
GROQ_API_KEY = os.environ.get("GROQ_API_KEY", "")
|
||||||
GROQ_MODEL = "llama-3.3-70b-versatile"
|
GROQ_MODEL = "llama-3.3-70b-versatile"
|
||||||
OLLAMA_HOST = "http://10.48.200.210:11434"
|
OLLAMA_HOST = "http://10.48.200.210:11434"
|
||||||
OLLAMA_MODEL = "llama3.1:8b"
|
OLLAMA_MODEL = "llama3.1:8b"
|
||||||
OLLAMA_VISION_MODEL = os.environ.get("OLLAMA_VISION_MODEL", "") # e.g. "llava" or "moondream" -- empty = disabled
|
OLLAMA_VISION_MODEL = os.environ.get("OLLAMA_VISION_MODEL", "") # e.g. "llava" or "moondream" -- empty = disabled
|
||||||
|
|
||||||
GMAIL_USER = "myronblair@gmail.com"
|
GMAIL_USER = "myronblair@gmail.com"
|
||||||
GMAIL_PASS = "demsvdylwweacbcx"
|
GMAIL_PASS = os.environ.get("GMAIL_PASS", "")
|
||||||
ICLOUD_USER = "myronblair@icloud.com"
|
ICLOUD_USER = "myronblair@icloud.com"
|
||||||
ICLOUD_PASS = "yxfi-yvzu-geqk-japr"
|
ICLOUD_PASS = os.environ.get("ICLOUD_PASS", "")
|
||||||
|
|
||||||
# ── LOGGING ───────────────────────────────────────────────────────────────────
|
# ── LOGGING ───────────────────────────────────────────────────────────────────
|
||||||
os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
|
os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
|
||||||
|
|||||||
@@ -663,7 +663,7 @@ Webhook secret: `4c8805f0285214ff0a0602b5880270b935f36a896946c7f1`
|
|||||||
|
|
||||||
### Agent System
|
### Agent System
|
||||||
Agents installed on all servers — phone home every 10s (heartbeat) / 30s (metrics).
|
Agents installed on all servers — phone home every 10s (heartbeat) / 30s (metrics).
|
||||||
Registration key: `f846a9aaf7ce9a61742c63c87c4186052a71d2a580c65518`
|
Registration key: `[rotated 2026-07-07 — stored in api/config.php on VM211, not documented here]`
|
||||||
Install command: `curl -sk http://10.48.200.211/install-agent.sh | bash -s <hostname> <linux|proxmox>`
|
Install command: `curl -sk http://10.48.200.211/install-agent.sh | bash -s <hostname> <linux|proxmox>`
|
||||||
|
|
||||||
### Self-Healing Watchdog
|
### Self-Healing Watchdog
|
||||||
@@ -918,7 +918,7 @@ sshpass -p 'Joker1974!!!' ssh root@10.48.200.90 \
|
|||||||
| Service | Key |
|
| Service | Key |
|
||||||
|---------|-----|
|
|---------|-----|
|
||||||
| GitHub PAT | `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` (rotated 2026-07-05, scopes `repo`+`workflow`) |
|
| GitHub PAT | `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` (rotated 2026-07-05, scopes `repo`+`workflow`) |
|
||||||
| JARVIS Agent Registration | `f846a9aaf7ce9a61742c63c87c4186052a71d2a580c65518` |
|
| JARVIS Agent Registration | `[rotated 2026-07-07 — stored in api/config.php on VM211, not documented here]` |
|
||||||
| Proxmox API Token | `root@pam!jarvis=c45b5feb-f9a9-445d-a626-14fbb959f78b` |
|
| Proxmox API Token | `root@pam!jarvis=c45b5feb-f9a9-445d-a626-14fbb959f78b` |
|
||||||
| HA Long-lived Token | `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzNmI0N2I1Njk5ZGQ0MTQ2ODMwZWFmYjZiYTQ1MjJkMSIsImlhdCI6MTc4MDIwMzU5NCwiZXhwIjoyMDk1NTYzNTk0fQ.sYRok-jRDlA4lFgWxLQELcEjkJNGQdprk6ZziLwLtXE` |
|
| HA Long-lived Token | `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzNmI0N2I1Njk5ZGQ0MTQ2ODMwZWFmYjZiYTQ1MjJkMSIsImlhdCI6MTc4MDIwMzU5NCwiZXhwIjoyMDk1NTYzNTk0fQ.sYRok-jRDlA4lFgWxLQELcEjkJNGQdprk6ZziLwLtXE` |
|
||||||
| Sonarr API | `b43e04350a594846b4ee95261c29e9e0` |
|
| Sonarr API | `b43e04350a594846b4ee95261c29e9e0` |
|
||||||
|
|||||||
@@ -21,7 +21,14 @@ JARVIS_HOST=""
|
|||||||
INSTALL_DIR="/opt/jarvis-agent"
|
INSTALL_DIR="/opt/jarvis-agent"
|
||||||
CONFIG_DIR="/etc/jarvis-agent"
|
CONFIG_DIR="/etc/jarvis-agent"
|
||||||
STATE_DIR="/var/lib/jarvis-agent"
|
STATE_DIR="/var/lib/jarvis-agent"
|
||||||
REG_KEY="f846a9aaf7ce9a61742c63c87c4186052a71d2a580c65518"
|
REG_KEY="${JARVIS_REG_KEY:-}"
|
||||||
|
if [ -z "$REG_KEY" ] && [ -r /dev/tty ]; then
|
||||||
|
read -rp "Enter JARVIS registration key: " REG_KEY </dev/tty
|
||||||
|
fi
|
||||||
|
if [ -z "$REG_KEY" ]; then
|
||||||
|
echo "ERROR: registration key required (set JARVIS_REG_KEY env var or enter at prompt)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
SERVICE_FILE="/etc/systemd/system/jarvis-agent.service"
|
SERVICE_FILE="/etc/systemd/system/jarvis-agent.service"
|
||||||
|
|
||||||
echo "=== JARVIS Agent Installer v3.0 ==="
|
echo "=== JARVIS Agent Installer v3.0 ==="
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ $_e1 = $_earlyParts[1] ?? '';
|
|||||||
$_skipSession = match(true) {
|
$_skipSession = match(true) {
|
||||||
$_e0 === 'ping' => true,
|
$_e0 === 'ping' => true,
|
||||||
$_e0 === 'netscan' => true,
|
$_e0 === 'netscan' => true,
|
||||||
$_e0 === 'agent' && !in_array($_e1, ['list','status','myip'], true) => true,
|
$_e0 === 'agent' && !in_array($_e1, ['list','status','myip','regkey'], true) => true,
|
||||||
default => false,
|
default => false,
|
||||||
};
|
};
|
||||||
if (!$_skipSession) {
|
if (!$_skipSession) {
|
||||||
|
|||||||
@@ -432,12 +432,16 @@ function renderAgentsTab(agents, metrics) {
|
|||||||
}).join('');
|
}).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
function openAgentModal() {
|
async function openAgentModal() {
|
||||||
const os = detectOS();
|
const os = detectOS();
|
||||||
const title = document.getElementById('agentModalTitle');
|
const title = document.getElementById('agentModalTitle');
|
||||||
const content = document.getElementById('agentModalContent');
|
const content = document.getElementById('agentModalContent');
|
||||||
const modal = document.getElementById('agentModal');
|
const modal = document.getElementById('agentModal');
|
||||||
const regKey = 'f846a9aaf7ce9a61742c63c87c4186052a71d2a580c65518';
|
let regKey = '<YOUR-REGISTRATION-KEY>';
|
||||||
|
try {
|
||||||
|
const rkResp = await fetch('/api/agent/regkey');
|
||||||
|
if (rkResp.ok) { const rk = await rkResp.json(); if (rk.registration_key) regKey = rk.registration_key; }
|
||||||
|
} catch (e) { /* not logged in — placeholder stays */ }
|
||||||
const jUrl = window.location.origin;
|
const jUrl = window.location.origin;
|
||||||
// Fixed 2026-07-07: this used to be hardcoded to https://jarvis.orbishosting.com/agent,
|
// Fixed 2026-07-07: this used to be hardcoded to https://jarvis.orbishosting.com/agent,
|
||||||
// which isn't reachable from outside the LAN at all (no FortiGate VIP forwards the
|
// which isn't reachable from outside the LAN at all (no FortiGate VIP forwards the
|
||||||
@@ -480,10 +484,9 @@ function openAgentModal() {
|
|||||||
},
|
},
|
||||||
linux: {
|
linux: {
|
||||||
label:'Linux',
|
label:'Linux',
|
||||||
// install.sh takes positional args (hostname, agent_type) and reads the
|
// install.sh takes positional args (hostname, agent_type); JARVIS URL and
|
||||||
// JARVIS URL from an env var — the registration key is already baked in,
|
// registration key come from env vars (key is no longer baked into the script).
|
||||||
// no --key flag exists.
|
cmd:'curl -sSL '+baseUrl+'/install.sh | JARVIS_URL='+jUrl+' JARVIS_REG_KEY=\''+regKey+'\' bash -s -- $(hostname) linux',
|
||||||
cmd:'curl -sSL '+baseUrl+'/install.sh | JARVIS_URL='+jUrl+' bash -s -- $(hostname) linux',
|
|
||||||
dl: baseUrl+'/install.sh',
|
dl: baseUrl+'/install.sh',
|
||||||
note:'Run in terminal (sudo). Installs as a systemd service.'
|
note:'Run in terminal (sudo). Installs as a systemd service.'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,7 +21,14 @@ JARVIS_HOST=""
|
|||||||
INSTALL_DIR="/opt/jarvis-agent"
|
INSTALL_DIR="/opt/jarvis-agent"
|
||||||
CONFIG_DIR="/etc/jarvis-agent"
|
CONFIG_DIR="/etc/jarvis-agent"
|
||||||
STATE_DIR="/var/lib/jarvis-agent"
|
STATE_DIR="/var/lib/jarvis-agent"
|
||||||
REG_KEY="f846a9aaf7ce9a61742c63c87c4186052a71d2a580c65518"
|
REG_KEY="${JARVIS_REG_KEY:-}"
|
||||||
|
if [ -z "$REG_KEY" ] && [ -r /dev/tty ]; then
|
||||||
|
read -rp "Enter JARVIS registration key: " REG_KEY </dev/tty
|
||||||
|
fi
|
||||||
|
if [ -z "$REG_KEY" ]; then
|
||||||
|
echo "ERROR: registration key required (set JARVIS_REG_KEY env var or enter at prompt)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
SERVICE_FILE="/etc/systemd/system/jarvis-agent.service"
|
SERVICE_FILE="/etc/systemd/system/jarvis-agent.service"
|
||||||
|
|
||||||
echo "=== JARVIS Agent Installer v3.0 ==="
|
echo "=== JARVIS Agent Installer v3.0 ==="
|
||||||
|
|||||||
+41
-20
@@ -1,30 +1,51 @@
|
|||||||
<?php
|
<?php
|
||||||
ini_set('session.cache_limiter', '');
|
ini_set('session.cache_limiter', '');
|
||||||
header('Cache-Control: no-store, no-cache, must-revalidate, no-transform');
|
header('Cache-Control: no-store, no-cache, must-revalidate, no-transform');
|
||||||
|
require_once __DIR__ . '/../api/config.php';
|
||||||
session_start();
|
session_start();
|
||||||
if (!empty($_SESSION['jarvis_token'])) { header('Location: /'); exit; }
|
if (!empty($_SESSION['jarvis_token'])) { header('Location: /'); exit; }
|
||||||
$error = '';
|
$error = '';
|
||||||
|
// ── Login rate limiting (Redis, per client IP) ────────────────────────────────
|
||||||
|
// Blocks brute force: 10 failed attempts within 15 min -> locked out for 15 min.
|
||||||
|
$clientIp = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? 'unknown';
|
||||||
|
$clientIp = trim(explode(',', $clientIp)[0]);
|
||||||
|
$rl = null;
|
||||||
|
try {
|
||||||
|
$rl = new Redis();
|
||||||
|
$rl->connect('127.0.0.1', 6379, 1.5);
|
||||||
|
} catch (Throwable $e) { $rl = null; } // fail open if Redis is down
|
||||||
|
$rlKey = 'login_fail:' . $clientIp;
|
||||||
|
$RL_MAX = 10; $RL_WINDOW = 900;
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$u = trim($_POST['username'] ?? '');
|
$fails = ($rl && $rl->exists($rlKey)) ? (int)$rl->get($rlKey) : 0;
|
||||||
$p = $_POST['password'] ?? '';
|
if ($fails >= $RL_MAX) {
|
||||||
if ($u && $p) {
|
$error = 'TOO MANY ATTEMPTS — LOCKED';
|
||||||
$pdo = new PDO('mysql:host=localhost;dbname=jarvis_db;charset=utf8mb4',
|
} else {
|
||||||
'jarvis_user', 'J4rv1s_Pr0t0c0l_2026!',
|
$u = trim($_POST['username'] ?? '');
|
||||||
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
|
$p = $_POST['password'] ?? '';
|
||||||
$row = $pdo->prepare('SELECT * FROM users WHERE username=? LIMIT 1');
|
if ($u && $p) {
|
||||||
$row->execute([$u]);
|
$pdo = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8mb4',
|
||||||
$user = $row->fetch(PDO::FETCH_ASSOC);
|
DB_USER, DB_PASS,
|
||||||
if ($user && password_verify($p, $user['password_hash'])) {
|
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
|
||||||
$token = bin2hex(random_bytes(32));
|
$row = $pdo->prepare('SELECT * FROM users WHERE username=? LIMIT 1');
|
||||||
$_SESSION['jarvis_token'] = $token;
|
$row->execute([$u]);
|
||||||
$_SESSION['jarvis_user_id'] = $user['id'];
|
$user = $row->fetch(PDO::FETCH_ASSOC);
|
||||||
$_SESSION['jarvis_name'] = $user['display_name'];
|
if ($user && password_verify($p, $user['password_hash'])) {
|
||||||
$pdo->prepare('UPDATE users SET last_seen=NOW() WHERE id=?')->execute([$user['id']]);
|
if ($rl) $rl->del($rlKey);
|
||||||
header('Location: /');
|
session_regenerate_id(true);
|
||||||
exit;
|
$token = bin2hex(random_bytes(32));
|
||||||
}
|
$_SESSION['jarvis_token'] = $token;
|
||||||
$error = 'ACCESS DENIED';
|
$_SESSION['jarvis_user_id'] = $user['id'];
|
||||||
} else { $error = 'ENTER CREDENTIALS'; }
|
$_SESSION['jarvis_name'] = $user['display_name'];
|
||||||
|
$pdo->prepare('UPDATE users SET last_seen=NOW() WHERE id=?')->execute([$user['id']]);
|
||||||
|
header('Location: /');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
if ($rl) { $rl->incr($rlKey); $rl->expire($rlKey, $RL_WINDOW); }
|
||||||
|
$error = 'ACCESS DENIED';
|
||||||
|
} else { $error = 'ENTER CREDENTIALS'; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?><!DOCTYPE html>
|
?><!DOCTYPE html>
|
||||||
<html lang="en"><head>
|
<html lang="en"><head>
|
||||||
|
|||||||
Reference in New Issue
Block a user