user.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. const bcrypt = require('bcryptjs');
  2. const nanoid = require('nanoid');
  3. const driver = require('./neo4j');
  4. exports.getUser = ({ email = '', apikey = '' }) =>
  5. new Promise((resolve, reject) => {
  6. const session = driver.session();
  7. session
  8. .readTransaction(tx =>
  9. tx.run(
  10. 'MATCH (u:USER) WHERE u.email = $email OR u.apikey = $apikey ' +
  11. 'OPTIONAL MATCH (u)-[r:RECEIVED]->(c) WITH u, collect(c.date) as cooldowns ' +
  12. 'OPTIONAL MATCH (u)-[:OWNS]->(d) RETURN u, d, cooldowns',
  13. {
  14. apikey,
  15. email,
  16. }
  17. )
  18. )
  19. .then(res => {
  20. session.close();
  21. const user = res.records.length && res.records[0].get('u').properties;
  22. const cooldowns = res.records.length && res.records[0].get('cooldowns');
  23. const domainProps = res.records.length && res.records[0].get('d');
  24. const domain = domainProps ? domainProps.properties.name : '';
  25. const homepage = domainProps ? domainProps.properties.homepage : '';
  26. const useHttps = domainProps ? domainProps.properties.useHttps : '';
  27. return resolve(user && { ...user, cooldowns, domain, homepage, useHttps });
  28. })
  29. .catch(err => reject(err));
  30. });
  31. exports.createUser = ({ email, password }) =>
  32. new Promise(async (resolve, reject) => {
  33. const session = driver.session();
  34. const salt = await bcrypt.genSalt(12);
  35. const hash = await bcrypt.hash(password, salt);
  36. const verificationToken = nanoid(40);
  37. session
  38. .writeTransaction(tx =>
  39. tx.run(
  40. 'MERGE (u:USER { email: $email }) ' +
  41. 'SET u.password = $hash , u.verified = $verified , ' +
  42. 'u.verificationToken = $verificationToken , u.createdAt = $createdAt ' +
  43. 'RETURN u',
  44. {
  45. email,
  46. hash,
  47. createdAt: new Date().toJSON(),
  48. verified: false,
  49. verificationToken,
  50. }
  51. )
  52. )
  53. .then(res => {
  54. session.close();
  55. const user = res.records[0].get('u').properties;
  56. return resolve(user);
  57. })
  58. .catch(err => reject(err));
  59. });
  60. exports.verifyUser = ({ verificationToken }) =>
  61. new Promise((resolve, reject) => {
  62. const session = driver.session();
  63. session
  64. .writeTransaction(tx =>
  65. tx.run(
  66. 'MATCH (u:USER { verificationToken: $verificationToken })' +
  67. 'SET u.verified = true SET u.verificationToken = NULL RETURN u',
  68. {
  69. verificationToken,
  70. }
  71. )
  72. )
  73. .then(({ records }) => {
  74. session.close();
  75. const user = records.length && records[0].get('u').properties;
  76. return resolve(user);
  77. })
  78. .catch(err => reject(err));
  79. });
  80. exports.changePassword = ({ email, password }) =>
  81. new Promise(async (resolve, reject) => {
  82. const session = driver.session();
  83. const salt = await bcrypt.genSalt(12);
  84. const hash = await bcrypt.hash(password, salt);
  85. session
  86. .writeTransaction(tx =>
  87. tx.run('MATCH (u:USER { email: $email }) SET u.password = $password RETURN u', {
  88. email,
  89. password: hash,
  90. })
  91. )
  92. .then(res => {
  93. session.close();
  94. const user = res.records.length && res.records[0].get('u').properties;
  95. return resolve(user);
  96. })
  97. .catch(err => session.close() || reject(err));
  98. });
  99. exports.generateApiKey = ({ email }) =>
  100. new Promise(async (resolve, reject) => {
  101. const session = driver.session();
  102. const apikey = nanoid(40);
  103. session
  104. .writeTransaction(tx =>
  105. tx.run('MATCH (u:USER { email: $email }) SET u.apikey = $apikey RETURN u', {
  106. email,
  107. apikey,
  108. })
  109. )
  110. .then(res => {
  111. session.close();
  112. const newApikey = res.records.length && res.records[0].get('u').properties.apikey;
  113. return resolve({ apikey: newApikey });
  114. })
  115. .catch(err => session.close() || reject(err));
  116. });
  117. exports.requestPasswordReset = ({ email }) =>
  118. new Promise(async (resolve, reject) => {
  119. const session = driver.session();
  120. const resetPasswordExprie = Date.now() + 3600000;
  121. const resetPasswordToken = nanoid(40);
  122. session
  123. .writeTransaction(tx =>
  124. tx.run(
  125. 'MATCH (u:USER { email: $email }) ' +
  126. 'SET u.resetPasswordToken = $resetPasswordToken ' +
  127. 'SET u.resetPasswordExprie = $resetPasswordExprie ' +
  128. 'RETURN u',
  129. {
  130. email,
  131. resetPasswordExprie,
  132. resetPasswordToken,
  133. }
  134. )
  135. )
  136. .then(res => {
  137. session.close();
  138. const user = res.records.length && res.records[0].get('u').properties;
  139. return resolve(user);
  140. })
  141. .catch(err => session.close() || reject(err));
  142. });
  143. exports.resetPassword = ({ resetPasswordToken }) =>
  144. new Promise((resolve, reject) => {
  145. const session = driver.session();
  146. session
  147. .writeTransaction(tx =>
  148. tx.run(
  149. 'MATCH (u:USER { resetPasswordToken: $resetPasswordToken })' +
  150. 'SET u.resetPasswordExprie = NULL SET u.resetPasswordToken = NULL RETURN u',
  151. {
  152. resetPasswordToken,
  153. }
  154. )
  155. )
  156. .then(({ records }) => {
  157. session.close();
  158. const user = records.length && records[0].get('u').properties;
  159. return resolve(user);
  160. })
  161. .catch(err => reject(err));
  162. });
  163. exports.addCooldown = ({ email }) =>
  164. new Promise((resolve, reject) => {
  165. const session = driver.session();
  166. session
  167. .writeTransaction(tx =>
  168. tx.run(
  169. 'MATCH (u:USER { email: $email }) ' +
  170. 'MERGE (u)-[r:RECEIVED]->(c:COOLDOWN { date: $date }) ' +
  171. 'RETURN COUNT(r) as count',
  172. {
  173. date: new Date().toJSON(),
  174. email,
  175. }
  176. )
  177. )
  178. .then(({ records }) => {
  179. session.close();
  180. const count = records.length && records[0].get('count').toNumber();
  181. return resolve({ count });
  182. })
  183. .catch(err => reject(err));
  184. });
  185. exports.getCooldowns = ({ email }) =>
  186. new Promise((resolve, reject) => {
  187. const session = driver.session();
  188. session
  189. .writeTransaction(tx =>
  190. tx.run(
  191. 'MATCH (u:USER { email: $email }) MATCH (u)-[r:RECEIVED]->(c) RETURN c.date as date',
  192. {
  193. date: new Date().toJSON(),
  194. email,
  195. }
  196. )
  197. )
  198. .then(({ records = [] }) => {
  199. session.close();
  200. const cooldowns = records.map(record => record.get('date'));
  201. return resolve({ cooldowns });
  202. })
  203. .catch(err => reject(err));
  204. });
  205. exports.banUser = ({ email }) =>
  206. new Promise((resolve, reject) => {
  207. const session = driver.session();
  208. session
  209. .writeTransaction(tx =>
  210. tx.run('MATCH (u:USER { email: $email }) SET u.banned = true RETURN u', {
  211. email,
  212. })
  213. )
  214. .then(({ records = [] }) => {
  215. session.close();
  216. const user = records.length && records[0].get('u');
  217. return resolve({ user });
  218. })
  219. .catch(err => reject(err));
  220. });