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.

212 lines
5.7 KiB

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