Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new: post /_admin/execute #309

Merged
merged 5 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions arango/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
ServerEchoError,
ServerEncryptionError,
ServerEngineError,
ServerExecuteError,
ServerLicenseGetError,
ServerLicenseSetError,
ServerLogLevelError,
Expand Down Expand Up @@ -227,6 +228,36 @@ def response_handler(resp: Response) -> Json:

return self._execute(request, response_handler)

def execute(self, command: str) -> Result[Any]:
"""Execute raw Javascript command on the server.

Executes the JavaScript code in the body on the server as
the body of a function with no arguments. If you have a
return statement then the return value you produce will be returned
as 'application/json'.

NOTE: this method endpoint will only be usable if the server
was started with the option `--javascript.allow-admin-execute true`.
The default value of this option is false, which disables the execution
of user-defined code and disables this API endpoint entirely.
This is also the recommended setting for production.

:param command: Javascript command to execute.
:type command: str
:return: Return value of **command**, if any.
:rtype: Any
:raise arango.exceptions.ServerExecuteError: If execution fails.
"""
request = Request(method="post", endpoint="/_admin/execute", data=command)

def response_handler(resp: Response) -> Any:
if not resp.is_success:
raise ServerExecuteError(resp, request)

return resp.body

return self._execute(request, response_handler)

def execute_transaction(
self,
command: str,
Expand Down
4 changes: 4 additions & 0 deletions arango/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,10 @@ class ServerEncryptionError(ArangoServerError):
"""Failed to reload user-defined encryption keys."""


class ServerExecuteError(ArangoServerError):
"""Failed to execute raw JavaScript command."""


#####################
# Task Exceptions #
#####################
Expand Down
16 changes: 9 additions & 7 deletions arango/replication.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,15 @@ def response_handler(resp: Response) -> Json:
if resp.is_success:
result = format_replication_header(resp.headers)
result["content"] = [
[
self._conn.deserialize(line)
for line in resp.body.split("\n")
if line
]
if deserialize
else resp.body
(
[
self._conn.deserialize(line)
for line in resp.body.split("\n")
if line
]
if deserialize
else resp.body
)
]
return result

Expand Down
1 change: 1 addition & 0 deletions tests/static/cluster-3.10.conf
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ jwt-secret = /tests/static/keyfile
[args]
all.database.password = passwd
all.log.api-enabled = true
all.javascript.allow-admin-execute = true
1 change: 1 addition & 0 deletions tests/static/cluster.conf
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ jwt-secret = /tests/static/keyfile
all.database.password = passwd
all.database.extended-names = true
all.log.api-enabled = true
all.javascript.allow-admin-execute = true
1 change: 1 addition & 0 deletions tests/static/single-3.10.conf
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ jwt-secret = /tests/static/keyfile

[args]
all.database.password = passwd
all.javascript.allow-admin-execute = true
1 change: 1 addition & 0 deletions tests/static/single.conf
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ jwt-secret = /tests/static/keyfile
[args]
all.database.password = passwd
all.database.extended-names = true
all.javascript.allow-admin-execute = true
6 changes: 6 additions & 0 deletions tests/test_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,12 @@ def test_database_misc_methods(client, sys_db, db, bad_db, cluster, secret):
bad_db.engine()
assert err.value.error_code in {11, 1228}

# Test execute JavaScript code
assert db.execute(1) is None
assert db.execute(None) == {"error": False, "code": 200}
assert db.execute("") == {"error": False, "code": 200}
assert db.execute("return 1") == 1

# Test database compact
with assert_raises(DatabaseCompactError) as err:
db.compact()
Expand Down
Loading