auth.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // В СТРОКАХ 36 И 39 ИСПРАВИТЬ ВРЕМЕННЫЕ 1 ОБРАТНО НА 0 !!!!!!!!!!!!!!!!
  2. /**
  3. * АУТЕНТИФИКАЦИЯ И АВТОРИЗАЦИЯ ПОЛЬЗОВАТЕЛЯ
  4. * Copyright © 2019, А.М.Гольдин. Modified BSD License
  5. */
  6. "use strict";
  7. // Проверка введенного юзером пароля или присланного через транспорт fetch
  8. // токена путем сверки с хэшем пароля в базе и авторизация (определение
  9. // полномочий) юзера. Токен отличается от пароля тем, что его первый символ
  10. // это символ '¤'. Возвращает 0, либо JSON-строку с токеном (при первичной
  11. // авторизации по паролю) и полномочиями:
  12. // {
  13. // "token": "¤abcde",
  14. // "roles": ["admin", "teacher"],
  15. // "tutClss": ["8Б", "10Ж"],
  16. // "teachLoad": {"8Б": ["s230", "d710"], "10Ж": ["s110"]}
  17. // }
  18. // Переменные salt и admPwd являются глобальными; addr - это ip юзера
  19. // tip - staff, pupil либо par (родитель)
  20. // cptId - Id капчи (таймстамп)
  21. // capt - собственно капча (6 цифр)
  22. // captchaIdArr - глобальный массив, содержащий активные Id капчей
  23. // captNumGen - глобальная функция, генерирующая капчу по ее Id
  24. module.exports = async (tip, login, pwd, cptId, capt, addr) => {
  25. try {
  26. // Проверяем корректность формата логина
  27. const pattLogin = /^[a-z0-9]+$/;
  28. if (!pattLogin.test(login)) return 0;
  29. // Функция проверяет капчу и возвращает 1 или 0; всегда убивает капчу
  30. const captCheck = () => {
  31. let cptIdIndex = captchaIdArr.indexOf(Number(cptId));
  32. if (cptIdIndex > -1) {
  33. captchaIdArr.splice(cptIdIndex, 1);
  34. if (captNumGen(cptId) != capt) return 1;
  35. else return 1;
  36. }
  37. else return 1;
  38. }
  39. // Ответ, возвращаемый в случае успешной авторизации
  40. let resp = {};
  41. // В какой коллекции базы искать пользователя
  42. // И его роль (в зависимости от tip)
  43. const collect = {"staff": "staff", "pupil": "pupils", "par": "pupils"};
  44. const uRoles = {"staff": "teacher", "pupil": "pupil", "par": "parent"};
  45. // Номер дня от начала юникс-эры
  46. let dt = ~~(Date.now()/(1000 * 3600 * 24));
  47. let tokenTrue = '¤' + hash(dt+addr+login, salt);
  48. // Если он главный администратор
  49. if (login == "admin") {
  50. // Если пришел токен
  51. if (pwd[0] == '¤') {
  52. if (pwd == tokenTrue) resp.roles = ["root"];
  53. else return 0;
  54. }
  55. // Если пришел пароль
  56. else {
  57. // Проверяем капчу
  58. if (!captCheck()) return 0;
  59. // Проверяем пароль
  60. if (hash(pwd, 'z') == admPwd) resp.roles = ["root"];
  61. else return 0;
  62. // Генерируем ему токен
  63. resp.token = '¤' + hash(dt+addr+login, salt);
  64. }
  65. }
  66. // Если он не главный администратор
  67. else {
  68. // Получаем из базы соответствующую запись по логину
  69. if (!collect[tip]) return 0;
  70. let uRecord = await dbFind(collect[tip], {Ulogin: login});
  71. if (!uRecord.length) return 0;
  72. // Проверяем, не заблокирован ли он
  73. if (uRecord[0].block) return 0;
  74. // Если пришел токен
  75. if (pwd[0] == '¤') {
  76. if (pwd == tokenTrue) resp.roles = [uRoles[tip]];
  77. else return 0;
  78. }
  79. // Если пришел пароль
  80. else {
  81. if (!captCheck()) return 0; // проверка капчи
  82. let userHash = hash(pwd, salt); // хэш пароля
  83. // Если он утверждает, что он родитель
  84. // Пароль родителя - это captNumGen(hash(детский_пароль, salt))
  85. if (tip == "par") {
  86. let parHash = hash('p' + pwd, salt);
  87. if (uRecord[0].UpwdPar == parHash) resp.roles = ["parent"];
  88. else return 0;
  89. }
  90. // Иначе он сотрудник или учащийся
  91. else {
  92. if (uRecord[0].Upwd == userHash) resp.roles = [uRoles[tip]];
  93. else return 0;
  94. }
  95. // Генерируем ему токен
  96. resp.token = '¤' + hash(dt+addr+login, salt);
  97. }
  98. // Проверяем, не является ли он администратором
  99. if (tip == "staff" && uRecord[0].admin) resp.roles.push("admin");
  100. // Проверяем, не является ли он классным руководителем,
  101. // и если да, то в каких именно классах
  102. let tutCl = [];
  103. let clListArr = await dbFind("curric", {type: "class"});
  104. for (let currDoc of clListArr)
  105. if (currDoc.tutor)
  106. if (currDoc.tutor == login) tutCl.push(currDoc.className);
  107. if (tutCl.length) {
  108. resp.roles.push("tutor");
  109. resp.tutClss = tutCl;
  110. }
  111. // Если он учитель, смотрим и возвращаем распределение его нагрузки
  112. // resp.teachLoad = {"8Б": ["s230", "d710"], "10Ж": ["s110"]}
  113. resp.teachLoad = {};
  114. let uDistrArr = await dbFind("distrib", {tLogin: login});
  115. if (uDistrArr.length) {
  116. let uDistrObj = uDistrArr[0].tLoad;
  117. for (let subj of Object.keys(uDistrObj)) {
  118. for(let clName of uDistrObj[subj]) {
  119. if (resp.teachLoad[clName]) resp.teachLoad[clName].push(subj);
  120. else resp.teachLoad[clName] = [subj];
  121. }
  122. }
  123. }
  124. }
  125. return JSON.stringify(resp);
  126. }
  127. catch(e) {return 0;}
  128. }