first commit
This commit is contained in:
426
README.md
Normal file
426
README.md
Normal file
@@ -0,0 +1,426 @@
|
||||
# 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**
|
||||
Reference in New Issue
Block a user