31 KiB
CRM Server API
Modern backend API server pre CRM systém s pokročilou autentifikáciou, JMAP email integráciou, kontakt managementom a kompletnou bezpečnostnou vrstvou.
📋 Obsah
- Technológie
- Funkcie
- Systém rolí a autorizácia
- Architektúra
- Databázová schéma
- API Endpoints
- JMAP Email integrácia
- Bezpečnosť
- Inštalácia a spustenie
- Štruktúra projektu
- Testing
- Deployment
🚀 Technológie
Backend Stack
- Node.js 18+ - Runtime environment
- Express.js 4.21 - Web framework
- PostgreSQL 16 - Relačná databáza
- Drizzle ORM 0.44 - Type-safe ORM
- JWT (jsonwebtoken 9.0) - Token-based autentifikácia
- Bcrypt.js 3.0 - Password hashing
- Zod 4.1 - Schema validation
- Axios 1.13 - HTTP client pre JMAP
Security & Middleware
- Helmet 8.0 - HTTP security headers (CSP, HSTS)
- CORS 2.8 - Cross-Origin Resource Sharing
- Express Rate Limit 8.2 - Rate limiting protection
- Cookie Parser 1.4 - Cookie parsing
- Morgan 1.10 - HTTP request logger
- XSS Clean 0.1 - XSS protection
Dev Tools
- Nodemon 3.1 - Auto-restart development server
- Drizzle Kit 0.31 - Database migrations
- ESLint - Code linting
- Jest 29.7 - Testing framework
- Supertest 6.3 - HTTP API testing
Email Integration
- JMAP Protocol - Modern email protocol
- Truemail.sk - Email provider integration
✨ Funkcie
Autentifikácia a používatelia
-
✅ 3-krokový onboarding flow
- Krok 1: Login s dočasným heslom
- Krok 2: Nastavenie vlastného hesla
- Krok 3: Voliteľné pripojenie JMAP email účtu
-
✅ Session-based autentifikácia
- JWT tokens (Access + Refresh)
- HttpOnly cookies pre bezpečnosť
- Automatický refresh tokenov
-
✅ User management (Admin)
- Vytvorenie používateľa s automatickým temp heslom
- Zmena rolí (admin/member)
- Zmazanie používateľa
- Zoznam všetkých používateľov
Email Management (JMAP)
-
✅ Email synchronizácia
- Stiahnutie emailov z JMAP servera (Truemail.sk)
- Automatická synchronizácia len pre pridané kontakty
- Thread-based organizácia (konverzácie)
-
✅ Email operácie
- Označovanie ako prečítané/neprečítané
- Vyhľadávanie v emailoch (subject, body, sender)
- Odpovede na emaily cez JMAP
- Počítadlo neprečítaných správ
-
✅ Contact Management
- Objavovanie potenciálnych kontaktov z email odosielateľov
- Pridávanie kontaktov
- Editácia kontaktov (meno, poznámky)
- Odstránenie kontaktu
- Pri pridaní kontaktu sa automaticky syncujú všetky jeho emaily
Audit a Logging
-
✅ Kompletný audit trail
- Všetky dôležité akcie logované do DB
- IP adresa, user agent, timestamp
- Staré a nové hodnoty (pre change tracking)
- Success/error status
-
✅ Audit events
- Login/logout
- Password changes
- Email linking
- Contact additions/removals
- Role changes (admin akcie)
🔐 Systém rolí a autorizácia
Role Hierarchy
1. Admin
Plné oprávnenia:
- ✅ Všetko čo môže Member
- ✅ User management:
POST /api/admin/users- Vytvorenie používateľaGET /api/admin/users- Zoznam všetkých používateľovGET /api/admin/users/:id- Detail používateľaPATCH /api/admin/users/:id/role- Zmena roleDELETE /api/admin/users/:id- Zmazanie používateľa
Backend implementácia:
// Middleware chain
router.use(authenticate); // Overí JWT token
router.use(requireAdmin); // Overí role === 'admin'
2. Member
Základné oprávnenia:
- ✅ Vlastný profil a nastavenia
- ✅ Zmena vlastného hesla
- ✅ Pripojenie vlastného email účtu
- ✅ Správa vlastných kontaktov
- ✅ Vlastné emaily a konverzácie
NEMÁ prístup k:
- ❌ Admin endpointy (
/api/admin/*) - ❌ Údaje iných používateľov
- ❌ Zmena rolí
Middleware Chain
Autentifikácia:
// src/middlewares/auth/authMiddleware.js
export const authenticate = async (req, res, next) => {
// 1. Získaj token z cookie alebo Authorization header
// 2. Verifikuj JWT token
// 3. Načítaj user z DB
// 4. Pridaj user do req.user
}
Autorizácia (role-based):
// src/middlewares/auth/roleMiddleware.js
export const requireAdmin = (req, res, next) => {
if (req.user.role !== 'admin') {
return res.status(403).json({ error: 'Forbidden' })
}
next()
}
Bezpečnostný princíp: Backend Filtering
✅ Správne: Backend filtruje dáta podľa role
// Admin endpoint - middleware blokuje non-adminov
router.get('/api/admin/users', authenticate, requireAdmin, getAllUsers)
// Member endpoint - user vidí len svoje dáta
router.get('/api/contacts', authenticate, async (req, res) => {
// Service layer filtruje podľa req.user.id
const contacts = await getContactsByUserId(req.user.id)
res.json({ data: contacts })
})
❌ Zlé: Posielanie všetkých dát a filtrovanie na frontende
- Citlivé admin dáta by boli viditeľné v Network tab
- Security by bola len "visual" - nie skutočná
🏗️ Architektúra
Layered Architecture
┌─────────────────────────────────────┐
│ Routes Layer │ ← API endpoints, middleware chains
│ (auth.routes.js, admin.routes.js) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Controllers Layer │ ← Request handling, validation
│ (auth.controller.js, ...) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Services Layer │ ← Business logic
│ (auth.service.js, jmap.service.js)│
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Database Layer (Drizzle ORM) │ ← Data persistence
│ (schema.js) │
└─────────────────────────────────────┘
Middleware Pipeline
Request
│
├─→ Morgan (logging)
├─→ Helmet (security headers)
├─→ CORS (cross-origin)
├─→ Body Parser (JSON, URL-encoded)
├─→ Cookie Parser
├─→ Rate Limiter
│
├─→ Route Matching
│ │
│ ├─→ authenticate (JWT validation)
│ ├─→ requireAdmin (role check)
│ ├─→ validateBody (Zod schemas)
│ ├─→ Controller
│ └─→ Service → Database
│
├─→ Not Found Handler (404)
└─→ Error Handler (global catch)
💾 Databázová schéma
Users Table
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
username TEXT NOT NULL UNIQUE,
email TEXT UNIQUE, -- JMAP email (Truemail.sk)
email_password TEXT, -- Encrypted JMAP password
jmap_account_id TEXT, -- JMAP account ID
first_name TEXT,
last_name TEXT,
password TEXT, -- Bcrypt hash (permanent)
temp_password TEXT, -- Bcrypt hash (temporary)
changed_password BOOLEAN DEFAULT false,
role role_enum DEFAULT 'member' NOT NULL, -- 'admin' | 'member'
last_login TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
Contacts Table
CREATE TABLE contacts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
email TEXT NOT NULL,
name TEXT,
notes TEXT,
added_at TIMESTAMP DEFAULT NOW(),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
Emails Table
CREATE TABLE emails (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
contact_id UUID REFERENCES contacts(id) ON DELETE CASCADE,
jmap_id TEXT UNIQUE, -- JMAP message ID
message_id TEXT UNIQUE, -- Email Message-ID header
thread_id TEXT, -- Thread grouping
in_reply_to TEXT, -- Reply chain
"from" TEXT,
"to" TEXT,
subject TEXT,
body TEXT,
is_read BOOLEAN DEFAULT false,
date TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
Audit Logs Table
CREATE TABLE audit_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
action TEXT NOT NULL, -- 'login', 'password_change', ...
resource TEXT NOT NULL, -- 'user', 'contact', 'email'
resource_id TEXT,
old_value TEXT, -- JSON string
new_value TEXT, -- JSON string
ip_address TEXT,
user_agent TEXT,
success BOOLEAN DEFAULT true,
error_message TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
Relationships
- Users → Contacts (1:N) - User môže mať viacero kontaktov
- Users → Emails (1:N) - User má svoje emaily
- Contacts → Emails (1:N) - Email je priradený kontaktu
- Users → Audit Logs (1:N) - Audit log pre každú akciu
📡 API Endpoints
Autentifikácia (/api/auth)
| Method | Endpoint | Auth | Role | Popis |
|---|---|---|---|---|
| POST | /auth/login |
❌ | - | Login s temporary alebo permanent heslom |
| POST | /auth/set-password |
✅ | - | Nastavenie nového hesla (onboarding) |
| POST | /auth/link-email |
✅ | - | Pripojenie JMAP email účtu |
| POST | /auth/skip-email |
✅ | - | Preskočenie email setupu |
| POST | /auth/logout |
✅ | - | Odhlásenie (clear cookies) |
| GET | /auth/session |
✅ | - | Získanie aktuálnej session |
| GET | /auth/me |
✅ | - | Profil aktuálneho usera |
Príklad: Login request
POST /api/auth/login
Content-Type: application/json
{
"username": "jan.novak",
"password": "TempPass123!"
}
// Response:
{
"success": true,
"data": {
"user": { "id": "...", "username": "jan.novak", "role": "member" },
"needsPasswordChange": true,
"needsEmailSetup": true
}
}
// + Sets accessToken cookie (httpOnly)
Admin (/api/admin) - Len pre adminov
| Method | Endpoint | Auth | Role | Popis |
|---|---|---|---|---|
| POST | /admin/users |
✅ | Admin | Vytvorenie nového používateľa |
| GET | /admin/users |
✅ | Admin | Zoznam všetkých používateľov |
| GET | /admin/users/:userId |
✅ | Admin | Detail používateľa |
| PATCH | /admin/users/:userId/role |
✅ | Admin | Zmena role používateľa |
| DELETE | /admin/users/:userId |
✅ | Admin | Zmazanie používateľa |
Príklad: Vytvorenie používateľa
POST /api/admin/users
Authorization: Bearer <admin-token>
Content-Type: application/json
{
"username": "jana.horvathova",
"firstName": "Jana",
"lastName": "Horvathova",
"email": "jana.horvathova@truemail.sk", // voliteľné
"emailPassword": "jmap-password-123" // voliteľné
}
// Response:
{
"success": true,
"data": {
"user": {
"id": "...",
"username": "jana.horvathova",
"tempPassword": "X9kL#mP2qR4w", // ← Admin si toto skopíruje!
"emailSetup": true // true ak bol email poskytnutý
}
}
}
Kontakty (/api/contacts)
| Method | Endpoint | Auth | Role | Popis |
|---|---|---|---|---|
| GET | /contacts |
✅ | - | Všetky kontakty usera |
| GET | /contacts/discover |
✅ | - | Potenciálne kontakty (z JMAP) |
| POST | /contacts |
✅ | - | Pridať kontakt + sync jeho emailov |
| PATCH | /contacts/:id |
✅ | - | Upraviť kontakt |
| DELETE | /contacts/:id |
✅ | - | Odstrániť kontakt |
Príklad: Objavenie potenciálnych kontaktov
GET /api/contacts/discover?limit=50&search=john
Authorization: Bearer <token>
// Response:
{
"success": true,
"data": [
{
"email": "john.doe@example.com",
"name": "John Doe",
"emailCount": 15,
"isContact": false, // Ešte nie je v kontaktoch
"lastEmailDate": "2024-11-18T10:30:00Z"
},
...
]
}
Emaily (/api/emails)
| Method | Endpoint | Auth | Role | Popis |
|---|---|---|---|---|
| GET | /emails |
✅ | - | Všetky emaily usera |
| GET | /emails/search?q=... |
✅ | - | Vyhľadávanie v emailoch |
| GET | /emails/unread-count |
✅ | - | Počet neprečítaných emailov |
| POST | /emails/sync |
✅ | - | Manuálna synchronizácia z JMAP |
| GET | /emails/thread/:threadId |
✅ | - | Thread (konverzácia) |
| POST | /emails/thread/:threadId/read |
✅ | - | Označiť thread ako prečítaný |
| GET | /emails/contact/:contactId |
✅ | - | Emaily od konkrétneho kontaktu |
| PATCH | /emails/:jmapId/read |
✅ | - | Označiť email ako prečítaný |
| POST | /emails/reply |
✅ | - | Odpovedať na email cez JMAP |
Príklad: Odpoveď na email
POST /api/emails/reply
Authorization: Bearer <token>
Content-Type: application/json
{
"to": "john.doe@example.com",
"subject": "Re: Project Update",
"body": "Thanks for the update!",
"inReplyTo": "<message-id@example.com>",
"threadId": "thread-abc123"
}
// Response:
{
"success": true,
"data": {
"messageId": "<new-message-id@truemail.sk>",
"sentAt": "2024-11-18T15:45:00Z"
}
}
📧 JMAP Email integrácia
Čo je JMAP?
JMAP (JSON Meta Application Protocol) je moderný email protocol, náhrada za IMAP/SMTP.
Výhody:
- JSON-based API (nie custom text protocol ako IMAP)
- Stateless (REST-like)
- Efektívnejší bandwidth (delta updates)
- Lepší pre mobile aplikácie
Truemail.sk integrácia
JMAP Server: https://mail.truemail.sk/jmap/
Autentifikácia:
// Basic Auth
username: "user@truemail.sk"
password: "user-email-password"
JMAP Session:
// 1. Získaj session info
GET https://mail.truemail.sk/jmap/
Authorization: Basic <base64-credentials>
// Response obsahuje:
{
"accounts": {
"ba": { ... } // ← accountId
},
"apiUrl": "https://mail.truemail.sk/jmap/"
}
Synchronizácia emailov
Kedy sa syncujú emaily:
- ✅ Pri pridaní nového kontaktu - automaticky sa stiahnu všetky jeho emaily
- ✅ Manuálne cez
POST /api/emails/sync - ✅ Automaticky každých 60 sekúnd (frontend polling)
Proces:
// Service layer: src/services/jmap.service.js
export const syncContactEmails = async (user, contactEmail) => {
const jmapConfig = getJmapConfig(user)
// 1. JMAP Email/query - nájdi emaily od/pre kontakt
const emailIds = await jmapRequest(jmapConfig, [
['Email/query', {
accountId: jmapConfig.accountId,
filter: {
from: contactEmail
// OR to: contactEmail
}
}]
])
// 2. JMAP Email/get - získaj detaily emailov
const emails = await jmapRequest(jmapConfig, [
['Email/get', {
accountId: jmapConfig.accountId,
ids: emailIds
}]
])
// 3. Ulož do DB (emails table)
await saveEmailsToDB(emails, user.id, contact.id)
}
Thread support:
- Emaily sú zoskupené podľa
threadId(JMAP native) inReplyToheader pre reply chains- Frontend zobrazuje ako konverzácie
🔒 Bezpečnosť
1. Password Security
Bcrypt hashing:
// 12 rounds (2^12 iterations)
const hash = await bcrypt.hash(password, 12)
Strong password policy:
- Minimálne 8 znakov
- Aspoň 1 veľké písmeno
- Aspoň 1 malé písmeno
- Aspoň 1 číslo
- Aspoň 1 špeciálny znak
Email password encryption:
// AES-256-GCM encryption pre JMAP password
const encrypted = encryptPassword(emailPassword)
// Formát: "iv:authTag:encryptedText"
2. JWT Token Security
Access Token:
- Krátka životnosť (1 hodina)
- HttpOnly cookie (nedostupný pre JavaScript)
- Secure flag (len HTTPS v produkcii)
- SameSite=Strict (CSRF protection)
Token generation:
// src/utils/jwt.js
export const generateAccessToken = (user) => {
return jwt.sign(
{ id: user.id, role: user.role },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
)
}
3. Rate Limiting
Login protection:
// 5 pokusov za 15 minút
loginRateLimiter: {
windowMs: 15 * 60 * 1000,
max: 5
}
API protection:
// Development: 1000 req/15min
// Production: 100 req/15min
apiRateLimiter: {
windowMs: 15 * 60 * 1000,
max: process.env.NODE_ENV === 'production' ? 100 : 1000
}
Sensitive operations:
// Password changes, email changes
// Production: 3 pokusy za 15 minút
sensitiveOperationLimiter: { max: 3 }
4. HTTP Security Headers (Helmet)
helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"]
}
},
hsts: {
maxAge: 31536000, // 1 rok
includeSubDomains: true,
preload: true
}
})
5. Input Validation (Zod)
Všetky user inputy sú validované:
// src/validators/auth.validators.js
export const loginSchema = z.object({
username: z.string().min(3).max(50),
password: z.string().min(8)
})
// Middleware
validateBody(loginSchema)
6. SQL Injection Protection
Drizzle ORM používa prepared statements:
// ✅ Bezpečné - parametrizované query
await db.select()
.from(users)
.where(eq(users.username, username)) // ← automaticky escaped
7. CORS Configuration
cors({
origin: process.env.CORS_ORIGIN || 'http://localhost:5173',
credentials: true, // Povoľ cookies
optionsSuccessStatus: 200
})
8. Audit Logging
Každá dôležitá akcia je logovaná:
await logAuditEvent({
userId: user.id,
action: 'login',
resource: 'auth',
ipAddress: req.ip,
userAgent: req.headers['user-agent'],
success: true
})
📦 Inštalácia a spustenie
Požiadavky
- Node.js 18+ a npm 9+
- PostgreSQL 16+
- Docker (voliteľné, pre lokálne DB)
Inštalácia
1. Klonovanie a Dependencies
npm install
2. Konfigurácia Environment Variables
Skopírujte .env.example do .env a upravte hodnoty:
cp .env.example .env
Dôležité premenné:
JWT_SECRET- Zmeňte v produkcii!JWT_REFRESH_SECRET- Zmeňte v produkcii!BETTER_AUTH_SECRET- Zmeňte v produkcii!DB_*- Databázové credentialsJMAP_*- Email server credentials
3. Databáza Setup
Spustite PostgreSQL (Docker):
docker compose up -d postgres
Vygenerujte a aplikujte migrácie:
npm run db:generate
npm run db:migrate
4. Seed Admin Account
Vytvorte prvý admin účet:
npm run db:seed
DÔLEŽITÉ: Uložte si vygenerované temporary password!
5. Spustenie Servera
Development mode:
npm run dev
Production mode:
npm start
Server beží na http://localhost:5000
API Endpointy
Public Endpoints
Login
POST /api/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "temporary-password"
}
Response:
{
"success": true,
"data": {
"user": { ... },
"tokens": {
"accessToken": "...",
"refreshToken": "..."
},
"needsPasswordChange": true,
"needsEmailSetup": true
}
}
Protected Endpoints (vyžadujú JWT token)
Set New Password (Krok 2)
POST /api/auth/set-password
Authorization: Bearer <token>
Content-Type: application/json
{
"newPassword": "NewSecurePass123!",
"confirmPassword": "NewSecurePass123!"
}
Link Email (Krok 3)
POST /api/auth/link-email
Authorization: Bearer <token>
Content-Type: application/json
{
"email": "user@example.com"
}
Skip Email Setup
POST /api/auth/skip-email
Authorization: Bearer <token>
Get Current User
GET /api/auth/me
Authorization: Bearer <token>
Logout
POST /api/auth/logout
Authorization: Bearer <token>
Admin Endpoints (vyžadujú admin rolu)
Create User
POST /api/admin/users
Authorization: Bearer <admin-token>
Content-Type: application/json
{
"username": "newuser",
"tempPassword": "TempPass123!",
"role": "member",
"firstName": "John",
"lastName": "Doe"
}
Get All Users
GET /api/admin/users
Authorization: Bearer <admin-token>
Get User by ID
GET /api/admin/users/:userId
Authorization: Bearer <admin-token>
Change User Role
PATCH /api/admin/users/:userId/role
Authorization: Bearer <admin-token>
Content-Type: application/json
{
"role": "admin"
}
Delete User
DELETE /api/admin/users/:userId
Authorization: Bearer <admin-token>
Databázová Schéma
Users Table
- id (UUID)
- username (unique)
- email (unique, nullable)
- email_verified (boolean)
- first_name
- last_name
- password (bcrypt hash)
- temp_password (bcrypt hash)
- changed_password (boolean)
- role (enum: admin, member)
- last_login
- created_at
- updated_at
Sessions Table
- id (text)
- user_id (UUID, FK)
- expires_at
- ip_address
- user_agent
- created_at
Audit Logs Table
- id (UUID)
- user_id (UUID, FK, nullable)
- action
- resource
- resource_id
- old_value (JSON)
- new_value (JSON)
- ip_address
- user_agent
- success (boolean)
- error_message
- created_at
Validačné Pravidlá
Password Policy
- Minimálne 8 znakov
- Aspoň 1 veľké písmeno
- Aspoň 1 malé písmeno
- Aspoň 1 číslo
- Aspoň 1 špeciálny znak
Username Policy
- 3-50 znakov
- Iba písmená, čísla, pomlčky a podčiarkovníky
Rate Limiting
- Login endpoint: 5 pokusov / 15 minút
- API endpoints: 100 requestov / 15 minút
- Citlivé operácie: 3 pokusy / 15 minút
Audit Logging
Všetky dôležité akcie sú automaticky logované:
- Login attempts (úspešné aj neúspešné)
- Password changes
- Email linking & verification
- Role changes
- User creation
- A ďalšie...
Security Best Practices
- HTTPS Only - V produkcii vždy používajte HTTPS
- Strong Secrets - Zmeňte všetky secret keys v
.env - Regular Updates - Aktualizujte dependencies
- Monitor Logs - Sledujte audit logs
- Backup Database - Pravidelné zálohy PostgreSQL
Database Commands
# Generovanie migrácií
npm run db:generate
# Aplikovanie migrácií
npm run db:migrate
# Push schema (alternative to migrations)
npm run db:push
# Drizzle Studio (GUI)
npm run db:studio
# Seed admin account
npm run db:seed
Testing
Spustenie testov:
npm test
📁 Štruktúra projektu
crm-server/
├── src/
│ ├── api/ # (unused, legacy?)
│ ├── config/
│ │ ├── database.js # Drizzle DB connection
│ │ └── jmap.js # JMAP configuration
│ │
│ ├── controllers/ # Request handlers
│ │ ├── auth.controller.js # Login, set password, link email
│ │ ├── admin.controller.js # User management (admin only)
│ │ ├── contact.controller.js # Contact CRUD
│ │ └── crm-email.controller.js # Email sync, search, replies
│ │
│ ├── db/
│ │ ├── schema.js # Drizzle tables (users, contacts, emails, audit_logs)
│ │ ├── migrate.js # Migration runner
│ │ ├── migrations/ # Auto-generated SQL migrations
│ │ └── seeds/
│ │ ├── admin.seed.js # Seed admin account
│ │ └── testuser.seed.js # Seed test user
│ │
│ ├── middlewares/
│ │ ├── auth/
│ │ │ ├── authMiddleware.js # JWT validation (authenticate)
│ │ │ └── roleMiddleware.js # Role check (requireAdmin, requireOwnerOrAdmin)
│ │ ├── security/
│ │ │ ├── rateLimiter.js # Login, API, sensitive operation limiters
│ │ │ └── validateInput.js # Zod schema validation
│ │ └── global/
│ │ ├── errorHandler.js # Global error handler
│ │ ├── notFound.js # 404 handler
│ │ └── validateBody.js # Body validation
│ │
│ ├── routes/ # API route definitions
│ │ ├── auth.routes.js # /api/auth/* (login, set-password, link-email)
│ │ ├── admin.routes.js # /api/admin/* (user management)
│ │ ├── contact.routes.js # /api/contacts/* (CRUD)
│ │ └── crm-email.routes.js # /api/emails/* (sync, search, reply)
│ │
│ ├── services/ # Business logic layer
│ │ ├── auth.service.js # User authentication, password management
│ │ ├── contact.service.js # Contact management
│ │ ├── crm-email.service.js # Email database operations
│ │ ├── jmap.service.js # JMAP API integration (Truemail.sk)
│ │ ├── email.service.js # Email utilities
│ │ └── audit.service.js # Audit logging
│ │
│ ├── validators/ # Zod validation schemas
│ │ └── auth.validators.js # Login, password, email schemas
│ │
│ ├── utils/ # Helper utilities
│ │ ├── errors.js # Custom error classes
│ │ ├── jwt.js # JWT generation & verification
│ │ ├── logger.js # Logging utility
│ │ └── password.js # Bcrypt hashing, temp password generation, encryption
│ │
│ ├── app.js # Express app configuration
│ └── index.js # Server entry point
│
├── __tests__/ # Jest test files
├── postgres/ # Docker volume for PostgreSQL data
├── .env.example # Environment variables template
├── .env # Environment variables (gitignored)
├── docker-compose.yml # PostgreSQL Docker setup
├── drizzle.config.js # Drizzle Kit configuration
├── package.json # NPM dependencies and scripts
└── README.md # This file
Kľúčové súbory
src/app.js
- Express aplikácia setup
- Middleware chain (security, CORS, parsing, rate limiting)
- Route mounting
- Global error handling
src/db/schema.js
- Drizzle ORM schema definície
- Tables: users, contacts, emails, audit_logs
- Relationships a indexy
src/services/jmap.service.js
- JMAP API client pre Truemail.sk
- Email sync, search, send reply
- Mailbox management
src/middlewares/auth/authMiddleware.js
- JWT token validation
- User session loading
- Pridáva
req.userdo requestu
src/middlewares/auth/roleMiddleware.js
- Role-based access control
requireAdmin- blokuje non-adminovrequireOwnerOrAdmin- vlastník alebo admin
🧪 Testing
Spustenie testov
npm test
Test coverage (TODO)
- Unit testy pre services
- Integration testy pre API endpoints
- E2E testy pre autentifikačný flow
🚀 Deployment
Production Checklist
1. Environment Variables
# Zmeň všetky secret keys!
JWT_SECRET=<strong-random-key>
JWT_REFRESH_SECRET=<strong-random-key>
BETTER_AUTH_SECRET=<strong-random-key>
# Production settings
NODE_ENV=production
CORS_ORIGIN=https://your-frontend-domain.com
RATE_LIMIT_MAX_REQUESTS=100
# Database
DB_HOST=your-production-db-host
DB_PORT=5432
DB_USER=crm_user
DB_PASSWORD=<strong-db-password>
DB_NAME=crm_production
2. HTTPS Setup
- Použite reverse proxy (Nginx, Caddy)
- SSL certifikáty (Let's Encrypt)
- Redirect HTTP → HTTPS
3. Database
- Povolte SSL connections
- Pravidelné backupy (pg_dump)
- Monitoring (pg_stat_statements)
4. Security
- Firewall rules (povoľ len potrebné porty)
- DDoS protection (Cloudflare, AWS Shield)
- Monitoring a alerting (Sentry, DataDog)
5. Deployment Platforms
- VPS: DigitalOcean, Linode, Vultr
- Cloud: AWS (EC2, RDS), Google Cloud, Azure
- Platform: Railway, Render, Fly.io
Docker Deployment
# Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 5000
CMD ["npm", "start"]
# Build
docker build -t crm-server .
# Run
docker run -d \
--name crm-api \
-p 5000:5000 \
--env-file .env \
crm-server
📝 TODO / Budúce vylepšenia
- Refresh token rotation
- Email verification (2FA)
- Password reset flow
- User profile pictures
- Advanced audit log filtering
- Webhook support
- Real-time notifications (WebSockets)
- Multi-tenant support
- API rate limiting per user
- Automated backup system
🐛 Known Issues
- JMAP sync môže byť pomalý pri veľkom množstve emailov (optimalizovať batch size)
- Rate limiter je in-memory (nepersistuje cez reštarty) - zvážiť Redis
- Session refresh token nemá automatic rotation
📞 Podpora a Kontakt
Pre technické otázky a bug reporting:
- Vytvor Issue v repozitári
- Email: richard@example.com
📄 Licencia
MIT License
Copyright (c) 2024 Richard Tekula
👨💻 Autor
Richard Tekula
Backend Developer
⚠️ PRODUCTION WARNING:
Tento projekt je v aktívnom vývoji. Pred production deploymentom nezabudni:
- ✅ Zmeniť všetky secret keys v
.env - ✅ Nastaviť HTTPS (reverse proxy)
- ✅ Konfigurovať firewall pravidlá
- ✅ Nastaviť monitoring a alerting (Sentry, Prometheus)
- ✅ Pravidelné security audity (
npm audit) - ✅ Database backupy (automatizované)
- ✅ Load balancing (pri vysokom trafficu)
- ✅ CDN pre static assets
- ✅ GDPR compliance (ak potrebné)
Happy coding! 🚀