Skip to content
This repository has been archived by the owner on Sep 12, 2024. It is now read-only.

Commit

Permalink
[ENHANCEMENT]: Implement Access Validation
Browse files Browse the repository at this point in the history
  • Loading branch information
amadolid committed Aug 21, 2024
1 parent 861512f commit 8734184
Show file tree
Hide file tree
Showing 7 changed files with 828 additions and 121 deletions.
134 changes: 84 additions & 50 deletions jaclang/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import ast as ast3
import importlib
import inspect
import marshal
import os
import pickle
Expand All @@ -22,7 +21,7 @@
from jaclang.plugin.builtin import dotgen
from jaclang.plugin.feature import JacCmd as Cmd
from jaclang.plugin.feature import JacFeature as Jac
from jaclang.runtimelib.constructs import Architype, WalkerArchitype
from jaclang.runtimelib.constructs import WalkerArchitype
from jaclang.runtimelib.machine import JacProgram
from jaclang.utils.helpers import debugger as db
from jaclang.utils.lang_tools import AstTool
Expand Down Expand Up @@ -68,12 +67,7 @@ def format_file(filename: str) -> None:

@cmd_registry.register
def run(
filename: str,
session: str = "",
main: bool = True,
cache: bool = True,
walker: str = "",
node: str = "",
filename: str, session: str = "", main: bool = True, cache: bool = True
) -> None:
"""Run the specified .jac file."""
# if no session specified, check if it was defined when starting the command shell
Expand All @@ -94,62 +88,71 @@ def run(
jctx = Jac.create_context(base_path=base, session=session)

if filename.endswith(".jac"):
ret_module = jac_import(
jac_import(
target=mod,
base_path=base,
cachable=cache,
override_name="__main__" if main else None,
)
if ret_module is None:
loaded_mod = None
else:
(loaded_mod,) = ret_module
elif filename.endswith(".jir"):
with open(filename, "rb") as f:
ir = pickle.load(f)
jac_program = JacProgram(mod_bundle=ir, bytecode=None)
jctx.jac_machine.attach_program(jac_program)
ret_module = jac_import(
jac_import(
target=mod,
base_path=base,
cachable=cache,
override_name="__main__" if main else None,
)
if ret_module is None:
loaded_mod = None
else:
(loaded_mod,) = ret_module
else:
print("Not a .jac file.")
return

if not node or node == "root":
entrypoint: Architype = jctx.root.architype
elif obj := jctx.datasource.find_by_id(UUID(node)):
entrypoint = obj.architype
else:
print(f"Entrypoint {node} not found.")
Jac.close_context()
return

# TODO: handle no override name
if walker:
walker_module = dict(inspect.getmembers(loaded_mod)).get(walker)
if walker_module:
Jac.spawn_call(entrypoint, walker_module())
else:
print(f"Walker {walker} not found.")
raise ValueError("Not a valid file!\nOnly supports `.jac` and `.jir`")

Jac.close_context()


@cmd_registry.register
def get_object(id: str, session: str = "") -> dict:
def get_object(
filename: str, id: str, session: str = "", main: bool = True, cache: bool = True
) -> dict:
"""Get the object with the specified id."""
if session == "":
session = cmd_registry.args.session if "session" in cmd_registry.args else ""
session = (
cmd_registry.args.session
if hasattr(cmd_registry, "args")
and hasattr(cmd_registry.args, "session")
and cmd_registry.args.session
else ""
)

jctx = Jac.create_context(session=session)
base, mod = os.path.split(filename)
base = base if base else "./"
mod = mod[:-4]

jctx = Jac.create_context(base_path=base, session=session)

if filename.endswith(".jac"):
jac_import(
target=mod,
base_path=base,
cachable=cache,
override_name="__main__" if main else None,
)
elif filename.endswith(".jir"):
with open(filename, "rb") as f:
ir = pickle.load(f)
jac_program = JacProgram(mod_bundle=ir, bytecode=None)
jctx.jac_machine.attach_program(jac_program)
jac_import(
target=mod,
base_path=base,
cachable=cache,
override_name="__main__" if main else None,
)
else:
Jac.close_context()
raise ValueError("Not a valid file!\nOnly supports `.jac` and `.jir`")

data = {}
if id == "root":
Expand Down Expand Up @@ -215,6 +218,8 @@ def enter(
entrypoint: str,
args: list,
session: str = "",
main: bool = True,
cache: bool = True,
root: str = "",
node: str = "",
) -> None:
Expand All @@ -228,23 +233,52 @@ def enter(
:param root: root executor.
:param node: starting node.
"""
jctx = Jac.create_context(session=session, root=root, entry=node)
if session == "":
session = (
cmd_registry.args.session
if hasattr(cmd_registry, "args")
and hasattr(cmd_registry.args, "session")
and cmd_registry.args.session
else ""
)

base, mod = os.path.split(filename)
base = base if base else "./"
mod = mod[:-4]

jctx = Jac.create_context(base_path=base, session=session, root=root, entry=node)

if filename.endswith(".jac"):
base, mod_name = os.path.split(filename)
base = base if base else "./"
mod_name = mod_name[:-4]
(mod,) = jac_import(target=mod_name, base_path=base)
if not mod:
ret_module = jac_import(
target=mod,
base_path=base,
cachable=cache,
override_name="__main__" if main else None,
)
elif filename.endswith(".jir"):
with open(filename, "rb") as f:
ir = pickle.load(f)
jac_program = JacProgram(mod_bundle=ir, bytecode=None)
jctx.jac_machine.attach_program(jac_program)
ret_module = jac_import(
target=mod,
base_path=base,
cachable=cache,
override_name="__main__" if main else None,
)
else:
Jac.close_context()
raise ValueError("Not a valid file!\nOnly supports `*.jac` and `*.jir`")

if ret_module:
(loaded_mod,) = ret_module
if not loaded_mod:
print("Errors occurred while importing the module.")
else:
architype = getattr(mod, entrypoint)(*args)
if isinstance(architype, WalkerArchitype):
architype = getattr(loaded_mod, entrypoint)(*args)
if isinstance(architype, WalkerArchitype) and jctx.validate_access():
Jac.spawn_call(jctx.entry.architype, architype)

else:
print("Not a .jac file.")

Jac.close_context()


Expand Down
17 changes: 10 additions & 7 deletions jaclang/plugin/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,13 +481,14 @@ def connect(
_left = i.__jac__
for j in right:
_right = j.__jac__
conn_edge = edge_spec()
edges.append(conn_edge)
_left.connect_node(_right, conn_edge.__jac__)
if _left.persistent or _right.persistent:
conn_edge.__jac__.save()
_right.save()
_left.save()
if _left.has_connect_access(_right):
conn_edge = edge_spec()
edges.append(conn_edge)
_left.connect_node(_right, conn_edge.__jac__)
if _left.persistent or _right.persistent:
conn_edge.__jac__.save()
_right.save()
_left.save()
return right if not edges_only else edges

@staticmethod
Expand Down Expand Up @@ -516,13 +517,15 @@ def disconnect(
dir in [EdgeDir.OUT, EdgeDir.ANY]
and node == source
and target.architype in right
and source.has_write_access(target)
):
anchor.destroy()
disconnect_occurred = True
if (
dir in [EdgeDir.IN, EdgeDir.ANY]
and node == target
and source.architype in right
and target.has_write_access(source)
):
anchor.destroy()
disconnect_occurred = True
Expand Down
82 changes: 82 additions & 0 deletions jaclang/plugin/tests/fixtures/other_root_access.jac
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import:py from jaclang.runtimelib.architype {Anchor}
import:py from uuid {UUID}

node A {
has val: int;
}

walker check_node {
can enter with `root entry {
visit [-->];
}

can enter2 with A entry {
print(here);
}
}

walker update_node {
has val: int;

can enter2 with A entry {
here.val = self.val;
}
}

walker create_node {
has val: int;

can enter with `root entry {
a = A(val=self.val);
here ++> a;
print(a.__jac__.id);
}
}

walker create_other_root {
can enter with `root entry {
other_root = `root().__jac__;
other_root.save();
print(other_root.id);
}
}

walker allow_other_root_access {
has root_id: str, level: int | str = 0, via_all: bool = False;

can enter_root with `root entry {
if self.via_all {
here.__jac__.unrestrict(self.level);
} else {
here.__jac__.allow_root(UUID(self.root_id), self.level);
}
}

can enter_nested with A entry {
if self.via_all {
here.__jac__.unrestrict(self.level);
} else {
here.__jac__.allow_root(UUID(self.root_id), self.level);
}
}
}

walker disallow_other_root_access {
has root_id: str, via_all: bool = False;

can enter_root with `root entry {
if self.via_all {
here.__jac__.restrict();
} else {
here.__jac__.disallow_root(UUID(self.root_id));
}
}

can enter_nested with A entry {
if self.via_all {
here.__jac__.restrict();
} else {
here.__jac__.disallow_root(UUID(self.root_id));
}
}
}
Loading

0 comments on commit 8734184

Please sign in to comment.