server.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. const app = require('./app')
  2. const db = require('./db')
  3. const log = require('./log')
  4. const { hashPassword, genSeed, genKey, authorize, createToken } = require('./security')
  5. const { sendmail } = require('./mail')
  6. const uuid = require('uuid/v4')
  7. const { getRss } = require('./rss')
  8. app.post('/signup', async (req, res) => {
  9. if (!req.body.name) throw new Error('Missing name')
  10. if (!req.body.password) throw new Error('Missing password')
  11. if (!req.body.email) throw new Error('Missing email')
  12. const email = req.body.email.toLowerCase().trim()
  13. const existing = await db.users.get(email)
  14. if (existing && existing.confirmed) throw new Error('User already exists.')
  15. const seed = genSeed()
  16. const password = hashPassword({password: req.body.password, email, seed})
  17. const confirmKey = genKey()
  18. const user = {
  19. name: req.body.name,
  20. email: req.body.email,
  21. password,
  22. seed,
  23. ip: req.ip,
  24. confirmed: false,
  25. confirmKey,
  26. keyCreated: Date.now(),
  27. failCount: 0,
  28. created: Date.now()
  29. }
  30. const mailResult = await sendmail({
  31. to: `${user.name} <${user.email}>`,
  32. from: `RSS Unlimited <noreply@rssunlimited.com>`,
  33. subject: `Please verify your email address.`,
  34. text: `Enter the following code to confirm your email address on RSSUnlimited.com:\n\n${confirmKey}`
  35. })
  36. await db.users.put(email, user)
  37. log({
  38. type: 'user-created',
  39. user
  40. })
  41. res.status(200).send({})
  42. })
  43. app.post('/confirm', async (req, res) => {
  44. if (!req.body.confirmKey) throw new Error('Missing confirmKey')
  45. if (!req.body.email) throw new Error('Missing email')
  46. const email = req.body.email.toLowerCase().trim()
  47. const user = await db.users.get(email)
  48. if (user && !user.confirmed && user.confirmKey.toUpperCase() === req.body.confirmKey.toUpperCase().trim()) {
  49. user.confirmed = true
  50. db.users.put(email, user)
  51. res.status(200).send({
  52. token: createToken(user)
  53. })
  54. } else {
  55. res.status(400).send({
  56. error: 'Something went wrong :('
  57. })
  58. }
  59. })
  60. app.post('/login', async (req, res) => {
  61. if (!req.body.password) throw new Error('Missing password')
  62. if (!req.body.email) throw new Error('Missing email')
  63. const email = req.body.email.toLowerCase().trim()
  64. const user = await db.users.get(email)
  65. if (user) {
  66. const password = hashPassword({
  67. password: req.body.password,
  68. seed: user.seed,
  69. email
  70. })
  71. if (password === user.password) {
  72. log({ type: 'login', user})
  73. res.status(200).send({
  74. token: createToken(user)
  75. })
  76. return
  77. }
  78. }
  79. res.status(400).send({
  80. error: 'Login failed'
  81. })
  82. })
  83. app.post('/renew', authorize(), async (req, res) => {
  84. log({
  85. type: 'renew',
  86. user: req.identity
  87. })
  88. const identity = {...req.identity}
  89. delete identity.exp
  90. delete identity.iat
  91. res.status(200).send({
  92. token: createToken(identity)
  93. })
  94. })
  95. app.post('/feeds', authorize(), async (req, res) => {
  96. if (!req.body.url) throw new Error('Missing url')
  97. const doc = await getRss(req.body.url)
  98. let title
  99. try {
  100. title = doc.rss.channel[0].title[0]
  101. } catch (err) {}
  102. if (!title) throw new Error('RSS has no channel or title.')
  103. const userFeeds = (await db.userFeeds.get(req.identity.email)) || []
  104. const feed = {
  105. id: uuid(),
  106. url: req.body.url,
  107. email: req.identity.email,
  108. title,
  109. confirmed: false,
  110. confirmKey: genKey({format: '[###-###-###-###]' }),
  111. created: Date.now()
  112. }
  113. userFeeds.push(feed.id)
  114. await db.userFeeds.put(req.identity.email, userFeeds)
  115. await db.feeds.put(feed.id, feed)
  116. res.status('200').send({
  117. id: feed.id
  118. })
  119. })
  120. app.get('/feeds/:id', authorize(), async (req, res) => {
  121. const feed = await db.feeds.get(req.params.id)
  122. if (!feed) return res.status(404).send('Feed not found')
  123. if (feed.email !== req.identity.email) return res.status(403).send('This feed does not belong to you.')
  124. res.status(200).send(feed)
  125. })
  126. app.patch('/feeds/:id', authorize(), async (req, res) => {
  127. const feed = await db.feeds.get(req.params.id)
  128. if (!feed) return res.status(404).send('Feed not found')
  129. if (feed.email !== req.identity.email) return res.status(403).send('This feed does not belong to you.')
  130. const allowedKeys = new Set([
  131. 'title'
  132. ])
  133. Object.entries(req.body).forEach(([key, value]) => {
  134. if (allowedKeys.has(key)) feed[key] = value
  135. })
  136. await db.feeds.put(feed.id, feed)
  137. res.status(200).send(feed)
  138. })
  139. app.start()