2020-11-17 21:49:32 +00:00
|
|
|
import ast
|
2020-12-28 05:40:10 +00:00
|
|
|
|
|
|
|
import asttokens
|
2021-06-24 12:23:33 +00:00
|
|
|
|
2024-04-26 20:34:16 +00:00
|
|
|
from predicate_formula import NamedEntity, parse_predicate_formula_json, TreeConverter
|
2020-11-17 21:49:32 +00:00
|
|
|
|
2024-04-26 20:34:16 +00:00
|
|
|
def parse_acl_formulas(col_values):
|
2020-11-17 21:49:32 +00:00
|
|
|
"""
|
2024-04-26 20:34:16 +00:00
|
|
|
Populates `aclFormulaParsed` by parsing `aclFormula` for all `col_values`.
|
2020-11-17 21:49:32 +00:00
|
|
|
"""
|
2024-04-26 20:34:16 +00:00
|
|
|
if 'aclFormula' not in col_values:
|
|
|
|
return
|
2020-11-17 21:49:32 +00:00
|
|
|
|
2024-04-26 20:34:16 +00:00
|
|
|
col_values['aclFormulaParsed'] = [parse_predicate_formula_json(v)
|
|
|
|
for v
|
|
|
|
in col_values['aclFormula']]
|
2020-12-28 05:40:10 +00:00
|
|
|
|
|
|
|
def parse_acl_grist_entities(acl_formula):
|
|
|
|
"""
|
|
|
|
Parse the ACL formula collecting any entities that may be subject to renaming. Returns a
|
|
|
|
NamedEntity list.
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
atok = asttokens.ASTTokens(acl_formula, tree=ast.parse(acl_formula, mode='eval'))
|
|
|
|
converter = _EntityCollector()
|
|
|
|
converter.visit(atok.tree)
|
|
|
|
return converter.entities
|
|
|
|
except SyntaxError as err:
|
|
|
|
return []
|
|
|
|
|
2024-04-26 20:34:16 +00:00
|
|
|
class _EntityCollector(TreeConverter):
|
2020-12-28 05:40:10 +00:00
|
|
|
def __init__(self):
|
|
|
|
self.entities = [] # NamedEntity list
|
|
|
|
|
|
|
|
def visit_Attribute(self, node):
|
|
|
|
parent = self.visit(node.value)
|
|
|
|
|
|
|
|
# We recognize a couple of specific patterns for entities that may be affected by renames.
|
2021-05-11 19:58:35 +00:00
|
|
|
if parent == ['Name', 'rec'] or parent == ['Name', 'newRec']:
|
2020-12-28 05:40:10 +00:00
|
|
|
# rec.COL refers to the column from the table that the rule is on.
|
|
|
|
self.entities.append(NamedEntity('recCol', node.last_token.startpos, node.attr, None))
|
|
|
|
if parent == ['Name', 'user']:
|
|
|
|
# user.ATTR is a user attribute.
|
|
|
|
self.entities.append(NamedEntity('userAttr', node.last_token.startpos, node.attr, None))
|
|
|
|
elif parent[0] == 'Attr' and parent[1] == ['Name', 'user']:
|
|
|
|
# user.ATTR.COL is a column from the lookup table of the UserAttribute ATTR.
|
|
|
|
self.entities.append(
|
|
|
|
NamedEntity('userAttrCol', node.last_token.startpos, node.attr, parent[2]))
|
|
|
|
|
|
|
|
return ["Attr", parent, node.attr]
|