Migrate from Firebase to file-based storage system
- Remove Firebase dependency and all Firebase code - Implement local file-based storage with encryption - Create custom authentication system with password hashing - Add API routes for auth (register/login) and data operations - Create FileStorageService for server-side file I/O - Add AuthService for client-side authentication wrapper - Update all components to use new storage system - Add comprehensive documentation (FILE_STORAGE.md, MIGRATION_SUMMARY.md) - Improve security with AES-GCM encryption and SHA-256 password hashing - Add ErrorBoundary component for better error handling - Fix multiple bugs: date serialization, transaction deletion, envelope calculations
This commit is contained in:
1 parent
174b247c6d
commit
959249ab22
22 files changed
+1538
-1157
No files matched your search
+139
@@ -0,0 +1,139 @@
|
||||
# File-Based Storage System
|
||||
|
||||
This application uses a local file-based storage system instead of cloud databases like Firebase. All user data is stored on the server in JSON files.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Storage Location
|
||||
- All user data is stored in the `/data` directory
|
||||
- User credentials: `/data/users.json`
|
||||
- User budget data: `/data/{userId}.json`
|
||||
|
||||
### Authentication Flow
|
||||
1. User registers with email and password
|
||||
2. Password is hashed using SHA-256
|
||||
3. User credentials stored in `/data/users.json`
|
||||
4. Unique userId generated and returned to client
|
||||
5. Client stores userId in localStorage for session persistence
|
||||
|
||||
### Data Storage Flow
|
||||
1. Client authenticates and receives userId
|
||||
2. Client makes API calls with userId in headers
|
||||
3. Server reads/writes user data file at `/data/{userId}.json`
|
||||
4. Data is encrypted server-side using AES-GCM encryption
|
||||
5. Encrypted data saved to disk
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Authentication
|
||||
- `POST /api/auth/register` - Register new user
|
||||
- Body: `{ email, password }`
|
||||
- Returns: `{ userId, email }`
|
||||
|
||||
- `POST /api/auth/login` - Login existing user
|
||||
- Body: `{ email, password }`
|
||||
- Returns: `{ userId, email }`
|
||||
|
||||
### Data Operations
|
||||
- `GET /api/data` - Load user data
|
||||
- Headers: `x-user-id: {userId}`
|
||||
- Returns: `{ data: UserData }`
|
||||
|
||||
- `POST /api/data` - Save user data
|
||||
- Headers: `x-user-id: {userId}`
|
||||
- Body: `{ accounts, envelopes, transactions, setupCompleted }`
|
||||
- Returns: `{ success: true }`
|
||||
|
||||
## Security
|
||||
|
||||
### Password Security
|
||||
- Passwords hashed with SHA-256 before storage
|
||||
- Original passwords never stored
|
||||
- Hash comparison done server-side
|
||||
|
||||
### Data Encryption
|
||||
- All user budget data encrypted with AES-GCM
|
||||
- Encryption key stored in environment variable: `ENCRYPTION_KEY`
|
||||
- 256-bit encryption with PBKDF2 key derivation
|
||||
- Unique salt and IV for each encryption operation
|
||||
|
||||
### Session Management
|
||||
- UserId stored in browser localStorage
|
||||
- No sensitive data in browser storage
|
||||
- Server validates userId on every request
|
||||
- User can sign out to clear session
|
||||
|
||||
## Environment Variables
|
||||
|
||||
```bash
|
||||
# .env.local
|
||||
ENCRYPTION_KEY=your-32-byte-hex-key-here
|
||||
```
|
||||
|
||||
Generate a secure key with:
|
||||
```bash
|
||||
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
/data
|
||||
├── users.json # User credentials (email → userId mapping)
|
||||
├── {userId1}.json # User 1 budget data (encrypted)
|
||||
├── {userId2}.json # User 2 budget data (encrypted)
|
||||
└── .gitignore # Excludes all JSON files from git
|
||||
```
|
||||
|
||||
## Data Backup
|
||||
|
||||
Since all data is stored in local files:
|
||||
1. **Regular Backups**: Copy `/data` directory to secure backup location
|
||||
2. **Version Control**: The `/data` directory is gitignored for security
|
||||
3. **Migration**: Simply copy files to move data between servers
|
||||
4. **Export**: Users can export their data via the app's export feature
|
||||
|
||||
## Development Setup
|
||||
|
||||
1. Install dependencies:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
2. Create `.env.local`:
|
||||
```bash
|
||||
cp .env.local.example .env.local
|
||||
```
|
||||
|
||||
3. Generate encryption key:
|
||||
```bash
|
||||
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
||||
```
|
||||
|
||||
4. Update `.env.local` with your encryption key
|
||||
|
||||
5. Start development server:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Production Deployment
|
||||
|
||||
1. Set environment variable `ENCRYPTION_KEY` on your server
|
||||
2. Ensure `/data` directory has write permissions
|
||||
3. Set up automated backups of `/data` directory
|
||||
4. Use HTTPS for all API communication
|
||||
5. Consider adding rate limiting to API routes
|
||||
6. Monitor `/data` directory disk usage
|
||||
|
||||
## Migration from Firebase
|
||||
|
||||
The app previously used Firebase. The migration to file-based storage included:
|
||||
- ✅ Removed Firebase SDK dependency
|
||||
- ✅ Created custom authentication system
|
||||
- ✅ Implemented file-based data storage
|
||||
- ✅ Added encryption for data at rest
|
||||
- ✅ Created API routes for all operations
|
||||
- ✅ Updated all components to use new auth system
|
||||
|
||||
All Firebase code has been removed and replaced with local file storage.
|
||||
Reference in new issue
Block a user