penlify-server
v1.0.0
Published
Backend API server for Penlify note-taking application using Fastify, PostgreSQL, and secure-node-auth.
Readme
Penlify Server
Backend API server for Penlify note-taking application using Fastify, PostgreSQL, and secure-node-auth.
Features
- ✅ Fastify web framework (high performance)
- ✅ PostgreSQL database
- ✅ JWT authentication with refresh tokens
- ✅ Email verification (6-digit codes)
- ✅ Password reset (6-digit codes)
- ✅ Rate limiting
- ✅ CORS enabled
- ✅ Auto-creates database tables
- ✅ Production-ready security
Quick Start
1. Install Dependencies
npm install2. Configure Environment
Create .env file (already exists with your config):
DB_HOST=95.111.234.0
DB_USER=postgres
DB_PASSWORD=your_password
DB_NAME=postgres
DB_PORT=5432
JWT_ACCESS_SECRET=your_secret_here
JWT_REFRESH_SECRET=your_refresh_secret_here3. Run Server
# Development (with auto-reload)
npm run dev
# Production
npm startAPI Endpoints
Public Endpoints
Health Check
GET /Authentication
POST /auth/register
POST /auth/login
POST /auth/refresh
POST /auth/logoutEmail Verification
POST /auth/send-verification-code
POST /auth/verify-codePassword Reset
POST /auth/send-password-reset-code
POST /auth/reset-password-with-codeProtected Endpoints (Require Bearer Token)
User Profile
GET /auth/me
PATCH /auth/me
POST /auth/change-passwordAPI Routes
GET /api/testExample Usage
Register User
curl -X POST http://localhost:3000/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "SecurePass123!",
"firstName": "John",
"lastName": "Doe"
}'Login
curl -X POST http://localhost:3000/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "SecurePass123!"
}'Get Profile (Protected)
curl -X GET http://localhost:3000/auth/me \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Send Verification Code
curl -X POST http://localhost:3000/auth/send-verification-code \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]"
}'Verify Email
curl -X POST http://localhost:3000/auth/verify-code \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"code": "123456"
}'Database Tables
The following tables are automatically created:
secure_auth_users- User accountssecure_auth_refresh_tokens- JWT refresh tokenssecure_auth_login_attempts- Login attempt trackingsecure_auth_verification_tokens- Email verification codes
Security Features
- ✅ Bcrypt password hashing (10 rounds)
- ✅ JWT access tokens (15 min expiry)
- ✅ JWT refresh tokens (7 days expiry)
- ✅ Rate limiting (100 req/15min)
- ✅ Account lockout after 5 failed attempts
- ✅ SQL injection protection
- ✅ CORS protection
- ✅ Token blacklisting on logout
Environment Variables
| Variable | Description | Default |
| ------------------------ | ----------------------------- | --------- |
| DB_HOST | PostgreSQL host | localhost |
| DB_PORT | PostgreSQL port | 5432 |
| DB_USER | Database user | postgres |
| DB_PASSWORD | Database password | - |
| DB_NAME | Database name | postgres |
| JWT_ACCESS_SECRET | JWT access token secret | - |
| JWT_REFRESH_SECRET | JWT refresh token secret | - |
| JWT_ACCESS_EXPIRES_IN | Access token expiry | 15m |
| JWT_REFRESH_EXPIRES_IN | Refresh token expiry | 7d |
| BCRYPT_ROUNDS | Bcrypt hash rounds | 10 |
| MAX_LOGIN_ATTEMPTS | Max failed login attempts | 5 |
| LOCKOUT_TIME | Account lockout duration (ms) | 900000 |
| PORT | Server port | 3000 |
Development
# Install dependencies
npm install
# Run in development mode (auto-reload)
npm run dev
# Run in production mode
npm startTroubleshooting
Cannot connect to database
- Verify PostgreSQL is running
- Check credentials in
.env - Ensure database exists
Invalid token errors
- Access tokens expire in 15 minutes
- Use refresh token endpoint to get new access token
Account locked
- Wait 15 minutes after 5 failed login attempts
- Or adjust
LOCKOUT_TIMEin.env
Next Steps
- ✅ Server is ready to run
- Start server:
npm run dev - Test endpoints with curl or Postman
- Connect your frontend Auth component
- Add your application's API routes in
/apisection
