Advertisement
Guest User

Untitled

a guest
Jun 18th, 2019
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.88 KB | None | 0 0
  1. 'use strict';
  2.  
  3. var collections = require('../helpers/backend').collections;
  4. var simpleApi = require('./simple-api/simple-api');
  5. var crypto = require('crypto');
  6. var vo = require('vo');
  7. var q = require('q');
  8.  
  9. const utils = require('../helpers/utils');
  10. var getOptions = require('../helpers/backend').getOptions;
  11. const errorResponse = require('../helpers/response-handler').responseBadRequest;
  12.  
  13. const generateCorrelationId = require('uuid/v1');
  14. const _ = require('lodash');
  15.  
  16. const ERROR_CODE_ACCEPT_EULA_REQUIRED = 1036;
  17. const ERROR_CODE_DUPLICATE_EMAIL_ADDRESS = 1000;
  18. const ERROR_CODE_SIMPLE_API_ERROR = 1097;
  19. const ERROR_CODE_REGISTRATION_NOT_CONFIRMED = 1024;
  20.  
  21. var loggedInSimpleUsers = {};
  22. var LOGGER = require('../../config/logger').logger;
  23.  
  24. module.exports = {
  25. register: register,
  26. validateUserCredentials: validateUserCredentials,
  27. getSimpleToken: getSimpleToken,
  28. saveUserObject: saveUserObject //for testing
  29. };
  30.  
  31. function validateUserCredentials(req, serverRes) {
  32.  
  33. LOGGER.info('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
  34. LOGGER.info('validateUserCredentials START');
  35. LOGGER.info('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
  36.  
  37. var credentials = req.swagger.params.credentials.value;
  38. var correlationId = req.headers['x-correlation-id'] ? req.headers['x-correlation-id'] : generateCorrelationId();
  39. let provider = credentials.provider;
  40. vo(function* () {
  41. try {
  42. let loginResult;
  43. if (provider === 'simple') {
  44. loginResult = yield performSimpleLogin(credentials, correlationId);
  45. } else {
  46. loginResult = yield performSocialLogin(credentials, correlationId);
  47. }
  48.  
  49. serverRes.header('content-type', 'application/json');
  50. return serverRes.send(loginResult.code, loginResult.body);
  51.  
  52. } catch (err) {
  53. LOGGER.error('Error: ', err);
  54. return errorResponse(serverRes, err);
  55. }
  56. })();
  57. }
  58.  
  59. function* performSimpleLogin(credentials, correlationId) {
  60.  
  61. LOGGER.info('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
  62. LOGGER.info('performSimpleLogin START', credentials);
  63. LOGGER.info('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
  64.  
  65. let email = credentials.email;
  66. let password = credentials.password;
  67. let acceptChecks = credentials.acceptChecks;
  68. if (acceptChecks && acceptChecks.length === 0) {
  69. acceptChecks = null;
  70. }
  71. if (!email || !password) {
  72. return {
  73. code: 403,
  74. body: {
  75. message: "TXT_INVALID_CREDENTIALS_ERROR"
  76. }
  77. };
  78. }
  79. var simpleLoginResult = yield authenticateSimpleUser(email, password, acceptChecks, correlationId);
  80.  
  81. LOGGER.info('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
  82. LOGGER.info('simpleLoginResult', simpleLoginResult);
  83. LOGGER.info('simple token', getSimpleToken());
  84. LOGGER.info('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
  85.  
  86. if (simpleLoginResult.success) {
  87. return {
  88. code: 200,
  89. body: {
  90. _id: simpleLoginResult.localUserId
  91. }
  92. };
  93. } else if (simpleLoginResult.message && simpleLoginResult.message.includes(ERROR_CODE_SIMPLE_API_ERROR)) {
  94. return {
  95. code: 400,
  96. body: {
  97. message: 'TXT_ERROR_CODE_SIMPLE_API_ERROR'
  98. }
  99. };
  100. } else if (simpleLoginResult.message && simpleLoginResult.message.includes(ERROR_CODE_REGISTRATION_NOT_CONFIRMED)) {
  101. return {
  102. code: 400,
  103. body: {
  104. message: 'TXT_ERROR_CODE_REGISTRATION_NOT_CONFIRMED'
  105. }
  106. };
  107. } else if (simpleLoginResult.gdprNeeded) {
  108. return {
  109. code: 400,
  110. body: {
  111. message: 'TXT_ERROR_ACCEPT_EULA_REQUIRED'
  112. }
  113. };
  114. } else { //TODO remove local user after full migration to simple
  115. var localLoginResult = yield authenticateLocalUser(email, password, correlationId);
  116. if (localLoginResult.success) {
  117. return {
  118. code: localLoginResult.code,
  119. body: {
  120. _id: localLoginResult._id
  121. }
  122. };
  123. } else {
  124. return {
  125. code: localLoginResult.code,
  126. body: {
  127. message: localLoginResult.message
  128. }
  129. };
  130. }
  131. }
  132. }
  133.  
  134. function* performSocialLogin(credentials, correlationId) {
  135. let email = credentials.email;
  136. let provider = credentials.provider;
  137. let socialToken = credentials.authToken;
  138. let acceptChecks = credentials.acceptChecks;
  139. if (acceptChecks && acceptChecks.length === 0) {
  140. acceptChecks = null;
  141. }
  142. LOGGER.info('Credentials: ' + JSON.stringify(credentials));
  143. let registerResult = yield simpleApi.socialRegister(email, socialToken, provider, acceptChecks, correlationId);
  144. LOGGER.info('Got register result: ' + JSON.stringify(registerResult));
  145. if (registerResult.errorCodes && registerResult.errorCodes.includes(ERROR_CODE_ACCEPT_EULA_REQUIRED)) {
  146. return {
  147. code: 400,
  148. body: {
  149. message: 'TXT_ERROR_SOCIAL_ACCEPT_EULA_REQUIRED'
  150. }
  151. };
  152. } else if (registerResult.errorCodes && !registerResult.errorCodes.includes(ERROR_CODE_DUPLICATE_EMAIL_ADDRESS)) {
  153. LOGGER.error(`Error while registering social user ${email}, error code is ${JSON.stringify(registerResult.errorCodes)}`);
  154. return {
  155. code: 400,
  156. body: {
  157. message: 'TXT_ERROR_SOCIAL_REGISTER_FAILED'
  158. }
  159. };
  160. //error
  161. } else {
  162. let loginResult = yield simpleApi.socialLogin(email, socialToken, provider, acceptChecks, correlationId);
  163. LOGGER.info('social: ' + JSON.stringify(loginResult));
  164. if (loginResult.success) {
  165. const localUserId = yield ensureLocalUser(email, loginResult.userdata, correlationId);
  166. saveSimpleTokenForUser(localUserId, loginResult.token, correlationId);
  167.  
  168. return {
  169. code: 200,
  170. body: {
  171. _id: localUserId
  172. }
  173. };
  174. } else {
  175. return {
  176. code: 400,
  177. message: JSON.stringify(loginResult.errorCodes)
  178. };
  179. }
  180. }
  181. }
  182.  
  183. function* authenticateSimpleUser(username, password, acceptChecks, correlationId) {
  184. var userData = yield simpleApi.login(username, password, acceptChecks, correlationId);
  185. if (!userData.success) {
  186. if (userData.errorCodes && userData.errorCodes.includes(ERROR_CODE_ACCEPT_EULA_REQUIRED)) {
  187. return {
  188. success: false,
  189. gdprNeeded: true,
  190. message: 'TXT_ERROR_ACCEPT_EULA_REQUIRED'
  191. };
  192. } else {
  193. return {
  194. success: false,
  195. message: JSON.stringify(userData.errorCodes)
  196. };
  197. }
  198. } else {
  199. let localUserId = yield ensureLocalUser(username, userData.userdata, correlationId);
  200. saveSimpleTokenForUser(localUserId, userData.token, correlationId);
  201.  
  202. return {
  203. success: true,
  204. localUserId: localUserId
  205. };
  206. }
  207. }
  208.  
  209. function* ensureLocalUser(username, userData, correlationId) {
  210. let localUserId;
  211. const simpleUserId = userData.userId.toString();
  212. let localUser = yield getLocalUserByUsername(username, correlationId);
  213. if (!localUser) {
  214. let newUser = {
  215. username: username,
  216. name: userData.commonName,
  217. email: userData.email,
  218. simpleId: simpleUserId,
  219. password: ''
  220. };
  221. localUserId = yield saveUserObject(newUser);
  222. } else {
  223. if (!localUser.simpleId) {
  224. yield saveSimpleIdForUser(localUser._id, simpleUserId, correlationId);
  225. }
  226.  
  227. localUserId = localUser._id;
  228. }
  229. return localUserId;
  230. }
  231.  
  232. function getLocalUserByUsername(username, correlationId) {
  233. var deferred = q.defer();
  234. var query = {
  235. username: username
  236. };
  237. var qs = "?query=" + JSON.stringify(query);
  238. const path = '/api/v1/User/' + qs;
  239. const option = getOptions(path, correlationId);
  240. collections.users.get(option, function (err, req, res, users) {
  241. if (err) {
  242. LOGGER.error('err: ' + err);
  243. return deferred.reject(err);
  244. }
  245. if (users.length == 0) return deferred.resolve(null);
  246. var user = users[0];
  247. deferred.resolve(user);
  248. });
  249. return deferred.promise;
  250. }
  251.  
  252. function getSimpleToken(userId) {
  253. const user = utils.getUserPropertiesById(userId);
  254. LOGGER.info(JSON.stringify(user));
  255.  
  256. return loggedInSimpleUsers[userId];
  257. }
  258.  
  259. function* authenticateLocalUser(username, password, correlationId) {
  260. var user = yield getLocalUserByUsername(username, correlationId);
  261. if (!user) return {
  262. code: 403,
  263. success: false,
  264. message: "TXT_INVALID_CREDENTIALS_ERROR"
  265. };
  266. if (user.password !== hashPassword(password, user.salt)) return {
  267. code: 403,
  268. success: false,
  269. message: "TXT_INVALID_CREDENTIALS_ERROR"
  270. };
  271. return {
  272. code: 200,
  273. success: true,
  274. _id: user._id
  275. };
  276. }
  277.  
  278. function register(req, serverRes) {
  279. serverRes.header('content-type', 'application/json');
  280. var newUser = req.swagger.params.user.value;
  281. const correlationId = _.get(req.headers, 'x-correlation-id');
  282. vo(function* () {
  283. try {
  284. let registerResult = yield simpleApi.register(newUser.email, newUser.password, newUser.acceptChecks, correlationId);
  285. if (registerResult.success) {
  286. var userId = yield saveUserObject(newUser);
  287. return serverRes.send(200, {
  288. _id: userId
  289. });
  290. } else if (registerResult.errorCodes && registerResult.errorCodes.includes(ERROR_CODE_DUPLICATE_EMAIL_ADDRESS)) {
  291. LOGGER.error('Failed register result: ' + JSON.stringify(registerResult));
  292. return errorResponse(serverRes, 'TXT_DUPLICATE_EMAIL_ADDRESS');
  293. }else if (registerResult.errorCodes && registerResult.errorCodes.includes(ERROR_CODE_SIMPLE_API_ERROR)) {
  294. LOGGER.error('Failed register result: ' + JSON.stringify(registerResult));
  295. return errorResponse(serverRes, 'TXT_ERROR_CODE_SIMPLE_API_ERROR');
  296. } else {
  297. LOGGER.error('Failed register result: ' + JSON.stringify(registerResult));
  298. return errorResponse(serverRes, 'TXT_ERROR_REGISTER_FAILED');
  299. }
  300. } catch (err) {
  301. LOGGER.error('err: ' + err);
  302. return errorResponse(serverRes, 'TXT_ERROR_REGISTER_FAILED');
  303. }
  304. })();
  305. }
  306.  
  307. function saveUserObject(newUser) {
  308. var deferred = q.defer();
  309. newUser.salt = generateSalt();
  310. newUser.password = hashPassword(newUser.password, newUser.salt);
  311. if (newUser.username) {
  312. newUser.username.toLowerCase().trim();
  313. }
  314. if (newUser.email) {
  315. newUser.email = newUser.email.toLowerCase().trim();
  316. }
  317. //TODO get auth token/user id from headers
  318. collections.users.post('/api/v1/User/', newUser, function (err, req, res, body) {
  319. if (err) {
  320. LOGGER.error('err: ' + err);
  321. return deferred.reject(err);
  322. }
  323. return deferred.resolve(body._id);
  324. });
  325. return deferred.promise;
  326. }
  327.  
  328. function saveSimpleIdForUser(localUserId, simpleUserId, correlationId) {
  329. const deferred = q.defer();
  330. const path = `/api/v1/User/${localUserId}`;
  331. const options = getOptions(path, correlationId);
  332. const body = { simpleId: simpleUserId };
  333.  
  334. collections.users.put(options, body, (err, req, res, user) => {
  335. if (err) {
  336. LOGGER.error(`Error while updating user with Simple user id. Local user id: ${localUserId}, Simple user id: ${simpleUserId}. Error: ${err}.`);
  337.  
  338. return deferred.reject(err);
  339. }
  340.  
  341. return deferred.resolve(user);
  342. });
  343.  
  344. return deferred.promise;
  345. }
  346.  
  347. function saveSimpleTokenForUser(localUserId, simpleToken, correlationId) {
  348. const deferred = q.defer();
  349. const path = `/api/v1/User/${localUserId}`;
  350. const options = getOptions(path, correlationId);
  351. const body = { simpleId: simpleToken };
  352.  
  353. collections.users.put(options, body, (err, req, res, user) => {
  354. if (err) {
  355. LOGGER.error(`Error while updating user with Simple user token. Local user token: ${localUserId}, Simple user id: ${simpleToken}. Error: ${err}.`);
  356.  
  357. return deferred.reject(err);
  358. }
  359.  
  360. return deferred.resolve(user);
  361. });
  362.  
  363. return deferred.promise;
  364. }
  365.  
  366. function generateSalt() {
  367. return crypto.randomBytes(16).toString('base64');
  368. }
  369.  
  370. function hashPassword(password, salt) {
  371. return crypto.pbkdf2Sync(new Buffer(password, 'base64'), new Buffer(salt, 'base64'), 10000, 64, 'sha1').toString('base64');
  372. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement