Lightweight node app to use in place of plex to self host your video and movie collections. Running on just under 50MB of ram this is ideal for people looking to host videos on minimal hardware.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
5.5 KiB

  1. /** Crypto package used for hashing */
  2. const crypto = require('crypto');
  3. const configManager = require("./configManager");
  4. var users = configManager.getConfiguration().users;
  5. /**
  6. * Helper function to generate a hashed password
  7. * from a given plain text password.
  8. *
  9. * This uses 64 bits of entropy as the random salt
  10. * and uses sha256 hashing method to hash the password
  11. * combined with the salt.
  12. *
  13. * @param password
  14. * @returns {Object pass: hashedPassword, salt: salt used to hash}
  15. */
  16. const createHashedPasswordObject = function(password)
  17. {
  18. const randBuff = crypto.randomBytes(64);
  19. const salt = crypto.createHash('sha256').update(randBuff).digest('hex');
  20. const hashPass = hashPassword(password, salt);
  21. var hashPassObject = new Object();
  22. hashPassObject.pass = hashPass;
  23. hashPassObject.salt = salt;
  24. return hashPassObject;
  25. };
  26. const generateRandomAPIKey = function()
  27. {
  28. const randBuff = crypto.randomBytes(64);
  29. return crypto.createHash('sha256').update(randBuff).digest('hex');
  30. };
  31. /**
  32. * Hashes a pasword with a aprticular salt
  33. * using the crypto library
  34. *
  35. * @param password
  36. * @param salt
  37. */
  38. const hashPassword = function(password, salt)
  39. {
  40. return crypto.createHash('sha256')
  41. .update(password + salt)
  42. .digest('hex');
  43. };
  44. /**
  45. * Fetches the index of the user in the configuration. If the
  46. * user does not exists a -1 is returned.
  47. */
  48. const getIndexOfUser = function(username)
  49. {
  50. for(var i = 0; i < users.length; i++)
  51. {
  52. if (username === users[i].username)
  53. {
  54. if(username === users[i].username)
  55. {
  56. return i;
  57. }
  58. }
  59. }
  60. return -1;
  61. };
  62. module.exports =
  63. {
  64. isValidAPI: function(apiKey)
  65. {
  66. for(var i = 0; i < users.length; i++)
  67. {
  68. if(users[i].api === apiKey)
  69. {
  70. return true;
  71. }
  72. }
  73. return false;
  74. },
  75. isAdmin: function(username)
  76. {
  77. var index = getIndexOfUser(username);
  78. if(index !== -1)
  79. {
  80. return users[index].admin;
  81. }
  82. return false;
  83. },
  84. getID: function(username)
  85. {
  86. var index = getIndexOfUser(username);
  87. return users[index].id;
  88. },
  89. revokeAPI: function(username)
  90. {
  91. var index = getIndexOfUser(username);
  92. if(index !== -1)
  93. {
  94. users[index].api = generateRandomAPIKey();
  95. }
  96. configManager.getConfiguration().users = users;
  97. configManager.syncToDisk();
  98. },
  99. getAPIKEY: function(username)
  100. {
  101. var index = getIndexOfUser(username);
  102. if(index !== -1)
  103. return users[index].api;
  104. return 0;
  105. },
  106. /**
  107. * Checks to see if there was a valid login attempt
  108. *
  109. * @param username
  110. * @param password
  111. * @returns {boolean}
  112. */
  113. checkLogin: function(username, password)
  114. {
  115. const userIndex = getIndexOfUser(username);
  116. if(userIndex === -1)
  117. return false;
  118. const hashedPassword = hashPassword(password, users[userIndex].salt);
  119. return users[userIndex].password == hashedPassword;
  120. },
  121. /**
  122. * Adds a user to the configuration
  123. *
  124. * @param username
  125. * @param password
  126. * @returns {boolean}
  127. */
  128. addUser: function(username, password, admin)
  129. {
  130. const userIndex = getIndexOfUser(username);
  131. if(userIndex !== -1)
  132. return false; // user already exists
  133. var newUser = new Object();
  134. newUser.username = username;
  135. newUser.api = generateRandomAPIKey();
  136. if(users.length === 0)
  137. newUser.id = 1;
  138. else
  139. newUser.id = users[users.length -1].id + 1;
  140. const passObject = createHashedPasswordObject(password);
  141. newUser.salt = passObject.salt;
  142. newUser.password = passObject.pass;
  143. newUser.admin = admin;
  144. users.push(newUser);
  145. configManager.getConfiguration().users = users;
  146. configManager.syncToDisk();
  147. return true;
  148. },
  149. /**
  150. * Edits a user based on their id
  151. *
  152. * @param id
  153. * @param userName
  154. * @param password
  155. */
  156. editUser: function(id, userName, password, admin)
  157. {
  158. for(var i = 0; i < users.length; i++)
  159. {
  160. if (users[i].id + "" === id)
  161. {
  162. console.log("User account updated.");
  163. users[i].username = userName;
  164. users[i].admin = admin;
  165. var passObj = createHashedPasswordObject(password);
  166. users[i].salt = passObj.salt;
  167. users[i].password = passObj.pass;
  168. }
  169. }
  170. configManager.getConfiguration().users = users;
  171. configManager.syncToDisk();
  172. },
  173. /**
  174. * Removes a user account from the configuration
  175. * @param id
  176. */
  177. removeUser: function(id)
  178. {
  179. users = users.filter(function(value, index, arr)
  180. {
  181. return value.id + "" !== id
  182. });
  183. configManager.getConfiguration().users = users;
  184. configManager.syncToDisk();
  185. }
  186. };