Files
notely/README.md
domrichardson df40cc57e1 first commit
2026-03-24 16:03:04 +00:00

427 lines
9.3 KiB
Markdown

# Notely - Secure Multi-Space Note-Taking Application
A production-ready, secure multi-tenant note-taking platform built with Go, Vue 3, and MongoDB.
## 🚀 Quick Start
### Prerequisites
- Docker & Docker Compose
- Go 1.21+ (for local development)
- Node.js 18+ (for frontend development)
- MongoDB 7.0+ (for local development)
### Development with Docker Compose
```bash
# Start all services
docker-compose up
# Backend: http://localhost:8080
# Frontend: http://localhost:5173
# MongoDB: localhost:27017
# Nginx: http://localhost:80
```
### Local Development Setup
#### Backend
```bash
cd backend
# Install dependencies
go mod download
# Set environment variables
export MONGODB_URI=mongodb://admin:password@localhost:27017/noteapp?authSource=admin
export JWT_SECRET=your-secret-key
export ENCRYPTION_KEY=00000000000000000000000000000000
# Run migrations and server
go run ./cmd/server/main.go
```
#### Frontend
```bash
cd frontend
# Install dependencies
npm install
# Start development server
npm run dev
```
## 📚 Architecture
### Backend (GoClean Architecture)
```
backend/
├── cmd/server/ # Entry point
├── internal/
│ ├── domain/ # Business logic (entities, interfaces)
│ ├── application/ # Use cases (services, DTOs)
│ ├── infrastructure/ # External dependencies (DB, auth)
│ └── interfaces/ # API handlers & middleware
├── pkg/ # Public packages
└── tests/ # Test suites
```
### Frontend (Vue 3 Composition API)
```
frontend/
├── src/
│ ├── components/ # Reusable Vue components
│ ├── pages/ # Page components
│ ├── stores/ # Pinia state management
│ ├── services/ # API client
│ ├── router/ # Vue Router config
│ ├── assets/ # Styles and assets
│ └── main.js # Entry point
├── index.html
└── vite.config.js
```
## 🔐 Security Features
### Authentication
- **Argon2id password hashing** - Industry-standard PBKDF2
- **JWT tokens** with short expiration (1 hour)
- **HTTP-only secure cookies** for refresh tokens
- **CSRF protection** via SameSite cookies
- **Brute-force protection** via login attempt tracking
### Authorization
- **Role-based access control (RBAC)** per space:
- Owner: Full control
- Editor: Edit notes and categories
- Viewer: Read-only access
- **Space-level data isolation** - all queries include space_id
- **IDOR prevention** - middleware enforces ownership verification
### Data Security
- **Encryption at rest** for sensitive fields (OAuth secrets)
- **HTTPS/TLS** in production (Nginx reverse proxy)
- **Content Security Policy (CSP)** headers
- **XSS protection** - DOMPurify for markdown sanitization
- **SQL injection prevention** - parameterized queries (MongoDB)
### API Security
- **Rate limiting** - IP-based and user-based
- **Security headers** - HSTS, X-Frame-Options, X-Content-Type-Options
- **CORS properly configured** - whitelist origin domains
- **Input validation** on all endpoints
## 📦 API Endpoints
### Authentication
```
POST /api/v1/auth/register - Register new user
POST /api/v1/auth/login - Login user
POST /api/v1/auth/refresh - Refresh access token
POST /api/v1/auth/logout - Logout user
GET /health - Health check
```
### Spaces
```
GET /api/v1/spaces - List user's spaces
POST /api/v1/spaces - Create space
GET /api/v1/spaces/{spaceId} - Get space details
PUT /api/v1/spaces/{spaceId} - Update space
DELETE /api/v1/spaces/{spaceId} - Delete space
```
### Notes
```
GET /api/v1/spaces/{spaceId}/notes - List notes
POST /api/v1/spaces/{spaceId}/notes - Create note
GET /api/v1/spaces/{spaceId}/notes/{noteId} - Get note
PUT /api/v1/spaces/{spaceId}/notes/{noteId} - Update note
DELETE /api/v1/spaces/{spaceId}/notes/{noteId} - Delete note
GET /api/v1/spaces/{spaceId}/notes/search?q= - Search notes
```
### Categories
```
GET /api/v1/spaces/{spaceId}/categories - List categories
POST /api/v1/spaces/{spaceId}/categories - Create category
PUT /api/v1/spaces/{spaceId}/categories/{id} - Update category
DELETE /api/v1/spaces/{spaceId}/categories/{id} - Delete category
```
## 🗄️ Database Design
### MongoDB Collections
#### users
```javascript
{
_id: ObjectId,
email: String (unique),
username: String (unique),
password_hash: String,
first_name: String,
last_name: String,
avatar: String,
is_active: Boolean,
email_verified: Boolean,
created_at: Date,
updated_at: Date,
last_login_at: Date
}
```
#### spaces
```javascript
{
_id: ObjectId,
name: String,
description: String,
icon: String,
owner_id: ObjectId,
is_public: Boolean,
created_at: Date,
updated_at: Date
}
```
#### memberships
```javascript
{
_id: ObjectId,
user_id: ObjectId,
space_id: ObjectId,
role: String (owner|editor|viewer),
joined_at: Date,
invited_by: ObjectId,
invited_at: Date
}
```
#### notes
```javascript
{
_id: ObjectId,
space_id: ObjectId,
category_id: ObjectId,
title: String,
content: String (Markdown),
tags: [String],
is_pinned: Boolean,
is_favorite: Boolean,
created_by: ObjectId,
updated_by: ObjectId,
created_at: Date,
updated_at: Date,
viewed_at: Date
}
```
#### categories
```javascript
{
_id: ObjectId,
space_id: ObjectId,
name: String,
description: String,
parent_id: ObjectId (for hierarchical structure),
icon: String,
order: Number,
created_by: ObjectId,
updated_by: ObjectId,
created_at: Date,
updated_at: Date
}
```
#### Indexes
```
users: { email: 1 (unique), username: 1 (unique) }
spaces: { owner_id: 1, created_at: -1 }
memberships: { user_id: 1, space_id: 1 (unique), space_id: 1 }
notes: { space_id: 1, category_id: 1, updated_at: -1, text: "text" }
categories: { space_id: 1, parent_id: 1, order: 1 }
```
## 🐳 Deployment
### Docker Compose (Development/Testing)
```bash
docker-compose up -d
```
Services:
- **MongoDB** (port 27017)
- **Backend API** (port 8080)
- **Frontend** (port 5173)
- **Nginx Reverse Proxy** (port 80)
### Kubernetes (Production)
```bash
# Create namespace and secrets
kubectl apply -f devops/kubernetes/deployment.yaml
# Verify deployment
kubectl get pods -n noteapp
kubectl port-forward svc/frontend 5173:5173 -n noteapp
kubectl port-forward svc/backend 8080:8080 -n noteapp
```
Features:
- **StatefulSet** for MongoDB with persistent storage
- **Deployments** for backend and frontend with horizontal scaling
- **Ingress** for routing (requires ingress controller)
- **HPA** (Horizontal Pod Autoscaler) for automatic scaling
- **Liveness & readiness probes** for health checks
- **Resource limits** for fair resource allocation
## 🧪 Testing
### Backend Tests
```bash
cd backend
go test ./...
go test -v ./tests/unit/...
go test -v ./tests/integration/...
```
### Frontend Tests
```bash
cd frontend
npm run test
npm run test:watch
```
## 🔧 Configuration
### Environment Variables
#### Backend (.env)
```
MONGODB_URI=mongodb://admin:password@localhost:27017/noteapp
JWT_SECRET=your-secret-key-min-32-chars
ENCRYPTION_KEY=32-char-encryption-key-for-secrets
PORT=8080
LOG_LEVEL=info
ENV=development
```
#### Frontend (.env)
```
VITE_API_BASE_URL=http://localhost:8080
```
## 📝 Development Guidelines
### Code Structure
- Follow clean architecture principles
- Separate concerns: domain, application, infrastructure
- Use interfaces for dependency injection
- Keep services testable and focused
### Security Best Practices
1. **Never store secrets in code** - use environment variables
2. **Validate all inputs** on backend
3. **Sanitize outputs** before rendering
4. **Use HTTPS in production**
5. **Implement rate limiting** on APIs
6. **Log security events** (login attempts, permission denied)
7. **Audit trail** for sensitive operations
### Commit Message Format
```
[TYPE] Description
types: feat, fix, docs, style, refactor, test, chore
```
## 📖 API Documentation
### Request/Response Format
All API requests and responses use JSON.
```bash
# Example: Create Note
curl -X POST http://localhost:8080/api/v1/spaces/{spaceId}/notes \
-H "Authorization: Bearer {accessToken}" \
-H "Content-Type: application/json" \
-d '{
"title": "My Note",
"content": "# Markdown content",
"tags": ["tag1", "tag2"],
"category_id": null,
"is_pinned": false,
"is_favorite": false
}'
```
## 🚨 Error Handling
All errors return appropriate HTTP status codes:
- `400` - Bad Request
- `401` - Unauthorized
- `403` - Forbidden (insufficient permissions)
- `404` - Not Found
- `409` - Conflict (e.g., duplicate email)
- `429` - Too Many Requests (rate limit exceeded)
- `500` - Internal Server Error
## 🎯 Future Enhancements
- [ ] OAuth2/OIDC integration
- [ ] Email notifications
- [ ] Real-time collaboration (WebSockets)
- [ ] Full-text search with Elasticsearch
- [ ] Export to PDF/Markdown
- [ ] Mobile applications
- [ ] Plugin system
- [ ] Advanced permissions management
## 📄 License
MIT License - See LICENSE file
## 👥 Contributing
1. Fork the repository
2. Create a feature branch
3. Commit your changes
4. Push to the branch
5. Create a Pull Request
---
**Built with ❤️ for secure, collaborative note-taking**