user.js 6.7 KB

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