user.js 6.8 KB

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