diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0e90053 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,18 @@ +.git +.github +docs +tests +vendor +node_modules +.phpunit.cache +.phpunit.result.cache +composer.lock +docker/host-app/vendor +docker/host-app/node_modules +docker/host-app/public/build +docker/host-app/bootstrap/cache +docker/host-app/storage/framework/cache/data +docker/host-app/storage/framework/sessions +docker/host-app/storage/framework/views +docker/host-app/storage/logs +docker/host-app/database/database.sqlite diff --git a/.gitattributes b/.gitattributes index 8dc9278..5a9bb9e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,17 @@ -# Force LF line endings for all text files * text=auto eol=lf + +*.sh text eol=lf +Dockerfile* text eol=lf +*.yml text eol=lf +*.yaml text eol=lf +*.php text eol=lf +*.js text eol=lf +*.json text eol=lf +*.blade.php text eol=lf +*.css text eol=lf + +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..432e9ea --- /dev/null +++ b/docker/README.md @@ -0,0 +1,13 @@ +# Escalated WordPress โ€” Docker demo (scaffold, not end-to-end) + +Draft. Mounts the plugin into a stock `wordpress:6.6-php8.3-apache` image alongside MariaDB and Mailpit. + +**Differs from the other escalated-* demos: uses MariaDB, not Postgres.** WordPress is a MySQL-family application and swapping its DB layer is out of scope for a demo. + +**Not end-to-end.** Missing: + +- WP-CLI based setup script: `wp core install`, `wp user create`, plugin activation, seed demo tickets via an `escalated` CLI subcommand if one exists. +- `/demo` picker โ€” could be a WP page template that lists seeded users with WP auth cookie click-login via `wp_set_auth_cookie()`. +- Environment to reset the whole WP install on each `docker compose up` so the demo is reproducible. + +See the PR body for the punch list. diff --git a/docker/compose.yml b/docker/compose.yml new file mode 100644 index 0000000..ebde77e --- /dev/null +++ b/docker/compose.yml @@ -0,0 +1,63 @@ +name: escalated-wordpress-demo + +services: + wordpress: + image: wordpress:6.6-php8.3-apache + ports: + - "${APP_PORT:-8090}:80" + environment: + WORDPRESS_DB_HOST: db:3306 + WORDPRESS_DB_USER: escalated + WORDPRESS_DB_PASSWORD: escalated + WORDPRESS_DB_NAME: escalated + WORDPRESS_DEBUG: "1" + WORDPRESS_CONFIG_EXTRA: | + define('WP_ENVIRONMENT_TYPE', 'development'); + volumes: + - ../:/var/www/html/wp-content/plugins/escalated-wordpress:ro + - wp-data:/var/www/html + depends_on: + db: + condition: service_healthy + + db: + # WordPress plays best with MySQL. Note this is the one escalated-* demo + # that doesn't use Postgres โ€” the WP ecosystem targets MySQL/MariaDB. + image: mariadb:11-noble + environment: + MARIADB_DATABASE: escalated + MARIADB_USER: escalated + MARIADB_PASSWORD: escalated + MARIADB_ROOT_PASSWORD: escalated + healthcheck: + test: ["CMD-SHELL", "healthcheck.sh --connect --innodb_initialized"] + interval: 3s + retries: 20 + + wpcli: + image: wordpress:cli-php8.3 + user: "33:33" + depends_on: + wordpress: + condition: service_started + db: + condition: service_healthy + volumes: + - wp-data:/var/www/html + - ../:/var/www/html/wp-content/plugins/escalated-wordpress:ro + - ./setup.sh:/setup.sh:ro + - ./demo-picker.php:/demo-picker.php:ro + environment: + WORDPRESS_DB_HOST: db:3306 + WORDPRESS_DB_USER: escalated + WORDPRESS_DB_PASSWORD: escalated + WORDPRESS_DB_NAME: escalated + command: ["sh", "/setup.sh"] + + mailpit: + image: axllent/mailpit:latest + ports: + - "${MAILPIT_PORT:-8025}:8025" + +volumes: + wp-data: diff --git a/docker/demo-picker.php b/docker/demo-picker.php new file mode 100644 index 0000000..f22d85e --- /dev/null +++ b/docker/demo-picker.php @@ -0,0 +1,67 @@ + 'ID', 'order' => 'ASC']); + echo 'Escalated ยท WP Demo'; + echo '

Escalated WordPress Demo

Click a user to log in. Every restart resets the WordPress install.

'; + foreach ($users as $u) { + $is_admin = user_can($u, 'manage_options'); + $is_agent = user_can($u, 'edit_posts') && ! $is_admin; + $badge = $is_admin ? 'Admin' : ($is_agent ? 'Agent' : ''); + echo '
'; + echo wp_nonce_field('demo_login_'.$u->ID, '_demo_nonce', true, false); + echo '
'; + } + echo '
'; + exit; + } + + if ($action === 'login' && $_SERVER['REQUEST_METHOD'] === 'POST') { + $user_id = (int) get_query_var('user_id'); + if (! wp_verify_nonce($_POST['_demo_nonce'] ?? '', 'demo_login_'.$user_id)) { + status_header(419); + exit('CSRF check failed'); + } + wp_set_auth_cookie($user_id, true); + wp_set_current_user($user_id); + wp_safe_redirect(user_can($user_id, 'edit_posts') ? admin_url() : home_url()); + exit; + } +}); + +register_activation_hook(__FILE__, function () { + flush_rewrite_rules(); +}); +register_deactivation_hook(__FILE__, function () { + flush_rewrite_rules(); +}); diff --git a/docker/setup.sh b/docker/setup.sh new file mode 100644 index 0000000..2d4ab5d --- /dev/null +++ b/docker/setup.sh @@ -0,0 +1,44 @@ +#!/bin/sh +set -eu + +# WP-CLI bootstrap script run by docker compose `wpcli` service. +# Idempotent: skips steps that already succeeded. + +cd /var/www/html + +if ! wp core is-installed --allow-root 2>/dev/null; then + echo "[demo] installing WordPress" + wp core install --allow-root \ + --url=http://localhost:${APP_PORT:-8090} \ + --title="Escalated Demo" \ + --admin_user=alice \ + --admin_email=alice@demo.test \ + --admin_password=password \ + --skip-email +fi + +if ! wp plugin is-active escalated-wordpress --allow-root 2>/dev/null; then + echo "[demo] activating escalated-wordpress plugin" + wp plugin activate escalated-wordpress --allow-root +fi + +echo "[demo] seeding additional users" +for u in "bob:bob@demo.test:editor" "carol:carol@demo.test:editor" "frank:frank@acme.example:subscriber" "grace:grace@acme.example:subscriber"; do + user=$(echo "$u" | cut -d: -f1) + email=$(echo "$u" | cut -d: -f2) + role=$(echo "$u" | cut -d: -f3) + wp user create "$user" "$email" --role="$role" --user_pass=password --allow-root 2>/dev/null \ + || echo " $user exists" +done + +echo "[demo] installing /demo picker mu-plugin" +mkdir -p /var/www/html/wp-content/mu-plugins +cp /demo-picker.php /var/www/html/wp-content/mu-plugins/demo-picker.php + +echo "[demo] enabling pretty permalinks (needed for /demo/ rewrite)" +wp option update permalink_structure "/%postname%/" --allow-root + +echo "[demo] flushing rewrite rules" +wp rewrite flush --hard --allow-root || true + +echo "[demo] WP setup complete"