diff --git a/api/src/main/java/org/densy/scriptify/api/script/module/ScriptModuleManager.java b/api/src/main/java/org/densy/scriptify/api/script/module/ScriptModuleManager.java index 29feb9e..df7c4b9 100644 --- a/api/src/main/java/org/densy/scriptify/api/script/module/ScriptModuleManager.java +++ b/api/src/main/java/org/densy/scriptify/api/script/module/ScriptModuleManager.java @@ -1,5 +1,6 @@ package org.densy.scriptify.api.script.module; +import org.densy.scriptify.api.script.module.export.access.ScriptAccess; import org.densy.scriptify.api.script.module.export.resolver.ScriptModuleExportResolverFactory; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnmodifiableView; @@ -25,6 +26,20 @@ public interface ScriptModuleManager { */ void setModuleExportResolver(ScriptModuleExportResolverFactory factory); + /** + * Gets the script's access to the module and its exported properties. + * + * @return ScriptAccess enum + */ + ScriptAccess getScriptAccess(); + + /** + * Sets the script's access to the module and its exported properties. + * + * @param scriptAccess ScriptAccess to set + */ + void setScriptAccess(ScriptAccess scriptAccess); + /** * Gets the internal global module. Exports added here are available globally without import. */ diff --git a/api/src/main/java/org/densy/scriptify/api/script/module/export/access/ScriptAccess.java b/api/src/main/java/org/densy/scriptify/api/script/module/export/access/ScriptAccess.java new file mode 100644 index 0000000..3fbbc2a --- /dev/null +++ b/api/src/main/java/org/densy/scriptify/api/script/module/export/access/ScriptAccess.java @@ -0,0 +1,41 @@ +package org.densy.scriptify.api.script.module.export.access; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Defines the script's access to the module and its exported properties. + */ +public enum ScriptAccess { + /** + * Full access. + */ + ALL, + /** + * Explicit access to fields, methods, and constructors marked with an annotation {@link ScriptAccess.Export} + */ + EXPLICIT; + + /** + * An annotation that exports access to a method, field, or constructor for a script. + * + *
+     * public class MyService {
+     *     public String publicMethod() { ... }      // unavailable in script
+     *
+     *     @ScriptAccess.Export
+     *     public String internalMethod() { ... }    // available in script
+     *
+     *     @ScriptAccess.Export
+     *     public String sensitiveField;             // available in script
+     * }
+     * 
+ */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR}) + public @interface Export { + + } +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index d42a104..b90f127 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ java { allprojects { group = "org.densy.scriptify" - version = "1.6.0-SNAPSHOT" + version = "1.6.1-SNAPSHOT" } subprojects { diff --git a/http/src/main/java/org/densy/scriptify/http/script/function/data/HttpMethod.java b/http/src/main/java/org/densy/scriptify/http/script/function/data/HttpMethod.java index c7edad5..44a8184 100644 --- a/http/src/main/java/org/densy/scriptify/http/script/function/data/HttpMethod.java +++ b/http/src/main/java/org/densy/scriptify/http/script/function/data/HttpMethod.java @@ -1,12 +1,14 @@ package org.densy.scriptify.http.script.function.data; +import org.densy.scriptify.api.script.module.export.access.ScriptAccess; + public enum HttpMethod { - GET, - PUT, - POST, - DELETE, - PATCH, - HEAD, - OPTIONS, - TRACE + @ScriptAccess.Export GET, + @ScriptAccess.Export PUT, + @ScriptAccess.Export POST, + @ScriptAccess.Export DELETE, + @ScriptAccess.Export PATCH, + @ScriptAccess.Export HEAD, + @ScriptAccess.Export OPTIONS, + @ScriptAccess.Export TRACE } diff --git a/http/src/main/java/org/densy/scriptify/http/script/function/data/HttpRequest.java b/http/src/main/java/org/densy/scriptify/http/script/function/data/HttpRequest.java index 3d82d5f..24f8ad0 100644 --- a/http/src/main/java/org/densy/scriptify/http/script/function/data/HttpRequest.java +++ b/http/src/main/java/org/densy/scriptify/http/script/function/data/HttpRequest.java @@ -1,7 +1,7 @@ package org.densy.scriptify.http.script.function.data; -import org.densy.scriptify.api.script.ScriptObject; import okhttp3.*; +import org.densy.scriptify.api.script.module.export.access.ScriptAccess; import java.io.IOException; import java.util.HashMap; @@ -14,24 +14,29 @@ public class HttpRequest { private String body = ""; private String mediaType = ""; + @ScriptAccess.Export public HttpRequest(String url, HttpMethod method) { this.url = url; this.method = method; } + @ScriptAccess.Export public void setBody(String body, String mediaType) { this.body = body; this.mediaType = mediaType; } + @ScriptAccess.Export public void addHeader(String key, String value) { headers.put(key, value); } + @ScriptAccess.Export public Object send(String outputType) { return this.send(OutputType.valueOf(outputType)); } + @ScriptAccess.Export public Object send(OutputType outputType) { Request.Builder requestBuilder = new Request.Builder() .url(url); diff --git a/http/src/main/java/org/densy/scriptify/http/script/function/data/OutputType.java b/http/src/main/java/org/densy/scriptify/http/script/function/data/OutputType.java index 55fc939..6f89ed6 100644 --- a/http/src/main/java/org/densy/scriptify/http/script/function/data/OutputType.java +++ b/http/src/main/java/org/densy/scriptify/http/script/function/data/OutputType.java @@ -1,6 +1,8 @@ package org.densy.scriptify.http.script.function.data; +import org.densy.scriptify.api.script.module.export.access.ScriptAccess; + public enum OutputType { - STRING, - BYTES + @ScriptAccess.Export STRING, + @ScriptAccess.Export BYTES } diff --git a/script-js-graalvm/src/main/java/org/densy/scriptify/js/graalvm/script/JsScript.java b/script-js-graalvm/src/main/java/org/densy/scriptify/js/graalvm/script/JsScript.java index f9c0d99..789ae64 100644 --- a/script-js-graalvm/src/main/java/org/densy/scriptify/js/graalvm/script/JsScript.java +++ b/script-js-graalvm/src/main/java/org/densy/scriptify/js/graalvm/script/JsScript.java @@ -10,6 +10,7 @@ import org.densy.scriptify.api.script.function.ScriptFunctionManager; import org.densy.scriptify.api.script.function.definition.ScriptFunctionDefinition; import org.densy.scriptify.api.script.module.ScriptModuleManager; +import org.densy.scriptify.api.script.module.export.access.ScriptAccess; import org.densy.scriptify.api.script.module.export.resolver.ScriptModuleExportResolver; import org.densy.scriptify.api.script.security.ScriptSecurityManager; import org.densy.scriptify.core.script.constant.StandardConstantManager; @@ -89,7 +90,10 @@ public CompiledScript compile(String script) throws ScriptException { }; Context.Builder builder = Context.newBuilder("js") - .allowHostAccess(HostAccess.newBuilder(HostAccess.ALL) + .allowHostAccess(HostAccess.newBuilder(switch (moduleManager.getScriptAccess()) { + case ALL -> HostAccess.ALL; + case EXPLICIT -> HostAccess.EXPLICIT; + }) // Mapping for the ScriptObject class required // to convert a ScriptObject to the value it contains .targetTypeMapping( @@ -98,6 +102,8 @@ public CompiledScript compile(String script) throws ScriptException { object -> true, ScriptObject::getValue ) + .allowAccessAnnotatedBy(ScriptAccess.Export.class) + .allowImplementationsAnnotatedBy(ScriptAccess.Export.class) .build()) .allowIO(IOAccess.newBuilder() .fileSystem(new VirtualModuleFileSystem( diff --git a/script-js-graalvm/src/main/java/org/densy/scriptify/js/graalvm/script/module/GraalModuleManager.java b/script-js-graalvm/src/main/java/org/densy/scriptify/js/graalvm/script/module/GraalModuleManager.java index f990ea8..281afa5 100644 --- a/script-js-graalvm/src/main/java/org/densy/scriptify/js/graalvm/script/module/GraalModuleManager.java +++ b/script-js-graalvm/src/main/java/org/densy/scriptify/js/graalvm/script/module/GraalModuleManager.java @@ -5,6 +5,7 @@ import org.densy.scriptify.api.script.module.ScriptModule; import org.densy.scriptify.api.script.module.ScriptModuleManager; import org.densy.scriptify.api.script.module.export.ScriptExport; +import org.densy.scriptify.api.script.module.export.access.ScriptAccess; import org.densy.scriptify.api.script.module.export.resolver.ScriptModuleExportResolver; import org.densy.scriptify.api.script.module.export.resolver.ScriptModuleExportResolverFactory; import org.densy.scriptify.core.script.module.ScriptInternalGlobalModule; @@ -21,6 +22,7 @@ public class GraalModuleManager implements ScriptModuleManager { private final ScriptInternalGlobalModule globalModule = new ScriptInternalGlobalModule(); private final Map modules = new LinkedHashMap<>(); private ScriptModuleExportResolverFactory moduleExportResolverFactory; + private ScriptAccess scriptAccess = ScriptAccess.ALL; public GraalModuleManager(Script script) { this.setModuleExportResolver(new GraalModuleExportResolverFactory(script)); @@ -36,6 +38,16 @@ public void setModuleExportResolver(ScriptModuleExportResolverFactory moduleExpo this.moduleExportResolverFactory = Objects.requireNonNull(moduleExportResolverFactory, "moduleExportResolverFactory cannot be null"); } + @Override + public ScriptAccess getScriptAccess() { + return scriptAccess; + } + + @Override + public void setScriptAccess(ScriptAccess scriptAccess) { + this.scriptAccess = Objects.requireNonNull(scriptAccess, "scriptAccess cannot be null");; + } + @Override public ScriptInternalGlobalModule getGlobalModule() { return globalModule;