const app = require('./app') const db = require('./db') const log = require('./log') const { hashPassword, genSeed, genKey, authorize, createToken } = require('./security') const { sendmail } = require('./mail') const uuid = require('uuid/v4') const { getRss } = require('./rss') app.post('/signup', async (req, res) => { if (!req.body.name) throw new Error('Missing name') if (!req.body.password) throw new Error('Missing password') if (!req.body.email) throw new Error('Missing email') const email = req.body.email.toLowerCase().trim() const existing = await db.users.get(email) if (existing && existing.confirmed) throw new Error('User already exists.') const seed = genSeed() const password = hashPassword({password: req.body.password, email, seed}) const confirmKey = genKey() const user = { name: req.body.name, email: req.body.email, password, seed, ip: req.ip, confirmed: false, confirmKey, keyCreated: Date.now(), failCount: 0, created: Date.now() } const mailResult = await sendmail({ to: `${user.name} <${user.email}>`, from: `RSS Unlimited `, subject: `Please verify your email address.`, text: `Enter the following code to confirm your email address on RSSUnlimited.com:\n\n${confirmKey}` }) await db.users.put(email, user) log({ type: 'user-created', user }) res.status(200).send({}) }) app.post('/confirm', async (req, res) => { if (!req.body.confirmKey) throw new Error('Missing confirmKey') if (!req.body.email) throw new Error('Missing email') const email = req.body.email.toLowerCase().trim() const user = await db.users.get(email) if (user && !user.confirmed && user.confirmKey.toUpperCase() === req.body.confirmKey.toUpperCase().trim()) { user.confirmed = true db.users.put(email, user) res.status(200).send({ token: createToken(user) }) } else { res.status(400).send({ error: 'Something went wrong :(' }) } }) app.post('/login', async (req, res) => { if (!req.body.password) throw new Error('Missing password') if (!req.body.email) throw new Error('Missing email') const email = req.body.email.toLowerCase().trim() const user = await db.users.get(email) if (user) { const password = hashPassword({ password: req.body.password, seed: user.seed, email }) if (password === user.password) { log({ type: 'login', user}) res.status(200).send({ token: createToken(user) }) return } } res.status(400).send({ error: 'Login failed' }) }) app.post('/renew', authorize(), async (req, res) => { log({ type: 'renew', user: req.identity }) const identity = {...req.identity} delete identity.exp delete identity.iat res.status(200).send({ token: createToken(identity) }) }) app.post('/feeds', authorize(), async (req, res) => { if (!req.body.url) throw new Error('Missing url') const doc = await getRss(req.body.url) let title try { title = doc.rss.channel[0].title[0] } catch (err) {} if (!title) throw new Error('RSS has no channel or title.') const userFeeds = (await db.userFeeds.get(req.identity.email)) || [] const feed = { id: uuid(), url: req.body.url, email: req.identity.email, title, confirmed: false, confirmKey: genKey({format: '[###-###-###-###]' }), created: Date.now() } userFeeds.push(feed.id) await db.userFeeds.put(req.identity.email, userFeeds) await db.feeds.put(feed.id, feed) res.status('200').send({ id: feed.id }) }) app.get('/feeds/:id', authorize(), async (req, res) => { const feed = await db.feeds.get(req.params.id) if (!feed) return res.status(404).send('Feed not found') if (feed.email !== req.identity.email) return res.status(403).send('This feed does not belong to you.') res.status(200).send(feed) }) app.patch('/feeds/:id', authorize(), async (req, res) => { const feed = await db.feeds.get(req.params.id) if (!feed) return res.status(404).send('Feed not found') if (feed.email !== req.identity.email) return res.status(403).send('This feed does not belong to you.') const allowedKeys = new Set([ 'title' ]) Object.entries(req.body).forEach(([key, value]) => { if (allowedKeys.has(key)) feed[key] = value }) await db.feeds.put(feed.id, feed) res.status(200).send(feed) }) app.start()