Problem Statement
REST API exists but uses cookie-based auth only. No API key system for external developers to integrate programmatically. Developers cannot build applications on top of BoloDB without browser-based authentication.
Proposed Solution
Implement a BoloDB API key system with key generation, scoping, rate limiting, and usage tracking.
Acceptance Criteria
Technical Approach
Backend Changes
1. API key model (backend/app/pgdatabase/models.py):
class ApiKey(Base):
__tablename__ = "api_keys"
id = Column(UUID, primary_key=True)
user_id = Column(UUID, ForeignKey("users.id"))
name = Column(String, nullable=False)
key_hash = Column(String, nullable=False, unique=True)
key_prefix = Column(String, nullable=False) # First 8 chars for identification
scope = Column(String, default="read") # read, write, admin
is_active = Column(Boolean, default=True)
last_used = Column(DateTime)
usage_count = Column(Integer, default=0)
rate_limit = Column(Integer, default=1000) # requests per day
created_at = Column(DateTime, default=func.now())
expires_at = Column(DateTime)
2. Key generation service (backend/app/services/api_keys.py):
import secrets
import hashlib
class ApiKeyService:
def __init__(self, db):
self.db = db
async def generate_key(self, user_id: str, name: str, scope: str = "read") -> dict:
"""Generate a new API key."""
# Generate secure random key
raw_key = secrets.token_urlsafe(32)
key_hash = hashlib.sha256(raw_key.encode()).hexdigest()
key_prefix = raw_key[:8]
api_key = ApiKey(
user_id=user_id,
name=name,
key_hash=key_hash,
key_prefix=key_prefix,
scope=scope
)
self.db.add(api_key)
await self.db.commit()
# Return raw key only once
return {
"key": raw_key,
"id": api_key.id,
"name": name,
"scope": scope,
"prefix": key_prefix
}
async def validate_key(self, raw_key: str) -> dict:
"""Validate an API key and return user info."""
key_hash = hashlib.sha256(raw_key.encode()).hexdigest()
api_key = self.db.query(ApiKey).filter(
ApiKey.key_hash == key_hash,
ApiKey.is_active == True
).first()
if not api_key:
return None
# Check expiration
if api_key.expires_at and api_key.expires_at < datetime.utcnow():
return None
# Update usage
api_key.last_used = datetime.utcnow()
api_key.usage_count += 1
await self.db.commit()
return {
"user_id": api_key.user_id,
"scope": api_key.scope,
"key_id": api_key.id
}
async def revoke_key(self, key_id: str):
"""Revoke an API key."""
api_key = self.db.query(ApiKey).get(key_id)
if api_key:
api_key.is_active = False
await self.db.commit()
3. API key authentication dependency (backend/app/dependencies.py):
async def get_api_key_user(request: Request, db = Depends(get_db)):
"""Authenticate via API key (Bearer token or X-API-Key header)."""
auth_header = request.headers.get("Authorization", "")
api_key_header = request.headers.get("X-API-Key", "")
raw_key = None
if auth_header.startswith("Bearer "):
raw_key = auth_header[7:]
elif api_key_header:
raw_key = api_key_header
if not raw_key:
return None # Fall back to cookie auth
service = ApiKeyService(db)
return await service.validate_key(raw_key)
4. API routes (backend/app/routes/api_keys.py):
GET /api/keys - List user's API keys
POST /api/keys - Generate new key
DELETE /api/keys/{id} - Revoke key
GET /api/keys/{id}/usage - Get usage stats
5. Rate limiting - Implement per-key rate limiting
Frontend Changes
1. API key manager (frontend/src/routes/settings/api-keys/+page.svelte):
<script>
let keys = [];
let newKeyName = '';
let newKeyScope = 'read';
let generatedKey = null;
async function generateKey() {
const response = await apiCall('/api/keys', {
method: 'POST',
body: JSON.stringify({ name: newKeyName, scope: newKeyScope })
});
generatedKey = response.key;
keys = [...keys, response];
}
async function revokeKey(id) {
await apiCall(`/api/keys/${id}`, { method: 'DELETE' });
keys = keys.filter(k => k.id !== id);
}
</script>
<div class="api-keys">
<h1>API Keys</h1>
{#if generatedKey}
<div class="alert">
<strong>Your API Key:</strong>
<code>{generatedKey}</code>
<p>Copy this key now. It won't be shown again.</p>
<button on:click={() => navigator.clipboard.writeText(generatedKey)}>Copy</button>
</div>
{/if}
<div class="generate-form">
<input bind:value={newKeyName} placeholder="Key name (e.g., 'dev', 'staging')" />
<select bind:value={newKeyScope}>
<option value="read">Read Only</option>
<option value="read">Read/Write</option>
<option value="admin">Admin</option>
</select>
<button on:click={generateKey}>Generate Key</button>
</div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Prefix</th>
<th>Scope</th>
<th>Last Used</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{#each keys as key}
<tr>
<td>{key.name}</td>
<td><code>{key.prefix}...</code></td>
<td>{key.scope}</td>
<td>{key.last_used || 'Never'}</td>
<td>
<button on:click={() => revokeKey(key.id)}>Revoke</button>
</td>
</tr>
{/each}
</tbody>
</table>
</div>
2. Usage dashboard - Charts showing API usage over time
3. Quick start guide - Code examples for Python/JavaScript
Key Files
backend/app/pgdatabase/models.py - ApiKey model
backend/app/services/api_keys.py - Key service (new)
backend/app/dependencies.py - Auth dependency
backend/app/routes/api_keys.py - API routes (new)
frontend/src/routes/settings/api-keys/+page.svelte - Key manager
Related Issues
Problem Statement
REST API exists but uses cookie-based auth only. No API key system for external developers to integrate programmatically. Developers cannot build applications on top of BoloDB without browser-based authentication.
Proposed Solution
Implement a BoloDB API key system with key generation, scoping, rate limiting, and usage tracking.
Acceptance Criteria
Technical Approach
Backend Changes
1. API key model (
backend/app/pgdatabase/models.py):2. Key generation service (
backend/app/services/api_keys.py):3. API key authentication dependency (
backend/app/dependencies.py):4. API routes (
backend/app/routes/api_keys.py):GET /api/keys- List user's API keysPOST /api/keys- Generate new keyDELETE /api/keys/{id}- Revoke keyGET /api/keys/{id}/usage- Get usage stats5. Rate limiting - Implement per-key rate limiting
Frontend Changes
1. API key manager (
frontend/src/routes/settings/api-keys/+page.svelte):2. Usage dashboard - Charts showing API usage over time
3. Quick start guide - Code examples for Python/JavaScript
Key Files
backend/app/pgdatabase/models.py- ApiKey modelbackend/app/services/api_keys.py- Key service (new)backend/app/dependencies.py- Auth dependencybackend/app/routes/api_keys.py- API routes (new)frontend/src/routes/settings/api-keys/+page.svelte- Key managerRelated Issues