diff --git a/backend/scripts/build b/backend/scripts/build index 98174a5c1..bfb5ec475 100755 --- a/backend/scripts/build +++ b/backend/scripts/build @@ -13,9 +13,9 @@ cp ../CHANGES.md target/classes/changelog.md; clojure -T:build jar; mv target/penpot.jar target/dist/penpot.jar cp scripts/run.template.sh target/dist/run.sh; -cp scripts/manage.template.sh target/dist/manage.sh; +cp scripts/manage.py target/dist/manage.py chmod +x target/dist/run.sh; -chmod +x target/dist/manage.sh; +chmod +x target/dist/manage.py # Prefetch bb ./scripts/prefetch-templates.clj resources/app/onboarding.edn builtin-templates/ diff --git a/backend/scripts/manage.py b/backend/scripts/manage.py new file mode 100755 index 000000000..fd78d1a91 --- /dev/null +++ b/backend/scripts/manage.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# Copyright (c) KALEIDOS INC + +import argparse +import json +import socket +import sys + +from getpass import getpass +from urllib.parse import urlparse + +PREPL_URI = "tcp://localhost:6063" + +def get_prepl_conninfo(): + uri_data = urlparse(PREPL_URI) + if uri_data.scheme != "tcp": + raise RuntimeException(f"invalid PREPL_URI: {PREPL_URI}") + + if not isinstance(uri_data.netloc, str): + raise RuntimeException(f"invalid PREPL_URI: {PREPL_URI}") + + host, port = uri_data.netloc.split(":", 2) + + if port is None: + port = 6063 + + if isinstance(port, str): + port = int(port) + + return host, port + +def send_eval(expr): + host, port = get_prepl_conninfo() + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.connect((host, port)) + s.send(expr.encode("utf-8")) + s.send(b":repl/quit\n\n") + + with s.makefile() as f: + result = json.load(f) + tag = result.get("tag", None) + if tag != "ret": + raise RuntimeException("unexpected response from PREPL") + return result.get("val", None), result.get("exception", None) + +def encode(val): + return json.dumps(json.dumps(val)) + +def print_error(res): + for error in res["via"]: + print("ERR:", error["message"]) + break + +def run_cmd(params): + expr = "(app.srepl.ext/run-json-cmd {})".format(encode(params)) + res, failed = send_eval(expr) + if failed: + print_error(res) + sys.exit(-1) + + return res + +def create_profile(fullname, email, password): + params = { + "cmd": "create-profile", + "params": { + "fullname": fullname, + "email": email, + "password": password + } + } + + res = run_cmd(params) + print(f"Created: {res['email']} / {res['id']}") + +def update_profile(email, fullname, password, is_active): + params = { + "cmd": "update-profile", + "params": { + "email": email, + "fullname": fullname, + "password": password, + "is_active": is_active + } + } + + res = run_cmd(params) + if res is True: + print(f"Updated") + else: + print(f"No profile found with email {email}") + +def derive_password(password): + params = { + "cmd": "derive-password", + "params": { + "password": password, + } + } + + res = run_cmd(params) + print(f"Derived password: \"{res}\"") + +available_commands = [ + "create-profile", + "update-profile", + "derive-password" +] + +parser = argparse.ArgumentParser( + description=( + "Penpot Command Line Interface (CLI)" + ) +) + +parser.add_argument("-V", "--version", action="version", version="Penpot CLI %%develop%%") +parser.add_argument("action", action="store", choices=available_commands) +parser.add_argument("-n", "--fullname", help="Fullname", action="store") +parser.add_argument("-e", "--email", help="Email", action="store") +parser.add_argument("-p", "--password", help="Password", action="store") +parser.add_argument("-c", "--connect", help="Connect to PREPL", action="store", default="tcp://localhost:6063") + +args = parser.parse_args() + +PREPL_URI = args.connect + +if args.action == "create-profile": + email = args.email + password = args.password + fullname = args.fullname + + if email is None: + email = input("Email: ") + + if fullname is None: + fullname = input("Fullname: ") + + if password is None: + password = getpass("Password: ") + + create_profile(fullname, email, password) + +elif args.action == "update-profile": + email = args.email + password = args.password + + if email is None: + email = input("Email: ") + + if password is None: + password = getpass("Password: ") + + update_profile(email, None, password, None) + +elif args.action == "derive-password": + password = args.password + + if password is None: + password = getpass("Password: ") + + derive_password(password) diff --git a/backend/scripts/manage.template.sh b/backend/scripts/manage.template.sh deleted file mode 100644 index f3469f597..000000000 --- a/backend/scripts/manage.template.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash -set +e -JAVA_CMD=$(type -p java) - -set -e -if [[ ! -n "$JAVA_CMD" ]]; then - if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then - JAVA_CMD="$JAVA_HOME/bin/java" - else - >&2 echo "Couldn't find 'java'. Please set JAVA_HOME." - exit 1 - fi -fi - -if [ -f ./environ ]; then - source ./environ -fi - -exec $JAVA_CMD $JVM_OPTS -jar penpot.jar -m app.cli.manage "$@" diff --git a/docker/images/Dockerfile.backend b/docker/images/Dockerfile.backend index c34ec98c5..7a7102332 100644 --- a/docker/images/Dockerfile.backend +++ b/docker/images/Dockerfile.backend @@ -74,6 +74,7 @@ RUN set -ex; \ fontconfig \ woff-tools \ woff2 \ + python3 \ fontforge \ ; \ echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen; \