diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..32d82df --- /dev/null +++ b/.env.example @@ -0,0 +1,38 @@ +# Database Configuration +DB_HOST=localhost +DB_PORT=5432 +DB_USER=party +DB_PASS=your_db_password_here +DB_NAME=partydb +DB_SSLMODE=disable + +# Or use a full DATABASE_URL instead of individual DB_* vars +# DATABASE_URL=postgres://user:pass@host:port/dbname?sslmode=disable + +# Database Connection Pool +DB_MAX_OPEN_CONNS=25 +DB_MAX_IDLE_CONNS=25 +DB_CONN_MAX_LIFETIME=30m + +# Server Configuration +PORT=3000 +TUNNEL_PORT=4000 + +# Postgres (for docker-compose) +POSTGRES_USER=party +POSTGRES_PASSWORD=secret +POSTGRES_DB=partydb + +# Ory Configuration +ORY_PROJECT_ID=your_ory_project_id_here +ORY_PROJECT_SLUG=your_ory_project_slug_here +ORY_API_URL=https://your-project-slug.projects.oryapis.com +ORY_WORKSPACE_ID=your_ory_workspace_id_here + +# Ory Hydra (if using self-hosted) +HYDRA_SYSTEM_SECRET=your_hydra_system_secret_here + +# Ory Kratos (if using self-hosted) +KRATOS_PUBLIC=http://kratos:4433 +DSN=memory +LOG_LEVEL=debug diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57e161c --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ +# Environment variables +.env +.env.local + +# Binaries +server +*.exe +*.dll +*.so +*.dylib + +# Test binaries +*.test + +# Output of the go coverage tool +*.out + +# Dependency directories +vendor/ + +# Go workspace file +go.work + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Database +*.db +*.sqlite +*.sqlite3 +pocketbase/pb_data/ + +# Logs +*.log + +# Agent-based stuff +CRUSH.md +ORY_INTEGRATION.md +START_DEV.md +.crush/ diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..35453a5 --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,556 @@ +# Deployment Guide - Test Server Setup + +This guide walks through deploying Decor by Hannah's to a test server using rclone. + +## Prerequisites + +- A Linux server (Ubuntu 20.04+ recommended) +- SSH access to the server +- rclone installed locally +- Domain name (optional, but recommended) + +## Part 1: Local Preparation + +### 1. Configure rclone + +```bash +# Configure rclone with your server +rclone config + +# Follow prompts to add an SFTP remote: +# - Type: sftp +# - Host: your-server-ip +# - User: your-ssh-user +# - Port: 22 (or your SSH port) +# - Key file: path to your SSH key (optional) + +# Name it something like "testserver" +``` + +### 2. Prepare Your Local Project + +```bash +# Make sure everything is committed +git status + +# Create a .deployignore file (optional) +cat > .deployignore << 'EOF' +.git/ +.env +*.log +tmp/ +EOF + +# Test your build locally +go build -o server cmd/server/main.go +``` + +### 3. Copy Files to Server + +```bash +# Sync project to server (excluding .git and .env) +rclone sync . testserver:/home/youruser/decor-by-hannahs \ + --exclude ".git/**" \ + --exclude ".env" \ + --exclude "*.log" \ + --exclude "tmp/**" \ + --progress + +# Or use rsync if you prefer: +# rsync -avz --exclude '.git' --exclude '.env' . user@server:/home/youruser/decor-by-hannahs/ +``` + +## Part 2: Server Setup + +### 1. SSH into Your Server + +```bash +ssh user@your-server-ip +``` + +### 2. Install Docker & Docker Compose + +```bash +# Update system +sudo apt update && sudo apt upgrade -y + +# Install Docker +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh + +# Add your user to docker group +sudo usermod -aG docker $USER + +# Install Docker Compose +sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose +sudo chmod +x /usr/local/bin/docker-compose + +# Verify installation +docker --version +docker-compose --version + +# Log out and back in for group changes to take effect +exit +ssh user@your-server-ip +``` + +### 3. Install Go + +```bash +# Download Go (check for latest version at https://go.dev/dl/) +wget https://go.dev/dl/go1.21.5.linux-amd64.tar.gz + +# Remove old Go installation (if exists) +sudo rm -rf /usr/local/go + +# Extract and install +sudo tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz + +# Add to PATH +echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc +echo 'export PATH=$PATH:$HOME/go/bin' >> ~/.bashrc +source ~/.bashrc + +# Verify installation +go version +``` + +### 4. Install Node.js (for Ory CLI) + +```bash +# Install Node.js via nvm +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash +source ~/.bashrc + +# Install latest LTS +nvm install --lts +nvm use --lts + +# Verify +node --version +npm --version +``` + +### 5. Install Ory CLI + +```bash +# Install Ory CLI globally +npm install -g @ory/cli + +# Verify +ory version +``` + +## Part 3: Application Setup + +### 1. Navigate to Project Directory + +```bash +cd ~/decor-by-hannahs +``` + +### 2. Create Environment File + +```bash +# Copy example and edit +cp .env.example .env +nano .env + +# Fill in your values: +# DATABASE_URL=postgresql://party:your_password@localhost:5432/partydb +# ORY_API_URL=http://localhost:4000 +# TUNNEL_PORT=4000 +# PORT=3000 +``` + +### 3. Start PostgreSQL with Docker + +```bash +# Start database +docker-compose up -d db + +# Wait a few seconds for DB to initialize +sleep 5 + +# Verify it's running +docker ps + +# Test connection +docker exec -it $(docker ps -q -f name=db) psql -U party -d partydb -c "SELECT version();" +``` + +### 4. Run Database Migrations + +```bash +# Apply all migrations in order +for migration in migrations/*.sql; do + echo "Applying $migration..." + docker exec -i $(docker ps -q -f name=db) psql -U party -d partydb < "$migration" +done + +# Verify tables exist +docker exec -it $(docker ps -q -f name=db) psql -U party -d partydb -c "\dt" +``` + +### 5. Build the Application + +```bash +# Install Go dependencies +go mod download + +# Build the application +go build -o server cmd/server/main.go + +# Verify binary +./server --help || echo "Binary created successfully" +``` + +## Part 4: Running the Application + +### Option A: Run Directly (for testing) + +```bash +# Terminal 1: Start Ory tunnel +./start-tunnel.sh +# Or manually: +# ory tunnel --dev --project http://localhost:3000 + +# Terminal 2: Start the application +./server + +# Or run in background: +nohup ./server > app.log 2>&1 & +``` + +### Option B: Run with systemd (recommended for production-like setup) + +#### 1. Create Ory Tunnel Service + +```bash +sudo nano /etc/systemd/system/ory-tunnel.service +``` + +Add this content (replace values): + +```ini +[Unit] +Description=Ory Tunnel for Decor by Hannah's +After=network.target + +[Service] +Type=simple +User=youruser +WorkingDirectory=/home/youruser/decor-by-hannahs +Environment="PATH=/usr/local/bin:/usr/bin:/bin:/home/youruser/.nvm/versions/node/v20.10.0/bin" +ExecStart=/home/youruser/.nvm/versions/node/v20.10.0/bin/npx @ory/cli tunnel --dev --project your-ory-project-slug http://localhost:3000 +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +``` + +#### 2. Create Application Service + +```bash +sudo nano /etc/systemd/system/decor-by-hannahs.service +``` + +Add this content: + +```ini +[Unit] +Description=Decor by Hannah's Application +After=network.target docker.service ory-tunnel.service +Requires=docker.service + +[Service] +Type=simple +User=youruser +WorkingDirectory=/home/youruser/decor-by-hannahs +Environment="PATH=/usr/local/go/bin:/usr/local/bin:/usr/bin:/bin" +EnvironmentFile=/home/youruser/decor-by-hannahs/.env +ExecStart=/home/youruser/decor-by-hannahs/server +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +``` + +#### 3. Enable and Start Services + +```bash +# Reload systemd +sudo systemctl daemon-reload + +# Enable services to start on boot +sudo systemctl enable ory-tunnel +sudo systemctl enable decor-by-hannahs + +# Start services +sudo systemctl start ory-tunnel +sudo systemctl start decor-by-hannahs + +# Check status +sudo systemctl status ory-tunnel +sudo systemctl status decor-by-hannahs + +# View logs +sudo journalctl -u ory-tunnel -f +sudo journalctl -u decor-by-hannahs -f +``` + +## Part 5: Firewall & Networking + +### 1. Configure Firewall + +```bash +# Install ufw if not present +sudo apt install ufw -y + +# Allow SSH (IMPORTANT: do this first!) +sudo ufw allow 22/tcp + +# Allow HTTP and HTTPS +sudo ufw allow 80/tcp +sudo ufw allow 443/tcp + +# Allow application port (if accessing directly) +sudo ufw allow 3000/tcp + +# Enable firewall +sudo ufw enable + +# Check status +sudo ufw status +``` + +### 2. Setup Nginx Reverse Proxy (Optional but Recommended) + +```bash +# Install Nginx +sudo apt install nginx -y + +# Create site configuration +sudo nano /etc/nginx/sites-available/decor-by-hannahs +``` + +Add this configuration: + +```nginx +server { + listen 80; + server_name your-domain.com www.your-domain.com; + + location / { + proxy_pass http://localhost:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + +Enable the site: + +```bash +# Create symbolic link +sudo ln -s /etc/nginx/sites-available/decor-by-hannahs /etc/nginx/sites-enabled/ + +# Test configuration +sudo nginx -t + +# Restart Nginx +sudo systemctl restart nginx +sudo systemctl enable nginx +``` + +### 3. Setup SSL with Let's Encrypt (Optional) + +```bash +# Install Certbot +sudo apt install certbot python3-certbot-nginx -y + +# Obtain certificate +sudo certbot --nginx -d your-domain.com -d www.your-domain.com + +# Certbot will automatically configure Nginx for HTTPS +# Certificates auto-renew via cron +``` + +## Part 6: Post-Deployment + +### 1. Create Admin User + +```bash +# First, register a user through the web interface +# Then grant admin privileges: +docker exec -i $(docker ps -q -f name=db) psql -U party -d partydb -c "UPDATE users SET is_admin = TRUE WHERE email = 'your-email@example.com';" +``` + +### 2. Test the Application + +```bash +# Check if services are running +sudo systemctl status decor-by-hannahs +sudo systemctl status ory-tunnel + +# Test the endpoint +curl http://localhost:3000 + +# Or visit in browser: +# http://your-server-ip:3000 +# or http://your-domain.com (if using Nginx) +``` + +### 3. Monitor Logs + +```bash +# Application logs +sudo journalctl -u decor-by-hannahs -f + +# Ory tunnel logs +sudo journalctl -u ory-tunnel -f + +# Nginx logs (if using) +sudo tail -f /var/log/nginx/access.log +sudo tail -f /var/log/nginx/error.log + +# Database logs +docker logs -f $(docker ps -q -f name=db) +``` + +## Part 7: Maintenance & Updates + +### Deploying Updates + +```bash +# On local machine: sync changes +rclone sync . testserver:/home/youruser/decor-by-hannahs \ + --exclude ".git/**" \ + --exclude ".env" \ + --progress + +# On server: rebuild and restart +cd ~/decor-by-hannahs +go build -o server cmd/server/main.go +sudo systemctl restart decor-by-hannahs +``` + +### Database Backups + +```bash +# Create backup script +cat > ~/backup-db.sh << 'EOF' +#!/bin/bash +BACKUP_DIR=~/backups +mkdir -p $BACKUP_DIR +DATE=$(date +%Y%m%d_%H%M%S) +docker exec $(docker ps -q -f name=db) pg_dump -U party partydb > $BACKUP_DIR/backup_$DATE.sql +# Keep only last 7 days +find $BACKUP_DIR -name "backup_*.sql" -mtime +7 -delete +EOF + +chmod +x ~/backup-db.sh + +# Add to crontab (daily at 2 AM) +(crontab -l 2>/dev/null; echo "0 2 * * * /home/youruser/backup-db.sh") | crontab - +``` + +### Restore from Backup + +```bash +# Restore a backup +docker exec -i $(docker ps -q -f name=db) psql -U party -d partydb < ~/backups/backup_YYYYMMDD_HHMMSS.sql +``` + +## Troubleshooting + +### Application won't start + +```bash +# Check logs +sudo journalctl -u decor-by-hannahs -n 50 + +# Check if port is in use +sudo lsof -i :3000 + +# Check environment variables +sudo systemctl show decor-by-hannahs --property=Environment +``` + +### Database connection issues + +```bash +# Check if database is running +docker ps | grep db + +# Test connection +docker exec -it $(docker ps -q -f name=db) psql -U party -d partydb + +# Check database logs +docker logs $(docker ps -q -f name=db) +``` + +### Ory tunnel issues + +```bash +# Check tunnel status +sudo journalctl -u ory-tunnel -n 50 + +# Test Ory connection +curl http://localhost:4000/.ory/health/ready + +# Restart tunnel +sudo systemctl restart ory-tunnel +``` + +### Permission issues + +```bash +# Fix file ownership +sudo chown -R youruser:youruser ~/decor-by-hannahs + +# Fix binary permissions +chmod +x ~/decor-by-hannahs/server +``` + +## Security Checklist + +- [ ] Change default database password in docker-compose.yml and .env +- [ ] Setup firewall (ufw) +- [ ] Use HTTPS (Let's Encrypt) +- [ ] Keep system updated: `sudo apt update && sudo apt upgrade` +- [ ] Setup automated backups +- [ ] Use strong passwords for admin accounts +- [ ] Restrict SSH access (key-based auth, disable root login) +- [ ] Monitor logs regularly +- [ ] Setup fail2ban for SSH protection + +## Quick Reference Commands + +```bash +# Restart application +sudo systemctl restart decor-by-hannahs + +# View logs +sudo journalctl -u decor-by-hannahs -f + +# Rebuild application +cd ~/decor-by-hannahs && go build -o server cmd/server/main.go + +# Database CLI +docker exec -it $(docker ps -q -f name=db) psql -U party -d partydb + +# Backup database +docker exec $(docker ps -q -f name=db) pg_dump -U party partydb > backup.sql + +# Check service status +sudo systemctl status decor-by-hannahs ory-tunnel nginx +``` diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..2ff7bb1 --- /dev/null +++ b/TODO.md @@ -0,0 +1,106 @@ +# TODO - Decor by Hannah's + +## High Priority + +### Features +- [ ] Email notifications for booking confirmations/updates +- [ ] Calendar integration for event scheduling +- [ ] Photo upload functionality for gallery (currently manual file placement) +- [ ] Service pricing calculator on catalog page +- [ ] Customer testimonials/reviews section + +### Admin Improvements +- [ ] Admin dashboard statistics (total bookings, revenue, upcoming events) +- [ ] Bulk booking status updates +- [ ] Export bookings to CSV/Excel +- [ ] Admin user management (add/remove admin privileges via UI) +- [ ] Booking search and filtering + +### Security & Auth +- [ ] Rate limiting on API endpoints +- [ ] CSRF protection for forms +- [ ] Session timeout configuration +- [ ] Password reset flow (via Ory) +- [ ] Two-factor authentication option + +## Medium Priority + +### UX Improvements +- [ ] Better mobile responsiveness testing +- [ ] Loading states for form submissions +- [ ] Toast notifications instead of alerts +- [ ] Image lazy loading in gallery +- [ ] Booking confirmation page (instead of alert) +- [ ] Service availability calendar on booking page + +### Admin Features +- [ ] Edit service details (name, description, price) +- [ ] Add/remove services via admin UI +- [ ] Upload gallery photos via admin panel +- [ ] Customer contact information in admin view +- [ ] Booking notes/internal comments + +### Code Quality +- [ ] Add unit tests for handlers +- [ ] Add integration tests for booking flow +- [ ] Error logging to file/service (e.g., Sentry) +- [ ] API documentation +- [ ] Code coverage reporting + +## Low Priority + +### Nice to Have +- [ ] Dark mode improvements (better color contrast) +- [ ] Print-friendly booking receipts +- [ ] Social media integration (Instagram feed) +- [ ] Blog/news section +- [ ] FAQ page +- [ ] Contact form +- [ ] Google Maps integration for service area +- [ ] Multi-language support + +### Performance +- [ ] Image optimization/compression +- [ ] CDN for static assets +- [ ] Database query optimization +- [ ] Caching layer (Redis) +- [ ] Minify CSS/JS + +### DevOps +- [ ] CI/CD pipeline setup +- [ ] Automated database backups +- [ ] Staging environment +- [ ] Production deployment guide +- [ ] Monitoring and alerting (uptime, errors) +- [ ] Docker production configuration + +## Technical Debt +- [ ] Consolidate duplicate code in handlers +- [ ] Standardize error responses across API +- [ ] Move magic strings to constants +- [ ] Add database indexes for performance +- [ ] Refactor template data structures (use shared base struct) + +## Documentation +- [ ] API endpoint documentation +- [ ] Database schema documentation +- [ ] Deployment guide +- [ ] Contributing guidelines +- [ ] User manual for admin panel + +## Bugs/Issues +- [ ] None currently known + +## Completed ✓ +- [x] User authentication with Ory +- [x] Booking system with service options +- [x] Australian address validation +- [x] Admin dashboard with booking management +- [x] Admin authorization and security +- [x] Profile page with user bookings +- [x] Service catalog display +- [x] Photo gallery +- [x] Responsive navigation with drawer +- [x] Dark/light theme toggle +- [x] Database migrations system +- [x] Ory redirect pages with toast notifications diff --git a/internal/auth/admin_middleware.go b/internal/auth/admin_middleware.go new file mode 100644 index 0000000..4bf9bdf --- /dev/null +++ b/internal/auth/admin_middleware.go @@ -0,0 +1,48 @@ +package auth + +import ( + "context" + "database/sql" + "log" + "net/http" + + ory "github.com/ory/client-go" + + "decor-by-hannahs/internal/db" +) + +func AdminMiddleware(oryClient *ory.APIClient, queries *db.Queries) func(http.HandlerFunc) http.HandlerFunc { + return func(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cookies := r.Header.Get("Cookie") + session, _, err := oryClient.FrontendAPI.ToSession(r.Context()).Cookie(cookies).Execute() + + if err != nil || session == nil || session.Active == nil || !*session.Active { + http.Error(w, "Unauthorized - Please log in", http.StatusUnauthorized) + return + } + + email := getEmailFromSession(session) + if email == "" { + http.Error(w, "No email in session", http.StatusBadRequest) + return + } + + oryID := sql.NullString{String: session.Identity.Id, Valid: true} + user, err := queries.GetUserByOryID(r.Context(), oryID) + if err != nil { + http.Error(w, "User not found", http.StatusUnauthorized) + return + } + + if !user.IsAdmin.Bool { + log.Printf("Non-admin user %s attempted to access admin area", email) + http.Error(w, "Forbidden - Admin access required", http.StatusForbidden) + return + } + + ctx := context.WithValue(r.Context(), "user", user) + next.ServeHTTP(w, r.WithContext(ctx)) + } + } +} diff --git a/internal/handlers/admin.go b/internal/handlers/admin.go new file mode 100644 index 0000000..375168b --- /dev/null +++ b/internal/handlers/admin.go @@ -0,0 +1,102 @@ +package handlers + +import ( + "database/sql" + "html/template" + "log" + "net/http" + "strconv" + + ory "github.com/ory/client-go" + + "decor-by-hannahs/internal/db" +) + +type AdminBooking struct { + ID int64 + UserEmail string + ServiceName string + ServiceOption string + EventType string + EventDate string + Address string + Notes string + Status string + CreatedAt string +} + +type AdminData struct { + ActivePage string + Authenticated bool + OryLoginURL string + Bookings []AdminBooking +} + +func AdminHandler(q *db.Queries, tmpl *template.Template, oryClient *ory.APIClient) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + data := AdminData{ + ActivePage: "admin", + Authenticated: isAuthenticated(r, oryClient), + OryLoginURL: "/login", + } + + bookings, err := q.ListAllBookingsWithDetails(r.Context()) + if err != nil { + log.Printf("Error fetching bookings: %v", err) + } else { + for _, b := range bookings { + data.Bookings = append(data.Bookings, AdminBooking{ + ID: b.ID, + UserEmail: b.UserEmail, + ServiceName: b.ServiceName, + ServiceOption: nullStringToString(b.ServiceOption), + EventType: nullStringToString(b.EventType), + EventDate: b.EventDate.Format("January 2, 2006"), + Address: nullStringToString(b.Address), + Notes: nullStringToString(b.Notes), + Status: nullStringToString(b.Status), + CreatedAt: b.CreatedAt.Time.Format("Jan 2, 2006 3:04 PM"), + }) + } + } + + if err := tmpl.ExecuteTemplate(w, "admin.tmpl", data); err != nil { + log.Printf("Error rendering admin template: %v", err) + http.Error(w, "Failed to render page", http.StatusInternalServerError) + return + } + } +} + +func AdminUpdateBookingHandler(q *db.Queries, oryClient *ory.APIClient) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + bookingID, err := strconv.ParseInt(r.FormValue("booking_id"), 10, 64) + if err != nil { + http.Error(w, "Invalid booking ID", http.StatusBadRequest) + return + } + + status := r.FormValue("status") + if status == "" { + http.Error(w, "Status is required", http.StatusBadRequest) + return + } + + err = q.UpdateBookingStatus(r.Context(), db.UpdateBookingStatusParams{ + ID: bookingID, + Status: sql.NullString{String: status, Valid: true}, + }) + if err != nil { + log.Printf("Error updating booking: %v", err) + http.Error(w, "Failed to update booking", http.StatusInternalServerError) + return + } + + http.Redirect(w, r, "/admin", http.StatusSeeOther) + } +} diff --git a/internal/tmpl/admin.tmpl b/internal/tmpl/admin.tmpl new file mode 100644 index 0000000..eace5fd --- /dev/null +++ b/internal/tmpl/admin.tmpl @@ -0,0 +1,139 @@ +{{define "admin.tmpl"}} + + + + + +Admin - Decor By Hannahs + + + + + + + + + +{{template "header" .}} + +
+
+
+

Admin Dashboard

+

Manage bookings and orders

+
+ +
+
+

All Bookings

+

View and update booking statuses

+
+
+{{if .Bookings}} +
+ + + + + + + + + + + + + + + +{{range .Bookings}} + + + + + + + + + + + +{{if .Notes}} + + + +{{end}} +{{end}} + +
IDCustomerServiceEvent TypeEvent DateAddressStatusCreatedAction
{{.ID}}{{.UserEmail}}{{.ServiceOption}}{{.EventType}}{{.EventDate}}{{.Address}} +{{.Status}} +{{.CreatedAt}} +
+ + + +
+
+Notes: {{.Notes}} +
+
+{{else}} +

No bookings yet.

+{{end}} +
+
+
+
+ +{{template "footer"}} +{{template "theme-script"}} + + +{{end}} diff --git a/migrations/011_add_service_option_event_type.sql b/migrations/011_add_service_option_event_type.sql new file mode 100644 index 0000000..0400e05 --- /dev/null +++ b/migrations/011_add_service_option_event_type.sql @@ -0,0 +1,3 @@ +ALTER TABLE bookings +ADD COLUMN service_option TEXT, +ADD COLUMN event_type TEXT; diff --git a/migrations/012_add_is_admin.sql b/migrations/012_add_is_admin.sql new file mode 100644 index 0000000..65cec32 --- /dev/null +++ b/migrations/012_add_is_admin.sql @@ -0,0 +1,2 @@ +ALTER TABLE users +ADD COLUMN is_admin BOOLEAN DEFAULT FALSE; diff --git a/start-tunnel.sh b/start-tunnel.sh new file mode 100755 index 0000000..b5c4637 --- /dev/null +++ b/start-tunnel.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Load environment variables +if [ -f .env ]; then + export $(cat .env | grep -v '^#' | xargs) +fi + +# Check if ORY_PROJECT_SLUG is set +if [ -z "$ORY_PROJECT_SLUG" ]; then + echo "Error: ORY_PROJECT_SLUG not found in .env file" + exit 1 +fi + +echo "Starting Ory tunnel for project: $ORY_PROJECT_SLUG" +echo "Tunnel will be available at: http://localhost:${TUNNEL_PORT:-4000}" +echo "" + +npx @ory/cli tunnel --dev --project "$ORY_PROJECT_SLUG" http://localhost:${PORT:-3000}