blistovmhz

Untitled

Feb 3rd, 2024
896
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.   async newJoinMonster({
  2.     table,
  3.     whereClause: _WC,
  4.     knexQuery,
  5.     auth,
  6.     permission_list,
  7.     row_id,
  8.     force_id_read = false,
  9.     run_as,
  10.     operator,
  11.   }) {
  12.     const whereClause = JSON.parse(JSON.stringify(_WC));
  13.     const { token, account } = auth;
  14.     if (Array.isArray(whereClause)) {
  15.       if (whereClause.length === 0) {
  16.         return { builder: knexQuery, filters_applied: false };
  17.       }
  18.       if (
  19.         whereClause.length === 1 &&
  20.         (whereClause[0] === "AND" || whereClause[0] === "OR")
  21.       ) {
  22.         return { builder: knexQuery, filters_applied: false };
  23.       }
  24.       operator = whereClause.shift();
  25.       if (operator !== "AND" && operator !== "OR") {
  26.         throw new Error(
  27.           "Please send your operator as the first item of the array",
  28.         );
  29.       }
  30.       for (const item of whereClause) {
  31.         const temp_knex = this.knex;
  32.         const temp2_builder = await this.newJoinMonster({
  33.           table,
  34.           whereClause: item,
  35.           knexQuery: temp_knex.select("*"),
  36.           auth,
  37.           permission_list,
  38.           row_id,
  39.           force_id_read: false,
  40.           run_as,
  41.           operator,
  42.         });
  43.         if (
  44.           operator === "OR" &&
  45.           temp2_builder.filters_applied &&
  46.           temp2_builder.builder
  47.         ) {
  48.           knexQuery = knexQuery.orWhere((builder) => {
  49.             return builder.whereRaw(
  50.               temp2_builder.builder.toSQL().sql.split("select * where")[1],
  51.               temp2_builder.builder.toSQL().bindings,
  52.             );
  53.           });
  54.         } else if (
  55.           operator === "AND" &&
  56.           temp2_builder.filters_applied &&
  57.           temp2_builder.builder
  58.         ) {
  59.           knexQuery = knexQuery.where((builder) => {
  60.             return builder.whereRaw(
  61.               temp2_builder.builder.toSQL().sql.split("select * where")[1],
  62.               temp2_builder.builder.toSQL().bindings,
  63.             );
  64.           });
  65.         }
  66.       }
  67.       return {
  68.         builder: knexQuery,
  69.         filters_applied: true,
  70.       };
  71.     } else {
  72.       console.log("here");
  73.       for (const [key, value] of Object.entries(whereClause)) {
  74.         // CHECK IF KEY IS A TABLE
  75.         const some_type_of_link = ["foreign", "link", "externalLink"];
  76.  
  77.         console.log("KEY: ", key);
  78.         console.log("TABLE: ", this.schema[table]);
  79.         console.log("LINK TYPE: ", this.schema[table].columns?.[key]?.type);
  80.         // I WILL NEED TO HAVE SCHEMA INCLUDE ID, CREATED_AT, UPDATED_AT. BUT THAT IS A TASK FOR FUTURE ADAM
  81.         if (
  82.           some_type_of_link.includes(this.schema[table].columns?.[key]?.type)
  83.         ) {
  84.           // table schema details
  85.           const querySchema = this.schema[table].columns[key];
  86.           // check if this column is a reverse relation
  87.           const bColumnIsReverse = querySchema.reverse || false;
  88.           let allowed;
  89.           // check permissions and see if the user is actually allowed to query using the where filter
  90.           if (bColumnIsReverse) {
  91.             allowed = await this.aclAndRclPermissionCheck({
  92.               table_name: querySchema[querySchema.type].table,
  93.               key: querySchema[querySchema.type].reference_name,
  94.               account,
  95.               row_id,
  96.               force_id: force_id_read,
  97.               permission_list,
  98.               permissionType: "read",
  99.             });
  100.           } else {
  101.             allowed = await this.aclAndRclPermissionCheck({
  102.               table_name: table,
  103.               key,
  104.               account,
  105.               row_id,
  106.               virtual: querySchema.type === "link",
  107.               force_id: force_id_read,
  108.               permission_list,
  109.               permissionType: "read",
  110.             });
  111.           }
  112.           //debug_logger.log({ bColumnIsReverse });
  113.           /*           debug_logger.log('acl+rcl permission check arguments', {
  114.             table_name: table,
  115.             key,
  116.             account,
  117.             row_id,
  118.             virtual: querySchema.type === 'link',
  119.             force_id: force_id_read,
  120.             permission_list,
  121.             permissionType: 'read',
  122.           }); */
  123.           //console.log({ key, allowed });
  124.           if (!allowed) {
  125.             // QUERY TO AUTOMATICALLY REMOVE ALL ROWS / IMPOSSIBLE QUERY
  126.             // return this.throwErrorForJoinMonster(knexQuery, table);
  127.             throw new Error(
  128.               `Foreign field can't be searched in where clause because no ACL, yes RCL; field: ${key}`,
  129.            );
  130.          }
  131.          let tableToJoin = "";
  132.          if (querySchema.type === "foreign") {
  133.            allowed = await this.aclAndRclPermissionCheck({
  134.              table_name: querySchema[querySchema.type].table,
  135.              key: "id",
  136.              row_id,
  137.              force_id: force_id_read,
  138.              permission_list,
  139.              account,
  140.              permissionType: "read",
  141.            });
  142.  
  143.            tableToJoin = querySchema[querySchema.type].table;
  144.          } else {
  145.            allowed = await this.aclAndRclPermissionCheck({
  146.              table_name: table,
  147.              key,
  148.              row_id,
  149.              account,
  150.              force_id: force_id_read,
  151.              virtual: querySchema.type === "link",
  152.              permission_list,
  153.              permissionType: "read",
  154.            });
  155.            tableToJoin = key;
  156.          }
  157.          if (!allowed) {
  158.            // QUERY TO AUTOMATICALLY REMOVE ALL ROWS / IMPOSSIBLE QUERY
  159.            // return this.throwErrorForJoinMonster(knexQuery, table);
  160.            throw new Error(
  161.              `Foreign field can't be searched in where clause because yes ACL, ? RCL; field: ${key}`,
  162.             );
  163.           }
  164.  
  165.           /**
  166.            * if field simply specifies null, e.g.
  167.            *
  168.            * where: ["AND", { job: null }]
  169.            *
  170.            * just make it where null
  171.            */
  172.           if (value === null && !bColumnIsReverse) {
  173.             knexQuery.whereNull(key);
  174.             continue;
  175.           }
  176.           let children_results;
  177.  
  178.           const new_query_table = querySchema[querySchema.type].table;
  179.           // TODO: NEED TO CHECK IF PLUGIN
  180.           const new_query_table_schema =
  181.             this.schema[new_query_table].microservice_name;
  182.           let children_knex_query;
  183.           let children_query_key;
  184.  
  185.           const child_table_def = this.schema[table].columns?.[key]?.[
  186.             this.schema[table].columns?.[key]?.type
  187.           ];
  188.           const child_primary_key = child_table_def.key;
  189.           const reference_name = child_table_def.reference_name ||
  190.             child_table_def.table || table;
  191.  
  192.           if (bColumnIsReverse) {
  193.             children_query_key = table;
  194.             children_knex_query = this.knex
  195.               .from(`${new_query_table} AS ${new_query_table}`)
  196.               .withSchema(new_query_table_schema)
  197.               .select(reference_name);
  198.           } else if (querySchema.type === "link") {
  199.             children_query_key = "id";
  200.             children_knex_query = this.knex
  201.               .from(`${new_query_table} AS ${new_query_table}`)
  202.               .withSchema(new_query_table_schema)
  203.               .select(children_knex_query);
  204.           } else {
  205.             children_query_key = querySchema[querySchema.type].key;
  206.             children_knex_query = this.knex
  207.               .from(`${new_query_table} AS ${new_query_table}`)
  208.               .withSchema(new_query_table_schema)
  209.               .select(children_knex_query);
  210.           }
  211.  
  212.           if (value === null) {
  213.             /**
  214.              * inverse search
  215.              * in order to get where reverse foreign is null we have to do:
  216.              *
  217.              * get current records that do have that value, and "reverse" the result
  218.              *
  219.              * i.e. to get a list of jobs that do not have daily reports,
  220.              * get a list of daily reports that have jobs,
  221.              * get jobs which ids has not been in that array
  222.              */
  223.             const children_results_temp = await this.knex
  224.               .from(table)
  225.               .withSchema(new_query_table_schema)
  226.               .select(child_primary_key)
  227.               .whereNotIn(
  228.                 child_primary_key,
  229.                 children_knex_query.whereNotNull(reference_name),
  230.               );
  231.  
  232.             children_results = children_results_temp.map((el) => {
  233.               return el[child_primary_key];
  234.             });
  235.           } else {
  236.             const children_results_query = await this.newJoinMonster({
  237.               table: new_query_table,
  238.               whereClause: value,
  239.               knexQuery: children_knex_query,
  240.               permission_list,
  241.               row_id,
  242.               auth,
  243.             });
  244.             const children_results_temp = await children_results_query.builder;
  245.             children_results = children_results_temp.map((el) => {
  246.               return el[children_query_key];
  247.             });
  248.           }
  249.  
  250.           const column_type = querySchema[querySchema.type].type;
  251.           let where_key;
  252.           if (bColumnIsReverse) {
  253.             where_key = querySchema[querySchema.type].key;
  254.           } else {
  255.             where_key = key;
  256.           }
  257.           // over here, we just got the results back from the foreign key search and if column type isn't an array, we are doing a where in search.
  258.           if (querySchema.type === "foreign") {
  259.             if (!column_type?.includes("Array")) {
  260.               knexQuery.whereIn(where_key, children_results);
  261.             } else {
  262.               const raw_query = `array[${children_results.join(
  263.                 ", ",
  264.               )
  265.                 }] @> "${where_key}"`;
  266.               if (children_results.length === 0) {
  267.                 knexQuery.whereNull("id");
  268.               } else {
  269.                 knexQuery.whereRaw(raw_query);
  270.               }
  271.             }
  272.           } else if (querySchema.type === "link") {
  273.             const link_table_name = linkTableNamePartial({
  274.               table_name: table,
  275.               column_name: key,
  276.             });
  277.             let temp_query = await this.knex(link_table_name)
  278.               .withSchema("link")
  279.               .whereIn(
  280.                 getReverseColumnName({
  281.                   table_name: table,
  282.                   column_name: key,
  283.                 }),
  284.                 children_results,
  285.               );
  286.             knexQuery.whereIn(
  287.               "id",
  288.               temp_query.map((el) => el[`${table}_${key}`]),
  289.             );
  290.           }
  291.         } // must mean that the argument is a column name (id, name etc...)
  292.         // I'll add a check later
  293.         else {
  294.           console.log("CANNOT CREATE JOIN");
  295.           // STANDARD PERMISSION CHECKS
  296.           let temp_table = table;
  297.           if (this.schema[table].is_audit) {
  298.             temp_table = this.schema[table].audits;
  299.           }
  300.           const newPermissions = await this.CL.getAllPermissions({
  301.             table_name: temp_table,
  302.             account,
  303.             force_id: force_id_read,
  304.             info: {
  305.               where: "newJoinMonster STANDARD PERMISSION CHECKS",
  306.             },
  307.           });
  308.  
  309.           let has_access = false;
  310.  
  311.           //console.log('check permission for', key);
  312.  
  313.           // allow access if acl gives
  314.           if (newPermissions?.acl_permissions?.read?.includes(key)) {
  315.             has_access = true;
  316.           } else {
  317.             console.log({ row_id });
  318.             // else if acl blocks
  319.             // check if rcl gives
  320.             if (
  321.               _.find(newPermissions.rcl_permissions, {
  322.                 row_id,
  323.               })?.read?.includes(key)
  324.             ) {
  325.               has_access = true;
  326.             }
  327.           }
  328.  
  329.           if (has_access) {
  330.             // ============================ SPC =================
  331.             for (
  332.               const [
  333.                 search_operator,
  334.                 search_operator_value,
  335.               ] of Object.entries(value)
  336.             ) {
  337.               //NEED TO DO A NULL CHECK (ONLY WAY TO QUERY FOR NULL VALUES)
  338.               if (search_operator_value === null && search_operator === "eq") {
  339.                 knexQuery.whereNull(`${table}.${key}`);
  340.               } else if (
  341.                 search_operator_value === null &&
  342.                 search_operator === "neq"
  343.               ) {
  344.                 knexQuery.whereNotNull(`${table}.${key}`);
  345.               } else {
  346.                 if (
  347.                   this.schema?.[table]?.columns?.[key]?.type === "integer" &&
  348.                   GQLizerToKnexMappings[search_operator] === "ilike"
  349.                 ) {
  350.                   /**
  351.                    * if field type is integer but we use a like, cast the value to a string
  352.                    */
  353.                   knexQuery.whereRaw(
  354.                     [
  355.                       `"${table}"."${key}"` + "::varchar",
  356.                       GQLizerToKnexMappings[search_operator],
  357.                       `'${search_operator_value}'`,
  358.                     ].join(" "),
  359.                   );
  360.                 } else {
  361.                   knexQuery.where(
  362.                     `${table}.${key}`,
  363.                     GQLizerToKnexMappings[search_operator],
  364.                     search_operator_value,
  365.                   );
  366.                 }
  367.               }
  368.             }
  369.           } else {
  370.             // QUERY TO AUTOMATICALLY REMOVE ALL ROWS / IMPOSSIBLE QUERY
  371.             throw new Error("You do not have access to this");
  372.           }
  373.         }
  374.       }
  375.     }
  376.     return { builder: knexQuery, filters_applied: true };
  377.   }
Advertisement
Add Comment
Please, Sign In to add comment