Initial commit: Open sourcing all of the Maple Open Technologies code.
This commit is contained in:
commit
755d54a99d
2010 changed files with 448675 additions and 0 deletions
387
cloud/maplepress-backend/README.md
Normal file
387
cloud/maplepress-backend/README.md
Normal file
|
|
@ -0,0 +1,387 @@
|
|||
# 🚀 MaplePress Backend
|
||||
|
||||
> Cloud-powered services platform for WordPress sites - Multi-tenant SaaS backend built with Go.
|
||||
|
||||
MaplePress offloads computationally intensive tasks from WordPress to improve site performance. Features include cloud-powered search (Meilisearch), JWT authentication for users, API key authentication for WordPress plugins, and multi-tenant architecture.
|
||||
|
||||
## 📋 Prerequisites
|
||||
|
||||
**⚠️ Required:** You must have the infrastructure running first.
|
||||
|
||||
If you haven't set up the infrastructure yet:
|
||||
1. Go to [`../infrastructure/README.md`](../infrastructure/README.md)
|
||||
2. Follow the setup instructions
|
||||
3. Come back here once infrastructure is running
|
||||
|
||||
**Verify infrastructure is healthy:**
|
||||
```bash
|
||||
cd cloud/infrastructure/development
|
||||
task dev:status
|
||||
# All services should show (healthy)
|
||||
```
|
||||
|
||||
## 🏁 Getting Started
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
# From the monorepo root:
|
||||
cd cloud/maplepress-backend
|
||||
|
||||
# Create environment file:
|
||||
cp .env.sample .env
|
||||
|
||||
# Start the backend:
|
||||
task dev
|
||||
```
|
||||
|
||||
The backend runs at **http://localhost:8000**
|
||||
|
||||
### Verify Installation
|
||||
|
||||
Open a **new terminal** (leave `task dev` running):
|
||||
|
||||
```bash
|
||||
curl http://localhost:8000/health
|
||||
# Should return: {"status":"healthy"}
|
||||
```
|
||||
|
||||
> **Note:** Your first terminal shows backend logs. Keep it running and use a second terminal for testing.
|
||||
|
||||
## 💻 Developing
|
||||
|
||||
### Initial Configuration
|
||||
|
||||
**Environment Files:**
|
||||
- **`.env.sample`** - Template with defaults (committed to git)
|
||||
- **`.env`** - Your local configuration (git-ignored, created from `.env.sample`)
|
||||
- Use **only `.env`** for configuration (docker-compose loads this file)
|
||||
|
||||
The `.env` file defaults work for Docker development. **Optional:** Change `APP_JWT_SECRET` to a random string (use a password generator).
|
||||
|
||||
### Running in Development Mode
|
||||
|
||||
```bash
|
||||
# Start backend with hot-reload
|
||||
task dev
|
||||
|
||||
# View logs (in another terminal)
|
||||
docker logs -f maplepress-backend-dev
|
||||
|
||||
# Stop backend
|
||||
task dev:down
|
||||
# Or press Ctrl+C in the task dev terminal
|
||||
```
|
||||
|
||||
**What happens when you run `task dev`:**
|
||||
- Docker starts the backend container
|
||||
- Auto-migrates database tables
|
||||
- Starts HTTP server on port 8000
|
||||
- Enables hot-reload (auto-restarts on code changes)
|
||||
|
||||
Wait for: `Server started on :8000` in the logs
|
||||
|
||||
### Daily Workflow
|
||||
|
||||
```bash
|
||||
# Morning - check infrastructure (from monorepo root)
|
||||
cd cloud/infrastructure/development && task dev:status
|
||||
|
||||
# Start backend (from monorepo root)
|
||||
cd cloud/maplepress-backend && task dev
|
||||
|
||||
# Make code changes - backend auto-restarts
|
||||
|
||||
# Stop backend when done
|
||||
# Press Ctrl+C
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
task test
|
||||
|
||||
# Code quality checks
|
||||
task format # Format code
|
||||
task lint # Run linters
|
||||
```
|
||||
|
||||
### Database Operations
|
||||
|
||||
**View database:**
|
||||
```bash
|
||||
# From monorepo root
|
||||
cd cloud/infrastructure/development
|
||||
task cql
|
||||
|
||||
# Inside cqlsh:
|
||||
USE maplepress;
|
||||
DESCRIBE TABLES;
|
||||
SELECT * FROM sites_by_id;
|
||||
```
|
||||
|
||||
**Reset database (⚠️ deletes all data):**
|
||||
```bash
|
||||
task db:clear
|
||||
```
|
||||
|
||||
## 🔧 Usage
|
||||
|
||||
### Testing the API
|
||||
|
||||
Create a test user and site to verify the backend works:
|
||||
|
||||
**1. Register a user:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/register \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"email": "test@example.com",
|
||||
"password": "MySecureP@ssw0rd2024!XyZ",
|
||||
"name": "Test User",
|
||||
"tenant_name": "Test Organization",
|
||||
"tenant_slug": "test-org",
|
||||
"agree_terms_of_service": true
|
||||
}'
|
||||
```
|
||||
|
||||
> **Note:** MaplePress checks passwords against the [Have I Been Pwned](https://haveibeenpwned.com/) database. If your password has been found in data breaches, registration will fail. Use a strong, unique password that hasn't been compromised.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"user_id": "uuid-here",
|
||||
"user_email": "test@example.com",
|
||||
"user_name": "Test User",
|
||||
"tenant_id": "uuid-here",
|
||||
"tenant_name": "Test Organization",
|
||||
"access_token": "eyJhbGci...",
|
||||
"refresh_token": "eyJhbGci...",
|
||||
"access_expiry": "2025-10-29T12:00:00Z",
|
||||
"refresh_expiry": "2025-11-05T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
Save the `access_token` from the response:
|
||||
```bash
|
||||
export TOKEN="eyJhbGci...your-access-token-here"
|
||||
```
|
||||
|
||||
**2. Get your profile:**
|
||||
```bash
|
||||
curl http://localhost:8000/api/v1/me \
|
||||
-H "Authorization: JWT $TOKEN"
|
||||
```
|
||||
|
||||
**3. Create a WordPress site:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/sites \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: JWT $TOKEN" \
|
||||
-d '{
|
||||
"domain": "localhost:8081",
|
||||
"site_url": "http://localhost:8081"
|
||||
}'
|
||||
```
|
||||
|
||||
Save the `api_key` from the response (shown only once):
|
||||
```bash
|
||||
export API_KEY="your-api-key-here"
|
||||
```
|
||||
|
||||
**4. Test plugin authentication:**
|
||||
```bash
|
||||
curl http://localhost:8000/api/v1/plugin/status \
|
||||
-H "Authorization: Bearer $API_KEY"
|
||||
```
|
||||
|
||||
### WordPress Plugin Integration
|
||||
|
||||
**Access WordPress:**
|
||||
- URL: http://localhost:8081/wp-admin
|
||||
- Credentials: admin / admin
|
||||
|
||||
**Configure the plugin:**
|
||||
1. Go to **Settings → MaplePress**
|
||||
2. Enter:
|
||||
- **API URL:** `http://maplepress-backend-dev:8000`
|
||||
- **API Key:** Your API key from step 3 above
|
||||
3. Click **Save Settings & Verify Connection**
|
||||
|
||||
⚠️ **Important:** Use the container name (`maplepress-backend-dev`), not `localhost`, because WordPress runs in Docker.
|
||||
|
||||
**Next steps:**
|
||||
- WordPress plugin setup: [`../../native/wordpress/README.md`](../../native/wordpress/README.md)
|
||||
- Complete API documentation: [`docs/API/README.md`](docs/API/README.md)
|
||||
|
||||
### Error Handling
|
||||
|
||||
MaplePress uses **RFC 9457 (Problem Details for HTTP APIs)** for standardized error responses. All errors return a consistent, machine-readable format:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Validation Error",
|
||||
"status": 400,
|
||||
"detail": "One or more validation errors occurred",
|
||||
"errors": {
|
||||
"email": ["Invalid email format"],
|
||||
"password": ["Password must be at least 8 characters"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- 📋 Structured, predictable error format
|
||||
- 🤖 Machine-readable for frontend parsing
|
||||
- 🌍 Industry standard ([RFC 9457](https://datatracker.ietf.org/doc/html/rfc9457))
|
||||
- 🔍 Field-level validation errors
|
||||
|
||||
See [`docs/API/README.md#error-handling`](docs/API/README.md#error-handling) for complete error documentation.
|
||||
|
||||
## ⚙️ Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Key variables in `.env`:
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `APP_JWT_SECRET` | `change-me-in-production-use-a-long-random-string` | Secret for JWT token signing |
|
||||
| `SERVER_PORT` | `8000` | HTTP server port |
|
||||
| `DATABASE_HOSTS` | `cassandra-1,cassandra-2,cassandra-3` | Cassandra cluster nodes |
|
||||
| `CACHE_HOST` | `redis` | Redis cache host |
|
||||
| `MEILISEARCH_HOST` | `http://meilisearch:7700` | Search engine URL |
|
||||
|
||||
**Docker vs Local:**
|
||||
- Docker: Uses container names (`cassandra-1`, `redis`)
|
||||
- Local: Change to `localhost`
|
||||
|
||||
See `.env.sample` for complete documentation.
|
||||
|
||||
### Task Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `task dev` | Start backend (auto-migrate + hot-reload) |
|
||||
| `task dev:down` | Stop backend |
|
||||
| `task test` | Run tests |
|
||||
| `task format` | Format code |
|
||||
| `task lint` | Run linters |
|
||||
| `task db:clear` | Reset database (⚠️ deletes data) |
|
||||
| `task migrate:up` | Manual migration |
|
||||
|
||||
## 🔍 Troubleshooting
|
||||
|
||||
### Backend won't start - "connection refused"
|
||||
|
||||
**Error:** `dial tcp 127.0.0.1:9042: connect: connection refused`
|
||||
|
||||
**Cause:** `.env` file has `localhost` instead of container names.
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
cd cloud/maplepress-backend
|
||||
rm .env
|
||||
cp .env.sample .env
|
||||
task dev
|
||||
```
|
||||
|
||||
### Infrastructure not running
|
||||
|
||||
**Error:** Cassandra or Redis not available
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
cd cloud/infrastructure/development
|
||||
task dev:start
|
||||
task dev:status # Wait until all show (healthy)
|
||||
```
|
||||
|
||||
### Port 8000 already in use
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
lsof -i :8000 # Find what's using the port
|
||||
# Stop the other service, or change SERVER_PORT in .env
|
||||
```
|
||||
|
||||
### Token expired (401 errors)
|
||||
|
||||
JWT tokens expire after 60 minutes. Re-run the [registration step](#testing-the-api) to get a new token.
|
||||
|
||||
### WordPress can't connect
|
||||
|
||||
**Problem:** WordPress using `localhost:8000` instead of container name
|
||||
|
||||
**Fix:** In WordPress settings, use `http://maplepress-backend-dev:8000`
|
||||
|
||||
**Verify:**
|
||||
```bash
|
||||
docker exec maple-wordpress-dev curl http://maplepress-backend-dev:8000/health
|
||||
```
|
||||
|
||||
## 🛠️ Technology Stack
|
||||
|
||||
- **Go 1.23+** - Programming language
|
||||
- **Clean Architecture** - Code organization
|
||||
- **Wire** - Dependency injection
|
||||
- **Cassandra** - Multi-tenant database (3-node cluster)
|
||||
- **Redis** - Caching layer
|
||||
- **Meilisearch** - Full-text search
|
||||
- **JWT** - User authentication
|
||||
- **API Keys** - Plugin authentication
|
||||
|
||||
## 🌐 Services
|
||||
|
||||
When you run MaplePress, these services are available:
|
||||
|
||||
| Service | Port | Purpose | Access |
|
||||
|---------|------|---------|--------|
|
||||
| MaplePress Backend | 8000 | HTTP API | http://localhost:8000 |
|
||||
| Cassandra | 9042 | Database | `task cql` (from infrastructure dir) |
|
||||
| Redis | 6379 | Cache | `task redis` (from infrastructure dir) |
|
||||
| Meilisearch | 7700 | Search | http://localhost:7700 |
|
||||
| WordPress | 8081 | Plugin testing | http://localhost:8081 |
|
||||
|
||||
## 🧪 Test Mode vs Live Mode
|
||||
|
||||
MaplePress **automatically** generates the correct API key type based on your environment:
|
||||
|
||||
### Automatic Behavior
|
||||
|
||||
| Environment | API Key Type | When to Use |
|
||||
|-------------|-------------|-------------|
|
||||
| `development` | `test_sk_*` | Local development, testing |
|
||||
| `production` | `live_sk_*` | Production sites |
|
||||
|
||||
**Configuration (`.env`):**
|
||||
```bash
|
||||
# Development - automatically generates test_sk_ keys
|
||||
APP_ENVIRONMENT=development
|
||||
|
||||
# Production - automatically generates live_sk_ keys
|
||||
APP_ENVIRONMENT=production
|
||||
```
|
||||
|
||||
**No manual parameter needed!** The backend determines the key type from `APP_ENVIRONMENT`.
|
||||
|
||||
See [`docs/API.md#test-mode-vs-live-mode`](docs/API.md#test-mode-vs-live-mode) for details.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
- **API Documentation:** [`docs/API.md`](docs/API.md)
|
||||
- **Developer Guide:** [`docs/DEVELOPER_GUIDE.md`](docs/DEVELOPER_GUIDE.md)
|
||||
- **Getting Started Guide:** [`docs/GETTING-STARTED.md`](docs/GETTING-STARTED.md)
|
||||
- **WordPress Plugin:** [`../../native/wordpress/README.md`](../../native/wordpress/README.md)
|
||||
- **Architecture Details:** [`../../CLAUDE.md`](../../CLAUDE.md)
|
||||
- **Repository:** [Codeberg - mapleopentech/monorepo](https://codeberg.org/mapleopentech/monorepo)
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
Found a bug? Want a feature to improve MaplePress? Please create an [issue](https://codeberg.org/mapleopentech/monorepo/issues/new).
|
||||
|
||||
## 📝 License
|
||||
|
||||
This application is licensed under the [**GNU Affero General Public License v3.0**](https://opensource.org/license/agpl-v3). See [LICENSE](../../LICENSE) for more information.
|
||||
Loading…
Add table
Add a link
Reference in a new issue