diff --git a/.gitignore b/.gitignore index be5cd4b..318f83b 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ yarn-error.log /.nova /.vscode /.zed +/.vite diff --git a/.vite/deps/_metadata.json b/.vite/deps/_metadata.json new file mode 100644 index 0000000..71b5d08 --- /dev/null +++ b/.vite/deps/_metadata.json @@ -0,0 +1,8 @@ +{ + "hash": "9e76e24f", + "configHash": "16a1459d", + "lockfileHash": "e3b0c442", + "browserHash": "8e8bb46e", + "optimized": {}, + "chunks": {} +} \ No newline at end of file diff --git a/.vite/deps/package.json b/.vite/deps/package.json new file mode 100644 index 0000000..3dbc1ca --- /dev/null +++ b/.vite/deps/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/Dockerfile.dev b/Dockerfile.dev index 1ef1399..2206283 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -63,66 +63,54 @@ EOF # Install Node development dependencies globally RUN npm install -g nodemon -# Create startup script +# Create startup script for development (runs as host user) RUN cat > /start.sh <<'EOF' #!/bin/sh set -e -# Ensure all required Laravel directories exist -mkdir -p /app/bootstrap/cache -mkdir -p /app/storage/app/public -mkdir -p /app/storage/framework/cache/data -mkdir -p /app/storage/framework/sessions -mkdir -p /app/storage/framework/testing -mkdir -p /app/storage/framework/views -mkdir -p /app/storage/logs +# Create .env file if it doesn't exist +if [ ! -f ".env" ]; then + echo "Creating .env file from .env.example..." + cp .env.example .env +fi -# Set permissions - use www-data user -chown -R www-data:www-data /app/storage /app/bootstrap/cache -chmod -R 775 /app/storage /app/bootstrap/cache - -# Create cache directories with proper permissions -mkdir -p /app/storage/framework/cache/data -chown -R www-data:www-data /app/storage/framework/cache -chmod -R 775 /app/storage/framework/cache - -# Check if vendor exists in the volume +# Install dependencies if volumes are empty if [ ! -f "vendor/autoload.php" ]; then echo "Installing composer dependencies..." composer install -else - echo "Composer dependencies found, skipping install..." fi -# Check if node_modules exists in the volume +# Handle node_modules with care - clean install if having issues if [ ! -f "node_modules/.bin/vite" ]; then echo "Installing npm dependencies..." - npm install + # Clean any remnants first + rm -rf node_modules/.* 2>/dev/null || true + rm -rf /app/.npm 2>/dev/null || true + # Fresh install with cache in tmp to avoid permission issues + npm install --cache /tmp/.npm else - echo "Node modules found, skipping npm install..." + echo "Node modules already installed, skipping npm install" fi -# Run Laravel commands as www-data to avoid permission issues -su -s /bin/sh www-data -c "php artisan config:clear" || true -su -s /bin/sh www-data -c "php artisan cache:clear" || true -su -s /bin/sh www-data -c "php artisan route:clear" || true -su -s /bin/sh www-data -c "php artisan view:clear" || true +# Clear Laravel caches +php artisan config:clear || true +php artisan cache:clear || true -# Run migrations if database is ready +# Wait for database and run migrations echo "Waiting for database..." sleep 5 -su -s /bin/sh www-data -c "php artisan migrate --force" || echo "Migration failed or not needed" +php artisan migrate --force || echo "Migration failed or not needed" # Generate app key if not set if [ -z "$APP_KEY" ] || [ "$APP_KEY" = "base64:YOUR_KEY_HERE" ]; then echo "Generating application key..." - su -s /bin/sh www-data -c "php artisan key:generate" + php artisan key:generate fi -# Start Vite dev server in background for hot reload +# Start Vite dev server in background npm run dev & -# Start FrankenPHP (runs as root in dev for simplicity) +# Start FrankenPHP exec frankenphp run --config /etc/caddy/Caddyfile EOF diff --git a/app/Livewire/Auth/Login.php b/app/Livewire/Auth/Login.php index 2fb1e50..91b50e0 100644 --- a/app/Livewire/Auth/Login.php +++ b/app/Livewire/Auth/Login.php @@ -31,6 +31,6 @@ public function login() public function render() { return view('livewire.auth.login') - ->layout('layouts.guest'); + ->layout('components.layouts.guest'); } } \ No newline at end of file diff --git a/app/Livewire/Auth/Register.php b/app/Livewire/Auth/Register.php index 06ab32d..eb74e0a 100644 --- a/app/Livewire/Auth/Register.php +++ b/app/Livewire/Auth/Register.php @@ -2,7 +2,7 @@ namespace App\Livewire\Auth; -use App\Models\User; +use App\Models\Planner; use Livewire\Component; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; @@ -13,38 +13,25 @@ class Register extends Component #[Rule('required|string|max:255')] public $name = ''; - #[Rule('required|email|unique:users,email')] + #[Rule('required|email|unique:planners,email')] public $email = ''; #[Rule('required|min:8|confirmed')] public $password = ''; public $password_confirmation = ''; - - #[Rule('required|exists:planners,id')] - public $planner_id = ''; - - public function mount() - { - // Set default planner_id if only one exists - $planners = \App\Models\Planner::all(); - if ($planners->count() === 1) { - $this->planner_id = $planners->first()->id; - } - } public function register() { $this->validate(); - $user = User::create([ + $planner = Planner::create([ 'name' => $this->name, 'email' => $this->email, 'password' => Hash::make($this->password), - 'planner_id' => $this->planner_id, ]); - Auth::login($user); + Auth::login($planner); session()->regenerate(); return redirect()->route('dashboard'); @@ -52,8 +39,7 @@ public function register() public function render() { - return view('livewire.auth.register', [ - 'planners' => \App\Models\Planner::all() - ])->layout('layouts.guest'); + return view('livewire.auth.register') + ->layout('components.layouts.guest'); } } \ No newline at end of file diff --git a/bootstrap/app.php b/bootstrap/app.php index 265ca64..5c511ee 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -25,7 +25,8 @@ health: '/up', ) ->withMiddleware(function (Middleware $middleware) { - $middleware->append(ForceJsonResponse::class); + // Apply ForceJsonResponse only to API routes + $middleware->api(ForceJsonResponse::class); $middleware->append(StartSession::class); $middleware->append(HandleCors::class); }) diff --git a/build-push.sh b/build-push.sh new file mode 100755 index 0000000..532b43f --- /dev/null +++ b/build-push.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# Build and push production image to Codeberg + +set -e + +# Configuration +REGISTRY="codeberg.org" +NAMESPACE="lvl0" +IMAGE_NAME="dish-planner" +TAG="${1:-latest}" + +echo "๐Ÿ”จ Building production image..." +podman build -f Dockerfile -t ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${TAG} . + +echo "๐Ÿ“ค Pushing to Codeberg registry..." +echo "Please ensure you're logged in to Codeberg:" +echo " podman login codeberg.org" + +podman push ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${TAG} + +echo "โœ… Done! Image pushed to ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${TAG}" +echo "" +echo "To deploy in production:" +echo "1. Copy docker-compose.prod.yml to your server" +echo "2. Set required environment variables:" +echo " - APP_KEY (generate with: openssl rand -base64 32)" +echo " - APP_URL" +echo " - DB_DATABASE, DB_USERNAME, DB_PASSWORD, DB_ROOT_PASSWORD" +echo "3. Run: docker-compose -f docker-compose.prod.yml up -d" \ No newline at end of file diff --git a/build_and_push.sh b/build_and_push.sh new file mode 100755 index 0000000..b3ce7d4 --- /dev/null +++ b/build_and_push.sh @@ -0,0 +1,3 @@ +#!/bin/bash +docker build -t 192.168.178.152:50114/dishplanner-backend . +docker push 192.168.178.152:50114/dishplanner-backend diff --git a/docker-compose.override.yml b/docker-compose.override.yml deleted file mode 100644 index 963e70b..0000000 --- a/docker-compose.override.yml +++ /dev/null @@ -1,25 +0,0 @@ -services: - backend: - volumes: - - '.:/var/www/html:Z' - - mysql: - image: 'docker.io/library/mysql:8.0' - environment: - MYSQL_USER: '${DB_USERNAME}' - MYSQL_PASSWORD: '${DB_PASSWORD}' - volumes: - - 'sail-mysql:/var/lib/mysql:Z' - - frontend: - image: 'docker.io/library/node:22-alpine' - working_dir: /app - command: sh -c "npm install && npm run dev -- --host" - volumes: - - '../frontend:/app:Z' - ports: - - '5173:5173' - networks: - - sail - depends_on: - - backend diff --git a/docker-compose.yml b/docker-compose.yml index b8b37f2..bf97334 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,6 +8,8 @@ services: dockerfile: Dockerfile.dev container_name: dishplanner_app restart: unless-stopped + # Remove user directive to run as root in container + # The container will handle permissions internally ports: - "8000:8000" # Laravel app - "5173:5173" # Vite dev server @@ -38,13 +40,11 @@ services: # Vite VITE_HOST: "0.0.0.0" volumes: - # Mount entire project for hot reload - - .:/app - # Persist vendor and node_modules for performance + # Mount entire project for hot reload with SELinux context + - .:/app:Z + # Named volumes for performance and permission isolation - app_vendor:/app/vendor - app_node_modules:/app/node_modules - # Persist storage - - app_storage:/app/storage depends_on: - db networks: @@ -101,5 +101,4 @@ networks: volumes: db_data: app_vendor: - app_node_modules: - app_storage: \ No newline at end of file + app_node_modules: \ No newline at end of file diff --git a/public/.htaccess b/public/.htaccess old mode 100644 new mode 100755 diff --git a/public/favicon.ico b/public/favicon.ico old mode 100644 new mode 100755 diff --git a/public/index.php b/public/index.php old mode 100644 new mode 100755 diff --git a/public/robots.txt b/public/robots.txt old mode 100644 new mode 100755 diff --git a/resources/views/layouts/app.blade.php b/resources/views/components/layouts/app.blade.php similarity index 100% rename from resources/views/layouts/app.blade.php rename to resources/views/components/layouts/app.blade.php diff --git a/resources/views/layouts/guest.blade.php b/resources/views/components/layouts/guest.blade.php similarity index 100% rename from resources/views/layouts/guest.blade.php rename to resources/views/components/layouts/guest.blade.php diff --git a/resources/views/livewire/auth/register.blade.php b/resources/views/livewire/auth/register.blade.php index 1cc57dc..28f444f 100644 --- a/resources/views/livewire/auth/register.blade.php +++ b/resources/views/livewire/auth/register.blade.php @@ -23,20 +23,6 @@ class="w-full p-2 mb-4 border rounded bg-gray-600 border-secondary text-gray-100 @error('email') {{ $message }} @enderror - @if($planners->count() > 1) -
- - - @error('planner_id') {{ $message }} @enderror -
- @endif
diff --git a/shell.nix b/shell.nix index 18fbe4f..3f4487b 100644 --- a/shell.nix +++ b/shell.nix @@ -23,26 +23,32 @@ pkgs.mkShell { ]; shellHook = '' + # Export user/group IDs for Docker permission matching + export USER_ID=$(id -u) + export GROUP_ID=$(id -g) + # Use keep-id for proper permission mapping in rootless podman + export PODMAN_USERNS=keep-id + # Define helper functions dev-rebuild() { echo "๐Ÿ”จ Rebuilding development environment..." - podman-compose down -v - podman-compose build --no-cache app - podman-compose up -d + PODMAN_USERNS=keep-id podman-compose down -v + PODMAN_USERNS=keep-id podman-compose build --no-cache app + PODMAN_USERNS=keep-id podman-compose up -d echo "โœ… Rebuild complete! Check logs with: dev-logs" } dev-rebuild-quick() { echo "โšก Quick rebuild (keeping volumes)..." - podman-compose down - podman-compose build app - podman-compose up -d + PODMAN_USERNS=keep-id podman-compose down + PODMAN_USERNS=keep-id podman-compose build app + PODMAN_USERNS=keep-id podman-compose up -d echo "โœ… Quick rebuild complete!" } dev-up() { echo "๐Ÿš€ Starting development environment..." - podman-compose up -d + PODMAN_USERNS=keep-id podman-compose up -d echo "โœ… Dev environment started!" } @@ -70,6 +76,13 @@ pkgs.mkShell { podman-compose exec app php artisan "$@" } + dev-fix-permissions() { + echo "๐Ÿ”ง Fixing file permissions..." + echo "This will require sudo to fix Docker-created files" + sudo chown -R $(id -u):$(id -g) storage/ bootstrap/cache/ vendor/ node_modules/ 2>/dev/null || true + echo "โœ… Permissions fixed!" + } + prod-build() { local TAG="''${1:-latest}" local REGISTRY="codeberg.org" @@ -125,6 +138,7 @@ pkgs.mkShell { echo " dev-logs [svc] - Follow logs (default: all)" echo " dev-shell - Enter app container" echo " dev-artisan - Run artisan commands" + echo " dev-fix-permissions - Fix Docker-created file permissions" echo "" echo "Production commands:" echo " prod-login - Login to Codeberg registry" diff --git a/storage/app/.gitignore b/storage/app/.gitignore old mode 100644 new mode 100755 diff --git a/storage/app/private/.gitignore b/storage/app/private/.gitignore old mode 100644 new mode 100755 diff --git a/storage/app/public/.gitignore b/storage/app/public/.gitignore old mode 100644 new mode 100755 diff --git a/storage/framework/.gitignore b/storage/framework/.gitignore old mode 100644 new mode 100755 diff --git a/storage/framework/cache/.gitignore b/storage/framework/cache/.gitignore old mode 100644 new mode 100755 diff --git a/storage/framework/cache/data/.gitignore b/storage/framework/cache/data/.gitignore old mode 100644 new mode 100755 diff --git a/storage/framework/sessions/.gitignore b/storage/framework/sessions/.gitignore old mode 100644 new mode 100755 diff --git a/storage/framework/testing/.gitignore b/storage/framework/testing/.gitignore old mode 100644 new mode 100755 diff --git a/storage/framework/views/.gitignore b/storage/framework/views/.gitignore old mode 100644 new mode 100755 diff --git a/update.sh b/update.sh new file mode 100755 index 0000000..7320639 --- /dev/null +++ b/update.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -e + +echo "๐Ÿ”„ Pulling latest backend changes..." +git pull origin main + +echo "๐Ÿ“ฆ Installing PHP dependencies..." +composer install --no-interaction --prefer-dist --optimize-autoloader + +echo "๐Ÿ—„๏ธ Running migrations..." +php artisan migrate --force + +echo "๐Ÿงน Clearing and caching config..." +php artisan config:cache +php artisan route:cache +php artisan view:cache + +echo "โœ… Backend update complete!"