added encryption

This commit is contained in:
2026-03-09 10:54:07 +05:30
parent 6e184dc590
commit 6720e28d08
27 changed files with 2093 additions and 709 deletions

View File

@@ -39,15 +39,15 @@ Stores user profile information. One document per unique email.
#### Field Descriptions
| Field | Type | Required | Notes |
| ----------- | ------ | -------- | ----------------------------------------- |
| `_id` | ObjectId | Yes | Unique primary key, auto-generated |
| `email` | String | Yes | User's email; unique constraint; indexed |
| `displayName` | String | Yes | User's display name (from Google Auth) |
| `photoURL` | String | No | User's profile photo URL |
| `theme` | String | Yes | Theme preference: "light" or "dark" |
| `createdAt` | Date | Yes | Account creation timestamp |
| `updatedAt` | Date | Yes | Last profile update timestamp |
| Field | Type | Required | Notes |
| ------------- | -------- | -------- | ---------------------------------------- |
| `_id` | ObjectId | Yes | Unique primary key, auto-generated |
| `email` | String | Yes | User's email; unique constraint; indexed |
| `displayName` | String | Yes | User's display name (from Google Auth) |
| `photoURL` | String | No | User's profile photo URL |
| `theme` | String | Yes | Theme preference: "light" or "dark" |
| `createdAt` | Date | Yes | Account creation timestamp |
| `updatedAt` | Date | Yes | Last profile update timestamp |
#### Unique Constraints
@@ -84,11 +84,11 @@ Stores journal entries for each user. Each entry has a logical journal date and
mood: "happy" | "sad" | "neutral" | "anxious" | "grateful" | null,
tags: string[],
isPublic: boolean,
entryDate: Date, // Logical journal date
createdAt: Date,
updatedAt: Date,
encryption: {
encrypted: boolean,
iv: string | null, // Base64-encoded initialization vector
@@ -99,19 +99,19 @@ Stores journal entries for each user. Each entry has a logical journal date and
#### Field Descriptions
| Field | Type | Required | Notes |
| ---------- | ------ | -------- | ------------------------------------------ |
| `_id` | ObjectId | Yes | Entry ID; auto-generated; indexed |
| `userId` | ObjectId | Yes | Reference to user._id; indexed; enforced |
| `title` | String | Yes | Entry title/headline |
| `content` | String | Yes | Entry body content |
| `mood` | String | No | Mood selector (null if not set) |
| `tags` | Array | Yes | Array of user-defined tags [] |
| `isPublic` | Bool | Yes | Public sharing flag (currently unused) |
| `entryDate` | Date | Yes | Logical journal date (start of day, UTC) |
| `createdAt` | Date | Yes | Database write timestamp |
| `updatedAt` | Date | Yes | Last modification timestamp |
| `encryption` | Object | Yes | Encryption metadata (nested) |
| Field | Type | Required | Notes |
| ------------ | -------- | -------- | ----------------------------------------- |
| `_id` | ObjectId | Yes | Entry ID; auto-generated; indexed |
| `userId` | ObjectId | Yes | Reference to user.\_id; indexed; enforced |
| `title` | String | Yes | Entry title/headline |
| `content` | String | Yes | Entry body content |
| `mood` | String | No | Mood selector (null if not set) |
| `tags` | Array | Yes | Array of user-defined tags [] |
| `isPublic` | Bool | Yes | Public sharing flag (currently unused) |
| `entryDate` | Date | Yes | Logical journal date (start of day, UTC) |
| `createdAt` | Date | Yes | Database write timestamp |
| `updatedAt` | Date | Yes | Last modification timestamp |
| `encryption` | Object | Yes | Encryption metadata (nested) |
#### Encryption Metadata
@@ -124,6 +124,7 @@ Stores journal entries for each user. Each entry has a logical journal date and
```
**Notes:**
- `encrypted: false` by default (plain text storage)
- When setting `encrypted: true`, client provides `iv` and `algorithm`
- Server stores metadata but does NOT decrypt; decryption happens client-side
@@ -160,26 +161,26 @@ Indexes optimize query performance. All indexes are created by the `scripts/crea
```javascript
// Unique index on email (prevents duplicates)
db.users.createIndex({ email: 1 }, { unique: true })
db.users.createIndex({ email: 1 }, { unique: true });
// For sorting users by creation date
db.users.createIndex({ createdAt: -1 })
db.users.createIndex({ createdAt: -1 });
```
### Entries Indexes
```javascript
// Compound index for history pagination (most recent first)
db.entries.createIndex({ userId: 1, createdAt: -1 })
db.entries.createIndex({ userId: 1, createdAt: -1 });
// Compound index for calendar queries by date
db.entries.createIndex({ userId: 1, entryDate: 1 })
db.entries.createIndex({ userId: 1, entryDate: 1 });
// For tag-based searches (future feature)
db.entries.createIndex({ tags: 1 })
db.entries.createIndex({ tags: 1 });
// For sorting by entry date
db.entries.createIndex({ entryDate: -1 })
db.entries.createIndex({ entryDate: -1 });
```
### Index Rationale
@@ -385,15 +386,15 @@ iso_string = dt.isoformat()
### What Changed
| Aspect | Old Schema | New Schema |
| -------------- | ------------------------- | ------------------------------- |
| Users | Many per email possible | One per email (unique) |
| User _id | ObjectId (correct) | ObjectId (unchanged) |
| Entry userId | String | ObjectId |
| Entry date | Only `createdAt` | `createdAt` + `entryDate` |
| Encryption | Not supported | Metadata in `encryption` field |
| Settings | Separate collection | Merged into `users.theme` |
| Indexes | None | Comprehensive indexes |
| Aspect | Old Schema | New Schema |
| ------------ | ----------------------- | ------------------------------ |
| Users | Many per email possible | One per email (unique) |
| User \_id | ObjectId (correct) | ObjectId (unchanged) |
| Entry userId | String | ObjectId |
| Entry date | Only `createdAt` | `createdAt` + `entryDate` |
| Encryption | Not supported | Metadata in `encryption` field |
| Settings | Separate collection | Merged into `users.theme` |
| Indexes | None | Comprehensive indexes |
### Migration Steps
@@ -471,7 +472,8 @@ mongorestore --db grateful_journal ./backup-entries
### Q: How do I encrypt entry content?
**A:**
**A:**
1. Client encrypts content client-side using a key (not transmitted)
2. Client sends encrypted content + metadata (iv, algorithm)
3. Server stores content + encryption metadata as-is
@@ -480,14 +482,17 @@ mongorestore --db grateful_journal ./backup-entries
### Q: What if I have duplicate users?
**A:** Run the migration script:
```bash
python backend/scripts/migrate_data.py
```
It detects duplicates, keeps the oldest, and consolidates entries.
### Q: Should I paginate entries?
**A:** Yes. Use `skip` and `limit` to prevent loading thousands of entries:
```
GET /api/entries/{user_id}?skip=0&limit=50
```
@@ -495,6 +500,7 @@ GET /api/entries/{user_id}?skip=0&limit=50
### Q: How do I query entries by date range?
**A:** Use the calendar endpoint or build a query:
```python
db.entries.find({
"userId": oid,