Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

2 anos atrás
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. const cookie = require("cookie");
  2. const request = require("superagent");
  3. const { get_conf, get_redis_subscriber } = require("./node_utils");
  4. const conf = get_conf();
  5. const log = console.log; // eslint-disable-line
  6. const subscriber = get_redis_subscriber();
  7. const io = require("socket.io")(conf.socketio_port, {
  8. cors: {
  9. // Should be fine since we are ensuring whether hostname and origin are same before adding setting listeners for s socket
  10. origin: true,
  11. credentials: true,
  12. },
  13. });
  14. io.use((socket, next) => {
  15. if (get_hostname(socket.request.headers.host) != get_hostname(socket.request.headers.origin)) {
  16. next(new Error("Invalid origin"));
  17. return;
  18. }
  19. if (!socket.request.headers.cookie) {
  20. next(new Error("No cookie transmitted."));
  21. return;
  22. }
  23. let cookies = cookie.parse(socket.request.headers.cookie);
  24. if (!cookies.sid) {
  25. next(new Error("No sid transmitted."));
  26. return;
  27. }
  28. request
  29. .get(get_url(socket, "/api/method/xhiveframework.realtime.get_user_info"))
  30. .type("form")
  31. .query({
  32. sid: cookies.sid,
  33. })
  34. .then((res) => {
  35. socket.user = res.body.message.user;
  36. socket.user_type = res.body.message.user_type;
  37. socket.sid = cookies.sid;
  38. next();
  39. })
  40. .catch((e) => {
  41. next(new Error(`Unauthorized: ${e}`));
  42. });
  43. });
  44. // on socket connection
  45. io.on("connection", function (socket) {
  46. socket.join(get_user_room(socket, socket.user));
  47. socket.join(get_website_room(socket));
  48. if (socket.user_type == "System User") {
  49. socket.join(get_site_room(socket));
  50. }
  51. socket.on("doctype_subscribe", function (doctype) {
  52. can_subscribe_doctype({
  53. socket,
  54. doctype,
  55. callback: () => {
  56. socket.join(get_doctype_room(socket, doctype));
  57. },
  58. });
  59. });
  60. socket.on("task_subscribe", function (task_id) {
  61. var room = get_task_room(socket, task_id);
  62. socket.join(room);
  63. });
  64. socket.on("task_unsubscribe", function (task_id) {
  65. var room = get_task_room(socket, task_id);
  66. socket.leave(room);
  67. });
  68. socket.on("progress_subscribe", function (task_id) {
  69. var room = get_task_room(socket, task_id);
  70. socket.join(room);
  71. });
  72. socket.on("doc_subscribe", function (doctype, docname) {
  73. can_subscribe_doc({
  74. socket,
  75. doctype,
  76. docname,
  77. callback: () => {
  78. var room = get_doc_room(socket, doctype, docname);
  79. socket.join(room);
  80. },
  81. });
  82. });
  83. socket.on("doc_unsubscribe", function (doctype, docname) {
  84. var room = get_doc_room(socket, doctype, docname);
  85. socket.leave(room);
  86. });
  87. socket.on("doc_open", function (doctype, docname) {
  88. can_subscribe_doc({
  89. socket,
  90. doctype,
  91. docname,
  92. callback: () => {
  93. var room = get_open_doc_room(socket, doctype, docname);
  94. socket.join(room);
  95. // show who is currently viewing the form
  96. send_users(
  97. {
  98. socket: socket,
  99. doctype: doctype,
  100. docname: docname,
  101. },
  102. "view"
  103. );
  104. // show who is currently typing on the form
  105. send_users(
  106. {
  107. socket: socket,
  108. doctype: doctype,
  109. docname: docname,
  110. },
  111. "type"
  112. );
  113. },
  114. });
  115. });
  116. socket.on("doc_close", function (doctype, docname) {
  117. // remove this user from the list of 'who is currently viewing the form'
  118. var room = get_open_doc_room(socket, doctype, docname);
  119. socket.leave(room);
  120. send_users(
  121. {
  122. socket: socket,
  123. doctype: doctype,
  124. docname: docname,
  125. },
  126. "view"
  127. );
  128. });
  129. socket.on("doc_typing", function (doctype, docname) {
  130. // show users that are currently typing on the form
  131. const room = get_typing_room(socket, doctype, docname);
  132. socket.join(room);
  133. send_users(
  134. {
  135. socket: socket,
  136. doctype: doctype,
  137. docname: docname,
  138. },
  139. "type"
  140. );
  141. });
  142. socket.on("doc_typing_stopped", function (doctype, docname) {
  143. // remove this user from the list of users currently typing on the form'
  144. const room = get_typing_room(socket, doctype, docname);
  145. socket.leave(room);
  146. send_users(
  147. {
  148. socket: socket,
  149. doctype: doctype,
  150. docname: docname,
  151. },
  152. "type"
  153. );
  154. });
  155. socket.on("open_in_editor", (data) => {
  156. let s = get_redis_subscriber("redis_socketio");
  157. s.publish("open_in_editor", JSON.stringify(data));
  158. });
  159. });
  160. subscriber.on("message", function (_channel, message) {
  161. message = JSON.parse(message);
  162. if (message.room) {
  163. io.to(message.room).emit(message.event, message.message);
  164. } else {
  165. io.emit(message.event, message.message);
  166. }
  167. });
  168. subscriber.subscribe("events");
  169. function get_doc_room(socket, doctype, docname) {
  170. return get_site_name(socket) + ":doc:" + doctype + "/" + docname;
  171. }
  172. function get_open_doc_room(socket, doctype, docname) {
  173. return get_site_name(socket) + ":open_doc:" + doctype + "/" + docname;
  174. }
  175. function get_typing_room(socket, doctype, docname) {
  176. return get_site_name(socket) + ":typing:" + doctype + "/" + docname;
  177. }
  178. function get_user_room(socket, user) {
  179. return get_site_name(socket) + ":user:" + user || socket.user;
  180. }
  181. function get_site_room(socket) {
  182. return get_site_name(socket) + ":all";
  183. }
  184. function get_website_room(socket) {
  185. return get_site_name(socket) + ":website";
  186. }
  187. function get_doctype_room(socket, doctype) {
  188. return get_site_name(socket) + ":doctype:" + doctype;
  189. }
  190. function get_task_room(socket, task_id) {
  191. return get_site_name(socket) + ":task_progress:" + task_id;
  192. }
  193. function get_site_name(socket) {
  194. if (socket.site_name) {
  195. return socket.site_name;
  196. } else if (socket.request.headers["x-xhiveframework-site-name"]) {
  197. socket.site_name = get_hostname(socket.request.headers["x-xhiveframework-site-name"]);
  198. } else if (
  199. conf.default_site &&
  200. ["localhost", "127.0.0.1"].indexOf(get_hostname(socket.request.headers.host)) !== -1
  201. ) {
  202. // from currentsite.txt since host is localhost
  203. socket.site_name = conf.default_site;
  204. } else if (socket.request.headers.origin) {
  205. socket.site_name = get_hostname(socket.request.headers.origin);
  206. } else {
  207. socket.site_name = get_hostname(socket.request.headers.host);
  208. }
  209. return socket.site_name;
  210. }
  211. function get_hostname(url) {
  212. if (!url) return undefined;
  213. if (url.indexOf("://") > -1) {
  214. url = url.split("/")[2];
  215. }
  216. return url.match(/:/g) ? url.slice(0, url.indexOf(":")) : url;
  217. }
  218. function get_url(socket, path) {
  219. if (!path) {
  220. path = "";
  221. }
  222. return socket.request.headers.origin + path;
  223. }
  224. function can_subscribe_doc(args) {
  225. if (!args) return;
  226. if (!args.doctype || !args.docname) return;
  227. request
  228. .get(get_url(args.socket, "/api/method/xhiveframework.realtime.can_subscribe_doc"))
  229. .type("form")
  230. .query({
  231. sid: args.socket.sid,
  232. doctype: args.doctype,
  233. docname: args.docname,
  234. })
  235. .end(function (err, res) {
  236. if (!res) {
  237. log("No response for doc_subscribe");
  238. } else if (res.status == 403) {
  239. return;
  240. } else if (err) {
  241. log(err);
  242. } else if (res.status == 200) {
  243. args.callback(err, res);
  244. } else {
  245. log("Something went wrong", err, res);
  246. }
  247. });
  248. }
  249. function can_subscribe_doctype(args) {
  250. if (!args) return;
  251. if (!args.doctype) return;
  252. request
  253. .get(get_url(args.socket, "/api/method/xhiveframework.realtime.can_subscribe_doctype"))
  254. .type("form")
  255. .query({
  256. sid: args.socket.sid,
  257. doctype: args.doctype,
  258. })
  259. .end(function (err, res) {
  260. if (!res || res.status == 403 || err) {
  261. if (err) {
  262. log(err);
  263. }
  264. return false;
  265. } else if (res.status == 200) {
  266. args.callback && args.callback(err, res);
  267. return true;
  268. }
  269. log("ERROR (can_subscribe_doctype): ", err, res);
  270. });
  271. }
  272. function send_users(args, action) {
  273. if (!(args && args.doctype && args.docname)) {
  274. return;
  275. }
  276. const open_doc_room = get_open_doc_room(args.socket, args.doctype, args.docname);
  277. const room =
  278. action == "view"
  279. ? open_doc_room
  280. : get_typing_room(args.socket, args.doctype, args.docname);
  281. const clients = Array.from(io.sockets.adapter.rooms.get(room) || []);
  282. let users = [];
  283. io.sockets.sockets.forEach((sock) => {
  284. if (clients.includes(sock.id)) {
  285. users.push(sock.user);
  286. }
  287. });
  288. const emit_event = action == "view" ? "doc_viewers" : "doc_typers";
  289. // notify
  290. io.to(open_doc_room).emit(emit_event, {
  291. doctype: args.doctype,
  292. docname: args.docname,
  293. users: Array.from(new Set(users)),
  294. });
  295. }