352 lines
8.9 KiB
Markdown
352 lines
8.9 KiB
Markdown
# Appwrite Setup Guide
|
|
|
|
This guide walks you through setting up Appwrite for Code of Conquest.
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
- Appwrite Cloud account (https://cloud.appwrite.io) OR self-hosted Appwrite instance
|
|
- Admin access to create projects and collections
|
|
|
|
---
|
|
|
|
## Step 1: Create Project
|
|
|
|
1. Log in to Appwrite Console
|
|
2. Click **"Create Project"**
|
|
3. Project Name: `Code of Conquest`
|
|
4. Project ID: (auto-generated, save this for `.env`)
|
|
5. Click **"Create"**
|
|
|
|
---
|
|
|
|
## Step 2: Get API Credentials
|
|
|
|
1. In your project, go to **Settings**
|
|
2. Copy the following values:
|
|
- **Project ID** → `.env` as `APPWRITE_PROJECT_ID`
|
|
- **API Endpoint** → `.env` as `APPWRITE_ENDPOINT` (usually `https://cloud.appwrite.io/v1`)
|
|
3. Go to **Settings** → **API Keys**
|
|
4. Click **"Create API Key"**
|
|
- Name: `Backend Server`
|
|
- Expiration: Never (or long-term)
|
|
- Scopes: Select ALL scopes (for development)
|
|
5. Copy the generated API key → `.env` as `APPWRITE_API_KEY`
|
|
|
|
---
|
|
|
|
## Step 3: Create Database
|
|
|
|
1. Go to **Databases** in the left sidebar
|
|
2. Click **"Create Database"**
|
|
3. Database ID: `main`
|
|
4. Name: `Main Database`
|
|
5. Click **"Create"**
|
|
|
|
---
|
|
|
|
## Step 4: Create Collections
|
|
|
|
Create the following collections in the `main` database.
|
|
|
|
### Collection 1: characters
|
|
|
|
| Setting | Value |
|
|
|---------|-------|
|
|
| Collection ID | `characters` |
|
|
| Collection Name | `Characters` |
|
|
|
|
**Attributes:**
|
|
|
|
| Key | Type | Size | Required | Default | Array |
|
|
|-----|------|------|----------|---------|-------|
|
|
| `userId` | String | 255 | Yes | - | No |
|
|
| `characterData` | String | 100000 | Yes | - | No |
|
|
| `created_at` | DateTime | - | Yes | - | No |
|
|
| `updated_at` | DateTime | - | Yes | - | No |
|
|
| `is_active` | Boolean | - | Yes | true | No |
|
|
|
|
**Indexes:**
|
|
|
|
| Key | Type | Attributes |
|
|
|-----|------|------------|
|
|
| `userId_index` | Key | `userId` (ASC) |
|
|
| `active_index` | Key | `is_active` (ASC) |
|
|
|
|
**Permissions:**
|
|
- Create: `users`
|
|
- Read: `users`
|
|
- Update: `users`
|
|
- Delete: `users`
|
|
|
|
### Collection 2: game_sessions
|
|
|
|
| Setting | Value |
|
|
|---------|-------|
|
|
| Collection ID | `game_sessions` |
|
|
| Collection Name | `Game Sessions` |
|
|
|
|
**Attributes:**
|
|
|
|
| Key | Type | Size | Required | Default | Array |
|
|
|-----|------|------|----------|---------|-------|
|
|
| `party_member_ids` | String | 255 | Yes | - | Yes |
|
|
| `config` | String | 5000 | Yes | - | No |
|
|
| `combat_encounter` | String | 50000 | No | - | No |
|
|
| `conversation_history` | String | 500000 | Yes | - | No |
|
|
| `game_state` | String | 50000 | Yes | - | No |
|
|
| `turn_order` | String | 255 | Yes | - | Yes |
|
|
| `current_turn` | Integer | - | Yes | 0 | No |
|
|
| `turn_number` | Integer | - | Yes | 1 | No |
|
|
| `created_at` | DateTime | - | Yes | - | No |
|
|
| `last_activity` | DateTime | - | Yes | - | No |
|
|
| `status` | String | 50 | Yes | active | No |
|
|
|
|
**Indexes:**
|
|
|
|
| Key | Type | Attributes |
|
|
|-----|------|------------|
|
|
| `status_index` | Key | `status` (ASC) |
|
|
| `last_activity_index` | Key | `last_activity` (DESC) |
|
|
|
|
**Permissions:**
|
|
- Create: `users`
|
|
- Read: `users`
|
|
- Update: `users`
|
|
- Delete: `users`
|
|
|
|
### Collection 3: marketplace_listings
|
|
|
|
| Setting | Value |
|
|
|---------|-------|
|
|
| Collection ID | `marketplace_listings` |
|
|
| Collection Name | `Marketplace Listings` |
|
|
|
|
**Attributes:**
|
|
|
|
| Key | Type | Size | Required | Default | Array |
|
|
|-----|------|------|----------|---------|-------|
|
|
| `seller_id` | String | 255 | Yes | - | No |
|
|
| `character_id` | String | 255 | Yes | - | No |
|
|
| `item_data` | String | 10000 | Yes | - | No |
|
|
| `listing_type` | String | 50 | Yes | - | No |
|
|
| `price` | Integer | - | No | - | No |
|
|
| `starting_bid` | Integer | - | No | - | No |
|
|
| `current_bid` | Integer | - | No | - | No |
|
|
| `buyout_price` | Integer | - | No | - | No |
|
|
| `bids` | String | 50000 | No | - | No |
|
|
| `auction_end` | DateTime | - | No | - | No |
|
|
| `status` | String | 50 | Yes | active | No |
|
|
| `created_at` | DateTime | - | Yes | - | No |
|
|
|
|
**Indexes:**
|
|
|
|
| Key | Type | Attributes |
|
|
|-----|------|------------|
|
|
| `listing_type_index` | Key | `listing_type` (ASC) |
|
|
| `status_index` | Key | `status` (ASC) |
|
|
| `seller_index` | Key | `seller_id` (ASC) |
|
|
| `auction_end_index` | Key | `auction_end` (ASC) |
|
|
|
|
**Permissions:**
|
|
- Create: `users`
|
|
- Read: `any` (public can browse)
|
|
- Update: `users` (owner only, enforced in code)
|
|
- Delete: `users` (owner only, enforced in code)
|
|
|
|
### Collection 4: transactions
|
|
|
|
| Setting | Value |
|
|
|---------|-------|
|
|
| Collection ID | `transactions` |
|
|
| Collection Name | `Transactions` |
|
|
|
|
**Attributes:**
|
|
|
|
| Key | Type | Size | Required | Default | Array |
|
|
|-----|------|------|----------|---------|-------|
|
|
| `buyer_id` | String | 255 | Yes | - | No |
|
|
| `seller_id` | String | 255 | Yes | - | No |
|
|
| `listing_id` | String | 255 | No | - | No |
|
|
| `item_data` | String | 10000 | Yes | - | No |
|
|
| `price` | Integer | - | Yes | - | No |
|
|
| `timestamp` | DateTime | - | Yes | - | No |
|
|
| `transaction_type` | String | 50 | Yes | - | No |
|
|
|
|
**Indexes:**
|
|
|
|
| Key | Type | Attributes |
|
|
|-----|------|------------|
|
|
| `buyer_index` | Key | `buyer_id` (ASC) |
|
|
| `seller_index` | Key | `seller_id` (ASC) |
|
|
| `timestamp_index` | Key | `timestamp` (DESC) |
|
|
|
|
**Permissions:**
|
|
- Create: System only (API key)
|
|
- Read: `users` (buyer/seller only, enforced in code)
|
|
- Update: None
|
|
- Delete: None
|
|
|
|
---
|
|
|
|
## Step 5: Enable Realtime
|
|
|
|
1. Go to **Settings** → **Realtime**
|
|
2. Enable **Realtime API**
|
|
3. Add allowed origins:
|
|
- `http://localhost:5000` (development)
|
|
- Your production domain (when ready)
|
|
|
|
---
|
|
|
|
## Step 6: Configure Authentication
|
|
|
|
1. Go to **Auth** in the left sidebar
|
|
2. Enable **Email/Password** authentication
|
|
3. Configure password requirements:
|
|
- Minimum length: 8
|
|
- Require lowercase: Yes
|
|
- Require uppercase: Yes
|
|
- Require numbers: Yes
|
|
- Require special characters: Optional
|
|
|
|
**Optional:** Enable OAuth providers if desired (Google, GitHub, etc.)
|
|
|
|
---
|
|
|
|
## Step 7: Update .env File
|
|
|
|
Copy `.env.example` to `.env` and fill in the values:
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
Update the following in `.env`:
|
|
|
|
```bash
|
|
APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
|
|
APPWRITE_PROJECT_ID=your-project-id-here
|
|
APPWRITE_API_KEY=your-api-key-here
|
|
APPWRITE_DATABASE_ID=main
|
|
```
|
|
|
|
---
|
|
|
|
## Step 8: Test Connection
|
|
|
|
Create a test script to verify Appwrite connection:
|
|
|
|
**test_appwrite.py:**
|
|
|
|
```python
|
|
from appwrite.client import Client
|
|
from appwrite.services.databases import Databases
|
|
from dotenv import load_dotenv
|
|
import os
|
|
|
|
load_dotenv()
|
|
|
|
# Initialize Appwrite client
|
|
client = Client()
|
|
client.set_endpoint(os.getenv('APPWRITE_ENDPOINT'))
|
|
client.set_project(os.getenv('APPWRITE_PROJECT_ID'))
|
|
client.set_key(os.getenv('APPWRITE_API_KEY'))
|
|
|
|
# Test database connection
|
|
databases = Databases(client)
|
|
|
|
try:
|
|
# List collections
|
|
result = databases.list_collections(
|
|
database_id=os.getenv('APPWRITE_DATABASE_ID')
|
|
)
|
|
print(f"✓ Connected to Appwrite successfully!")
|
|
print(f"✓ Found {result['total']} collections:")
|
|
for collection in result['collections']:
|
|
print(f" - {collection['name']} (ID: {collection['$id']})")
|
|
except Exception as e:
|
|
print(f"✗ Failed to connect to Appwrite:")
|
|
print(f" Error: {str(e)}")
|
|
```
|
|
|
|
Run:
|
|
```bash
|
|
source venv/bin/activate
|
|
pip install appwrite python-dotenv
|
|
python test_appwrite.py
|
|
```
|
|
|
|
---
|
|
|
|
## Security Best Practices
|
|
|
|
### Production Permissions
|
|
|
|
**For production, tighten permissions:**
|
|
|
|
1. **characters collection:**
|
|
- Users can only access their own characters (enforce in code)
|
|
- Add server-side checks for `userId` match
|
|
|
|
2. **game_sessions collection:**
|
|
- Party members can read (enforce in code)
|
|
- Active player can write (enforce in code)
|
|
|
|
3. **marketplace_listings collection:**
|
|
- Anyone can read (browsing)
|
|
- Only owner can update/delete (enforce in code)
|
|
|
|
4. **transactions collection:**
|
|
- Create via API key only
|
|
- Users can read only their own transactions (enforce in code)
|
|
|
|
### API Key Security
|
|
|
|
- **Never commit** `.env` file to git
|
|
- Use different API keys for dev/staging/production
|
|
- Rotate API keys periodically
|
|
- Use minimal scopes in production (not "all")
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
**Issue:** "Project not found"
|
|
- Solution: Verify `APPWRITE_PROJECT_ID` matches the project ID in Appwrite Console
|
|
|
|
**Issue:** "Invalid API key"
|
|
- Solution: Regenerate API key and update `.env`
|
|
|
|
**Issue:** "Collection not found"
|
|
- Solution: Verify collection IDs match exactly (case-sensitive)
|
|
|
|
**Issue:** "Permission denied"
|
|
- Solution: Check collection permissions in Appwrite Console
|
|
|
|
**Issue:** "Realtime not working"
|
|
- Solution: Verify Realtime is enabled and origins are configured
|
|
|
|
---
|
|
|
|
## Next Steps
|
|
|
|
After completing Appwrite setup:
|
|
|
|
1. ✅ Install dependencies: `pip install -r requirements.txt`
|
|
2. ✅ Test connection with `test_appwrite.py`
|
|
3. ✅ Create Appwrite service wrapper (`app/services/appwrite_service.py`)
|
|
4. Start building API endpoints (Phase 2)
|
|
|
|
---
|
|
|
|
## Resources
|
|
|
|
- **Appwrite Documentation:** https://appwrite.io/docs
|
|
- **Appwrite Python SDK:** https://github.com/appwrite/sdk-for-python
|
|
- **Appwrite Console:** https://cloud.appwrite.io
|
|
- **Appwrite Discord:** https://appwrite.io/discord
|