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.

224 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. console.log(users);
  97. configManager.getConfiguration().users = users;
  98. configManager.syncToDisk();
  99. },
  100. getAPIKEY: function(username)
  101. {
  102. var index = getIndexOfUser(username);
  103. if(index !== -1)
  104. return users[index].api;
  105. return 0;
  106. },
  107. /**
  108. * Checks to see if there was a valid login attempt
  109. *
  110. * @param username
  111. * @param password
  112. * @returns {boolean}
  113. */
  114. checkLogin: function(username, password)
  115. {
  116. const userIndex = getIndexOfUser(username);
  117. if(userIndex === -1)
  118. return false;
  119. const hashedPassword = hashPassword(password, users[userIndex].salt);
  120. return users[userIndex].password == hashedPassword;
  121. },
  122. /**
  123. * Adds a user to the configuration
  124. *
  125. * @param username
  126. * @param password
  127. * @returns {boolean}
  128. */
  129. addUser: function(username, password, admin)
  130. {
  131. const userIndex = getIndexOfUser(username);
  132. if(userIndex !== -1)
  133. return false; // user already exists
  134. var newUser = new Object();
  135. newUser.username = username;
  136. newUser.api = generateRandomAPIKey();
  137. if(users.length === 0)
  138. newUser.id = 1;
  139. else
  140. newUser.id = users[users.length -1].id + 1;
  141. const passObject = createHashedPasswordObject(password);
  142. newUser.salt = passObject.salt;
  143. newUser.password = passObject.pass;
  144. newUser.admin = admin;
  145. users.push(newUser);
  146. configManager.getConfiguration().users = users;
  147. configManager.syncToDisk();
  148. return true;
  149. },
  150. /**
  151. * Edits a user based on their id
  152. *
  153. * @param id
  154. * @param userName
  155. * @param password
  156. */
  157. editUser: function(id, userName, password, admin)
  158. {
  159. for(var i = 0; i < users.length; i++)
  160. {
  161. if (users[i].id + "" === id)
  162. {
  163. console.log("User account updated.");
  164. users[i].username = userName;
  165. users[i].admin = admin;
  166. var passObj = createHashedPasswordObject(password);
  167. users[i].salt = passObj.salt;
  168. users[i].password = passObj.pass;
  169. }
  170. }
  171. configManager.getConfiguration().users = users;
  172. configManager.syncToDisk();
  173. },
  174. /**
  175. * Removes a user account from the configuration
  176. * @param id
  177. */
  178. removeUser: function(id)
  179. {
  180. users = users.filter(function(value, index, arr)
  181. {
  182. return value.id + "" !== id
  183. });
  184. configManager.getConfiguration().users = users;
  185. configManager.syncToDisk();
  186. }
  187. };