PostgreSQL Pro | Database Mastery
1.32K subscribers
1 photo
28 links
🐘 PostgreSQL Mastery Hub

🎯 What you get:
- Daily optimization tips
- Performance guides
- Real-world solutions
- Query debugging help
- Production best practices

📈 Join 500+ developers improving their PostgreSQL skills
Download Telegram
🔐 DECEMBER DAY 2: Add Auth in 30 Minutes

Yesterday: Database
Today: Authentication
Tomorrow: Your core feature

Pick Your Auth Method:
Option 1: Password Auth (Classic)

npm install bcrypt jsonwebtoken

// Register
app.post('/api/register', async (req, res) => {
const { email, password } = req.body;
const hashedPassword = await bcrypt.hash(password, 10);

const result = await pool.query(
'INSERT INTO users (email, password_hash) VALUES ($1, $2) RETURNING id, email',
[email, hashedPassword]
);

const token = jwt.sign(
{ userId: result.rows[0].id },
process.env.JWT_SECRET || 'december-2024',
{ expiresIn: '7d' }
);

res.json({ user: result.rows[0], token });
});

// Login
app.post('/api/login', async (req, res) => {
const { email, password } = req.body;

const user = await pool.query('SELECT * FROM users WHERE email = $1', [email]);
if (!user.rows[0]) return res.status(401).json({ error: 'Invalid credentials' });

const validPassword = await bcrypt.compare(password, user.rows[0].password_hash);
if (!validPassword) return res.status(401).json({ error: 'Invalid credentials' });

const token = jwt.sign(
{ userId: user.rows[0].id },
process.env.JWT_SECRET || 'december-2024',
{ expiresIn: '7d' }
);

res.json({ token });
});


Option 2: Magic Links (No Passwords!)

// Send magic link
app.post('/api/magic', async (req, res) => {
const token = crypto.randomBytes(32).toString('hex');

await pool.query(
`INSERT INTO magic_tokens (email, token, expires_at)
VALUES ($1, $2, NOW() + INTERVAL '15 minutes')`,
[req.body.email, token]
);

console.log(`Magic link: https://localhost:3000/magic/${token}`);
res.json({ message: 'Check console for magic link' });
});

// Verify magic link
app.get('/magic/:token', async (req, res) => {
const result = await pool.query(
'SELECT email FROM magic_tokens WHERE token = $1 AND expires_at > NOW()',
[req.params.token]
);

if (!result.rows[0]) return res.status(401).json({ error: 'Invalid token' });

// Create/get user and return JWT
const token = jwt.sign({ email: result.rows[0].email }, 'december-2024');
res.json({ token });
});


Protect Your Routes:

const authenticate = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'No token' });

try {
req.user = jwt.verify(token, process.env.JWT_SECRET || 'december-2024');
next();
} catch {
res.status(401).json({ error: 'Invalid token' });
}
};

// Use it
app.get('/api/me', authenticate, (req, res) => {
res.json({ userId: req.user.userId });
});


🎯 Day 2 Success = 3 Things Work:

Can register/login
Get a token back
Token protects routes

📊 Day 2 Live Stats:

Password auth: 67 devs
Magic links: 23 devs
Still building: 12 devs

Quick Test:
# Register
curl -X POST localhost:3000/api/register \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"test123"}'


Day 2 Check-in:

Auth working?
🔐 Which method?
⏱️ Time taken?

Tomorrow: Build your ONE core feature

Pro tip: Don't overthink. Basic auth shipped > Perfect auth planned.

Who has auth working? 🔐

#December #Day2 #Auth #Building

@postgres
2🔥2