Home Reference Source

cables_dev/cables_electron/src/utils/ops_util.js

  1. import { utilProvider, SharedOpsUtil } from "cables-shared-api";
  2. import path from "path";
  3. import mkdirp from "mkdirp";
  4. import fs from "fs";
  5. import projectsUtil from "./projects_util.js";
  6. import filesUtil from "./files_util.js";
  7. class OpsUtil extends SharedOpsUtil
  8. {
  9. validateAndFormatOpCode(code)
  10. {
  11. return {
  12. "formatedCode": this._helperUtil.removeTrailingSpaces(code),
  13. "error": false,
  14. "message": null
  15. };
  16. }
  17. isCoreOp(opName)
  18. {
  19. if (!opName || this.isLocalOp(opName)) return false;
  20. const opsDir = this._cables.getCoreOpsPath();
  21. const opDir = this.getOpSourceDir(opName);
  22. return opDir.startsWith(opsDir);
  23. }
  24. addPermissionsToOps(opDocs, user, teams = [], project = null)
  25. {
  26. if (!opDocs) return opDocs;
  27. opDocs.forEach((opDoc) =>
  28. {
  29. const file = this.getOpAbsoluteFileName(opDoc.name);
  30. opDoc.allowEdit = true;
  31. if (file)
  32. {
  33. try
  34. {
  35. fs.accessSync(file, fs.constants.R_OK | fs.constants.W_OK);
  36. opDoc.allowEdit = true;
  37. }
  38. catch (e)
  39. {
  40. // not allowed to read/write
  41. opDoc.allowEdit = false;
  42. }
  43. }
  44. });
  45. return opDocs;
  46. }
  47. userHasWriteRightsOp(user, opName, teams = [], project = null, ignoreAdmin = false)
  48. {
  49. if (!user) return false;
  50. if (!opName) return false;
  51. if (!opName.startsWith(this.PREFIX_OPS)) return false;
  52. if (opName.indexOf("..") > -1) return false;
  53. if (opName.indexOf(" ") > -1) return false;
  54. if (opName.startsWith(".")) return false;
  55. if (opName.endsWith(".")) return false;
  56. const validName = this.isOpNameValid(opName);
  57. if (!validName) return false;
  58. const file = this.getOpAbsoluteFileName(opName);
  59. if (file)
  60. {
  61. if (fs.existsSync(file))
  62. {
  63. try
  64. {
  65. fs.accessSync(file, fs.constants.R_OK | fs.constants.W_OK);
  66. return true;
  67. }
  68. catch (e)
  69. {
  70. // not allowed to read/write
  71. return false;
  72. }
  73. }
  74. else if (this._cables.inPackage(file))
  75. {
  76. return false;
  77. }
  78. else
  79. {
  80. return true;
  81. }
  82. }
  83. return true;
  84. }
  85. getOpAbsolutePath(opName)
  86. {
  87. return projectsUtil.getAbsoluteOpDirFromHierarchy(opName);
  88. }
  89. getOpSourceDir(opName, relative = false)
  90. {
  91. if (!opName) return null;
  92. if (relative) return super.getOpSourceDir(opName, relative);
  93. return projectsUtil.getAbsoluteOpDirFromHierarchy(opName);
  94. }
  95. getOpTargetDir(opName, relative = false)
  96. {
  97. let targetDir = "";
  98. if (relative)
  99. {
  100. if (opName.endsWith(".")) opName = opName.substring(0, opName.length - 1);
  101. return path.join(opName, "/");
  102. }
  103. else
  104. {
  105. targetDir = projectsUtil.getAbsoluteOpDirFromHierarchy(opName);
  106. }
  107. return targetDir;
  108. }
  109. getOpSourceNoHierarchy(opName, relative = false)
  110. {
  111. return super.getOpSourceDir(opName, relative);
  112. }
  113. getOpRenameConsequences(newName, oldName, targetDir = null)
  114. {
  115. return [];
  116. }
  117. /**
  118. * @typedef {Object} OpRenameProblems
  119. * @property {String} [source_does_not_exist]
  120. * @property {String} [overruled_by_other_op]
  121. * @property {String} [namespace_empty]
  122. * @property {String} [patch_op_illegal_namespace]
  123. * @property {String} [name_ends_with_dot]
  124. * @property {String} [name_ends_with_underscore]
  125. * @property {String} [name_not_op_namespace]
  126. * @property {String} [target_exists]
  127. * @property {String} [name_taken]
  128. * @property {String} [name_too_short]
  129. * @property {String} [name_contains_doubledot]
  130. * @property {String} [name_contains_illegal_characters]
  131. * @property {String} [patch_op_rename_illegal]
  132. * @property {String} [namespace_starts_with_numbers]
  133. * @property {String} [namespace_starts_with_whitespace]
  134. * @property {String} [namespace_starts_with_dash]
  135. * @property {String} [namespace_not_uppercase]
  136. * @property {String} [op_used_elsewhere]
  137. * @property {String} [no_rights_target]
  138. * @property {String} [no_rights_source]
  139. * @property {String} [not_found_source]
  140. * @property {String} [bad_op_hierarchy]
  141. * @property {String} [overruled_by_other_op]
  142. * @property {String} [illegal_ops]
  143. * @property {String} [version_suggestion]
  144. */
  145. /**
  146. * @returns {OpRenameProblems}
  147. */
  148. getOpRenameProblems(newName, oldName, userObj, teams = [], newOpProject = null, oldOpProject = null, opUsages = [], checkUsages = true, targetDir = null)
  149. {
  150. const problems = super.getOpRenameProblems(newName, oldName, userObj, teams, newOpProject, oldOpProject, opUsages, checkUsages);
  151. if (problems.no_rights_target && targetDir)
  152. {
  153. if (fs.existsSync(targetDir))
  154. {
  155. try
  156. {
  157. fs.accessSync(targetDir, fs.constants.R_OK | fs.constants.W_OK);
  158. delete problems.no_rights_target;
  159. }
  160. catch (e)
  161. {
  162. // not allowed to read/write
  163. }
  164. }
  165. else
  166. {
  167. try
  168. {
  169. mkdirp.sync(targetDir);
  170. delete problems.no_rights_target;
  171. }
  172. catch (e)
  173. {
  174. // not allowed to create targetDir
  175. }
  176. }
  177. }
  178. if (problems.target_exists && targetDir)
  179. {
  180. const newOpDir = path.join(targetDir, this.getOpTargetDir(newName, true), this.getOpFileName(newName));
  181. if (!fs.existsSync(newOpDir))
  182. {
  183. delete problems.target_exists;
  184. const existingOpDir = this.getOpSourceDir(newName);
  185. problems.overruled_by_other_op = "The new Op would conflict with the Op at:<br/> <a onclick=\"CABLESUILOADER.talkerAPI.send('openDir', { 'dir': '" + existingOpDir + "'});\">" + existingOpDir + "</a>";
  186. }
  187. }
  188. return problems;
  189. }
  190. getOpAssetPorts(op, includeLibraryAssets = false)
  191. {
  192. const assetPorts = [];
  193. if (!op) return assetPorts;
  194. if (!op.portsIn) return assetPorts;
  195. for (let i = 0; i < op.portsIn.length; i++)
  196. {
  197. const port = op.portsIn[i];
  198. if (
  199. port.value &&
  200. typeof port.value == "string" &&
  201. port.name &&
  202. port.value.length &&
  203. (port.display === "file" ||
  204. port.name.toLowerCase().indexOf("file") > -1 ||
  205. port.name.toLowerCase().indexOf("url") > -1 ||
  206. // port names in cubemapfromtextures !
  207. port.name.toLowerCase().indexOf("posx") > -1 ||
  208. port.name.toLowerCase().indexOf("posy") > -1 ||
  209. port.name.toLowerCase().indexOf("posz") > -1 ||
  210. port.name.toLowerCase().indexOf("negx") > -1 ||
  211. port.name.toLowerCase().indexOf("negy") > -1 ||
  212. port.name.toLowerCase().indexOf("negz") > -1)
  213. )
  214. {
  215. if (!port.value.toLowerCase().startsWith("/assets/library"))
  216. {
  217. assetPorts.push(port);
  218. }
  219. else if (includeLibraryAssets)
  220. {
  221. assetPorts.push(port);
  222. }
  223. }
  224. }
  225. return assetPorts;
  226. }
  227. getOpNameByAbsoluteFileName(fileName)
  228. {
  229. if (!fileName) return "";
  230. const parts = path.parse(fileName);
  231. if (parts && parts.name) return parts.name;
  232. return "";
  233. }
  234. updateOpCode(opName, author, code)
  235. {
  236. filesUtil.unregisterOpChangeListeners([opName]);
  237. const newCode = super.updateOpCode(opName, author, code);
  238. setTimeout(() =>
  239. {
  240. filesUtil.registerOpChangeListeners([opName]);
  241. }, 1000);
  242. return newCode;
  243. }
  244. getOpNpmPackages(opName)
  245. {
  246. let toInstall = [];
  247. const opDoc = this._docsUtil.getDocForOp(opName);
  248. if (opDoc && opDoc.hasOwnProperty("dependencies"))
  249. {
  250. const npmDeps = opDoc.dependencies.filter((dep) => { return dep.type === "npm"; });
  251. npmDeps.forEach((npmDep) =>
  252. {
  253. if (npmDep.src)
  254. {
  255. if (!toInstall.includes(npmDep.src))
  256. {
  257. toInstall.push(npmDep.src);
  258. }
  259. }
  260. });
  261. }
  262. return toInstall;
  263. }
  264. renameToCoreOp(oldName, newName, currentUser, cb = null)
  265. {
  266. let oldOpDir = this.getOpSourceDir(oldName);
  267. let newOpDir = oldOpDir.replace(oldName, newName);
  268. return this._renameOp(oldName, newName, currentUser, true, true, false, oldOpDir, newOpDir, cb);
  269. }
  270. renameToExtensionOp(oldName, newName, currentUser, cb = null)
  271. {
  272. let oldOpDir = this.getOpSourceDir(oldName);
  273. let newOpDir = oldOpDir.replace(oldName, newName);
  274. return this._renameOp(oldName, newName, currentUser, true, true, false, oldOpDir, newOpDir, cb);
  275. }
  276. renameToTeamOp(oldName, newName, currentUser, cb = null)
  277. {
  278. let oldOpDir = this.getOpSourceDir(oldName);
  279. let newOpDir = oldOpDir.replace(oldName, newName);
  280. return this._renameOp(oldName, newName, currentUser, false, true, false, oldOpDir, newOpDir, cb);
  281. }
  282. renameToUserOp(oldName, newName, currentUser, cb = null)
  283. {
  284. let oldOpDir = this.getOpSourceDir(oldName);
  285. let newOpDir = oldOpDir.replace(oldName, newName);
  286. return this._renameOp(oldName, newName, currentUser, false, true, false, oldOpDir, newOpDir, cb);
  287. }
  288. renameToPatchOp(oldName, newName, currentUser, removeOld, newId, cb = null)
  289. {
  290. let oldOpDir = this.getOpSourceDir(oldName);
  291. let newOpDir = oldOpDir.replace(oldName, newName);
  292. return this._renameOp(oldName, newName, currentUser, false, removeOld, newId, oldOpDir, newOpDir, cb);
  293. }
  294. getPatchOpNamespace(opName)
  295. {
  296. return this.getNamespace(opName);
  297. }
  298. getPatchOpsNamespaceForProject(proj)
  299. {
  300. return this.PREFIX_LOCAL_OPS;
  301. }
  302. userHasReadRightsOp(user, opName, teams = null, project = null, opOwner = null)
  303. {
  304. return true;
  305. }
  306. getCollectionName(opName)
  307. {
  308. if (!opName) return null;
  309. if (opName.startsWith(this.PREFIX_LOCAL_OPS)) return this.PREFIX_LOCAL_OPS;
  310. return super.getCollectionName(opName);
  311. }
  312. }
  313. export default new OpsUtil(utilProvider);