From 24a56487662e1ce99ebb4ad883a2750a354dd3b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Tue, 3 Sep 2024 11:37:12 +0200 Subject: [PATCH 01/10] [add] role:postgresql-for-wiki_js [add] role:authelia-for-wiki_js [add] role:wiki_js [add] role:wiki_js-and-nginx --- roles/authelia-for-wiki_js/defaults/main.json | 6 + roles/authelia-for-wiki_js/info.md | 9 ++ roles/authelia-for-wiki_js/tasks/main.json | 25 ++++ .../templates/authelia-client-conf.json.j2 | 17 +++ .../postgresql-for-wiki_js/defaults/main.json | 5 + roles/postgresql-for-wiki_js/tasks/main.json | 49 ++++++++ roles/wiki_js-and-nginx/defaults/main.json | 5 + roles/wiki_js-and-nginx/info.md | 3 + roles/wiki_js-and-nginx/tasks/main.json | 35 ++++++ roles/wiki_js-and-nginx/templates/conf.j2 | 33 ++++++ roles/wiki_js-and-nginx/vardef.json | 19 +++ roles/wiki_js/data.json | 11 ++ roles/wiki_js/defaults/main.json | 23 ++++ roles/wiki_js/info.md | 9 ++ roles/wiki_js/tasks/main.json | 112 ++++++++++++++++++ roles/wiki_js/templates/config.yml.j2 | 49 ++++++++ roles/wiki_js/templates/systemd-unit.j2 | 14 +++ roles/wiki_js/vardef.json | 106 +++++++++++++++++ 18 files changed, 530 insertions(+) create mode 100644 roles/authelia-for-wiki_js/defaults/main.json create mode 100644 roles/authelia-for-wiki_js/info.md create mode 100644 roles/authelia-for-wiki_js/tasks/main.json create mode 100644 roles/authelia-for-wiki_js/templates/authelia-client-conf.json.j2 create mode 100644 roles/postgresql-for-wiki_js/defaults/main.json create mode 100644 roles/postgresql-for-wiki_js/tasks/main.json create mode 100644 roles/wiki_js-and-nginx/defaults/main.json create mode 100644 roles/wiki_js-and-nginx/info.md create mode 100644 roles/wiki_js-and-nginx/tasks/main.json create mode 100644 roles/wiki_js-and-nginx/templates/conf.j2 create mode 100644 roles/wiki_js-and-nginx/vardef.json create mode 100644 roles/wiki_js/data.json create mode 100644 roles/wiki_js/defaults/main.json create mode 100644 roles/wiki_js/info.md create mode 100644 roles/wiki_js/tasks/main.json create mode 100644 roles/wiki_js/templates/config.yml.j2 create mode 100644 roles/wiki_js/templates/systemd-unit.j2 create mode 100644 roles/wiki_js/vardef.json diff --git a/roles/authelia-for-wiki_js/defaults/main.json b/roles/authelia-for-wiki_js/defaults/main.json new file mode 100644 index 0000000..adb7105 --- /dev/null +++ b/roles/authelia-for-wiki_js/defaults/main.json @@ -0,0 +1,6 @@ +{ + "var_authelia_for_wiki_js_wiki_js_url_base": "https://wiki_js.example.org", + "var_authelia_for_wiki_js_client_id": "wiki_js", + "var_authelia_for_wiki_js_client_secret": "REPLACE_ME", + "var_authelia_for_wiki_js_uuid": "REPLACE_ME", +} diff --git a/roles/authelia-for-wiki_js/info.md b/roles/authelia-for-wiki_js/info.md new file mode 100644 index 0000000..43e5da8 --- /dev/null +++ b/roles/authelia-for-wiki_js/info.md @@ -0,0 +1,9 @@ +## Beschreibung + +Um [Wiki.js](../wiki.js) gegen [Authelia](../authelia) authentifizieren zu lassen + + +## Verweise + +[Wiki.js-Dokumentation | Authentication](https://docs.requarks.io/auth) +[Authelia-Dokumentation | Wiki.js Integration](https://www.authelia.com/integration/openid-connect/wikijs/) diff --git a/roles/authelia-for-wiki_js/tasks/main.json b/roles/authelia-for-wiki_js/tasks/main.json new file mode 100644 index 0000000..185f052 --- /dev/null +++ b/roles/authelia-for-wiki_js/tasks/main.json @@ -0,0 +1,25 @@ +[ + { + "name": "configuration | emplace", + "become": true, + "ansible.builtin.template": { + "src": "authelia-client-conf.json.j2", + "dest": "/etc/authelia/conf.d/clients/wiki_js.json" + } + }, + { + "name": "configuration | apply", + "become": true, + "ansible.builtin.command": { + "cmd": "/usr/bin/authelia-conf-compose" + } + }, + { + "name": "restart service", + "become": true, + "ansible.builtin.systemd_service": { + "state": "restarted", + "name": "authelia" + } + } +] diff --git a/roles/authelia-for-wiki_js/templates/authelia-client-conf.json.j2 b/roles/authelia-for-wiki_js/templates/authelia-client-conf.json.j2 new file mode 100644 index 0000000..2bdc8e6 --- /dev/null +++ b/roles/authelia-for-wiki_js/templates/authelia-client-conf.json.j2 @@ -0,0 +1,17 @@ +{ + "client_id": "{{var_authelia_for_wiki_js_client_id}}", + "client_secret": "{{var_authelia_for_wiki_js_client_secret}}", + "client_name": "Wiki.js", + "public": false, + "authorization_policy": "one_factor", + "redirect_uris": [ + "{{var_authelia_for_wiki_js_wiki_js_url_base}}/login/{{var_authelia_for_wiki_js_uuid}}/calback" + ], + "scopes": [ + "openid", + "email", + "profile" + ], + "userinfo_signed_response_alg": "none", + "token_endpoint_auth_method": "client_secret_basic" +} diff --git a/roles/postgresql-for-wiki_js/defaults/main.json b/roles/postgresql-for-wiki_js/defaults/main.json new file mode 100644 index 0000000..b227a2e --- /dev/null +++ b/roles/postgresql-for-wiki_js/defaults/main.json @@ -0,0 +1,5 @@ +{ + "var_postgresql_for_wiki_js_username": "wiki_js_user", + "var_postgresql_for_wiki_js_password": "REPLACE_ME", + "var_postgresql_for_wiki_js_schema": "wiki_js" +} diff --git a/roles/postgresql-for-wiki_js/tasks/main.json b/roles/postgresql-for-wiki_js/tasks/main.json new file mode 100644 index 0000000..c8aafea --- /dev/null +++ b/roles/postgresql-for-wiki_js/tasks/main.json @@ -0,0 +1,49 @@ +[ + { + "name": "packages", + "become": true, + "ansible.builtin.apt": { + "update_cache": true, + "pkg": [ + "acl", + "python3-psycopg2" + ] + } + }, + { + "name": "user", + "become": true, + "become_user": "postgres", + "community.postgresql.postgresql_user": { + "state": "present", + "name": "{{var_postgresql_for_wiki_js_username}}", + "password": "{{var_postgresql_for_wiki_js_password}}" + }, + "environment": { + "PGOPTIONS": "-c password_encryption=scram-sha-256" + } + }, + { + "name": "schema", + "become": true, + "become_user": "postgres", + "community.postgresql.postgresql_db": { + "state": "present", + "name": "{{var_postgresql_for_wiki_js_schema}}", + "owner": "{{var_postgresql_for_wiki_js_username}}" + } + }, + { + "name": "rights", + "become": true, + "become_user": "postgres", + "community.postgresql.postgresql_privs": { + "state": "present", + "db": "{{var_postgresql_for_wiki_js_schema}}", + "objs": "ALL_IN_SCHEMA", + "roles": "{{var_postgresql_for_wiki_js_username}}", + "privs": "ALL", + "grant_option": true + } + } +] diff --git a/roles/wiki_js-and-nginx/defaults/main.json b/roles/wiki_js-and-nginx/defaults/main.json new file mode 100644 index 0000000..654de80 --- /dev/null +++ b/roles/wiki_js-and-nginx/defaults/main.json @@ -0,0 +1,5 @@ +{ + "var_vikunja_and_nginx_domain": "vikunja.example.org", + "var_wiki_js_and_nginx_internal_port": 5632, + "var_vikunja_and_nginx_tls_mode": "force" +} diff --git a/roles/wiki_js-and-nginx/info.md b/roles/wiki_js-and-nginx/info.md new file mode 100644 index 0000000..3e54803 --- /dev/null +++ b/roles/wiki_js-and-nginx/info.md @@ -0,0 +1,3 @@ +## Verweise + +- [Wiki.js-Dokumentation | Web Server](https://docs.requarks.io/en/install/requirements#web-server) diff --git a/roles/wiki_js-and-nginx/tasks/main.json b/roles/wiki_js-and-nginx/tasks/main.json new file mode 100644 index 0000000..d12f711 --- /dev/null +++ b/roles/wiki_js-and-nginx/tasks/main.json @@ -0,0 +1,35 @@ +[ + { + "name": "deactivate default site", + "become": true, + "ansible.builtin.file": { + "state": "absent", + "dest": "/etc/nginx/sites-enabled/default" + } + }, + { + "name": "emplace configuration | data", + "become": true, + "ansible.builtin.template": { + "src": "conf.j2", + "dest": "/etc/nginx/sites-available/{{var_wiki_js_and_nginx_domain}}" + } + }, + { + "name": "emplace configuration | link", + "become": true, + "ansible.builtin.file": { + "state": "link", + "src": "/etc/nginx/sites-available/{{var_wiki_js_and_nginx_domain}}", + "dest": "/etc/nginx/sites-enabled/{{var_wiki_js_and_nginx_domain}}" + } + }, + { + "name": "restart nginx", + "become": true, + "ansible.builtin.systemd_service": { + "state": "restarted", + "name": "nginx" + } + } +] diff --git a/roles/wiki_js-and-nginx/templates/conf.j2 b/roles/wiki_js-and-nginx/templates/conf.j2 new file mode 100644 index 0000000..186cc05 --- /dev/null +++ b/roles/wiki_js-and-nginx/templates/conf.j2 @@ -0,0 +1,33 @@ +{% macro wiki_js_common() %} + location / { + proxy_pass http://localhost:{{var_wiki_js_and_nginx_internal_port | string}}; + } +{% endmacro %} + +server { + server_name {{var_wiki_js_and_nginx_domain}}; + + listen 80; + listen [::]:80; + +{% if (var_wiki_js_and_nginx_tls_mode == 'force') %} + return 301 https://$http_host$request_uri; +{% else %} +{{ wiki_js_common() }} +{% endif %} +} + +{% if (var_wiki_js_and_nginx_tls_mode != 'disable') %} +server { + server_name {{var_wiki_js_and_nginx_domain}}; + + listen 443 ssl http2; + listen [::]:443 ssl http2; + + ssl_certificate_key /etc/ssl/private/{{var_wiki_js_and_nginx_domain}}.pem; + ssl_certificate /etc/ssl/fullchains/{{var_wiki_js_and_nginx_domain}}.pem; + include /etc/nginx/ssl-hardening.conf; + +{{ wiki_js_common() }} +} +{% endif %} diff --git a/roles/wiki_js-and-nginx/vardef.json b/roles/wiki_js-and-nginx/vardef.json new file mode 100644 index 0000000..81b266d --- /dev/null +++ b/roles/wiki_js-and-nginx/vardef.json @@ -0,0 +1,19 @@ +{ + "domain": { + "type": "string", + "mandatory": false + }, + "internal_port": { + "type": "integer", + "mandatory": false + }, + "tls_mode": { + "type": "string", + "options": [ + "disable", + "enable", + "force" + ], + "mandatory": false + } +} diff --git a/roles/wiki_js/data.json b/roles/wiki_js/data.json new file mode 100644 index 0000000..1ffd054 --- /dev/null +++ b/roles/wiki_js/data.json @@ -0,0 +1,11 @@ +{ + "key": "{{var_wiki_js_authentication_data_uuid}}", + "isEnabled": true, + "config": "{\"clientId\":\"{{var_wiki_js_authentication_data_authelia_client_id}}\",\"clientSecret\":\"{{var_wiki_js_authentication_data_authelia_client_secret}}\",\"authorizationURL\":\"{{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/authorization\",\"tokenURL\":\"{{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/token\",\"userInfoURL\":\"{{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/userinfo\",\"userIdClaim\":\"id\",\"displayNameClaim\":\"name\",\"emailClaim\":\"email\",\"mapGroups\":false,\"groupsClaim\":\"groups\",\"logoutURL\":\"\",\"scope\":\"openid profile email\",\"useQueryStringForAccessToken\":false,\"enableCSRFProtection\":true}", + "selfRegistration": true, + "domainWhitelist": "{\"v\":[]}", + "autoEnrollGroups": "{\"v\":[]}", + "order": 1, + "strategyKey": "oauth2", + "displayName": "{{var_wiki_js_authentication_data_authelia_provider_name}}" +} diff --git a/roles/wiki_js/defaults/main.json b/roles/wiki_js/defaults/main.json new file mode 100644 index 0000000..88216bd --- /dev/null +++ b/roles/wiki_js/defaults/main.json @@ -0,0 +1,23 @@ +{ + "var_wiki_js_port": 5632, + "var_wiki_js_distributed": false, + "var_wiki_js_user": "wiki_js", + "var_wiki_js_directory": "/opt/wiki_js", + "var_wiki_js_data_path": "/var/wiki_js/data", + "var_wiki_js_log_level": "info", + "var_wiki_js_log_format": "default", + "var_wiki_js_database_kind": "sqlite", + "var_wiki_js_database_data_sqlite_path": "/var/wiki.js/data.sqlite", + "var_wiki_js_database_data_postgresql_host": "postgresql.example.org", + "var_wiki_js_database_data_postgresql_port": 5432, + "var_wiki_js_database_data_postgresql_username": "wiki_js_user", + "var_wiki_js_database_data_postgresql_password": "REPLACE_ME", + "var_wiki_js_database_data_postgresql_schema": "wiki_js", + "var_wiki_js_authentication_kind": "internal", + "var_wiki_js_authentication_data_authelia_provider_id": "authelia", + "var_wiki_js_authentication_data_authelia_provider_name": "Authelia", + "var_wiki_js_authentication_data_authelia_client_id": "wiki_js", + "var_wiki_js_authentication_data_authelia_client_secret": "REPLACE_ME", + "var_wiki_js_authentication_data_authelia_url_base": "https://authelia.example.org", + "var_wiki_js_authentication_data_uuid": "REPLACE_ME", +} diff --git a/roles/wiki_js/info.md b/roles/wiki_js/info.md new file mode 100644 index 0000000..424f86a --- /dev/null +++ b/roles/wiki_js/info.md @@ -0,0 +1,9 @@ +## Beschreibung + +- Einrichtung der Aufgaben-Verwaltung [Wiki.js](https://js.wiki/) + + +## Verweise + +- [Wiki.js-Dokumentation | Linux-Installation](https://docs.requarks.io/install/linux) +- [Wiki.js-Dokumentation | Konfiguration](https://docs.requarks.io/install/config) diff --git a/roles/wiki_js/tasks/main.json b/roles/wiki_js/tasks/main.json new file mode 100644 index 0000000..2271dc3 --- /dev/null +++ b/roles/wiki_js/tasks/main.json @@ -0,0 +1,112 @@ +[ + { + "name": "packages", + "become": true, + "ansible.builtin.apt": { + "update_cache": true, + "pkg": [ + "npm" + ] + } + }, + { + "name": "user", + "become": true, + "ansible.builtin.user": { + "name": "{{var_wiki_js_user}}", + "create_home": true, + "home": "{{var_wiki_js_directory}}" + } + }, + { + "name": "directories", + "become": true, + "loop": [ + "{{var_wiki_js_data_path}}", + ], + "ansible.builtin.file": { + "owner": "{{var_wiki_js_user}}", + "state": "directory", + "path": "{{item}}" + } + }, + { + "name": "download", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.get_url": { + "url": "https://github.com/Requarks/wiki/releases/latest/download/wiki-js.tar.gz", + "dest": "/tmp/wiki_js.zip" + } + }, + { + "name": "unpack", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.unarchive": { + "remote_src": true, + "src": "/tmp/wiki_js.zip", + "dest": "{{var_wiki_js_directory}}" + } + }, + { + "name": "database | sqlite | dirctory", + "when": "var_wiki_js_database_kind == 'sqlite'", + "become": true, + "ansible.builtin.file": { + "path": "{{var_wiki_js_database_data_sqlite_path | dirname}}", + "state": "directory", + "owner": "{{var_wiki_js_user}}" + } + }, + { + "name": "database | sqlite | file", + "when": "var_wiki_js_database_kind == 'sqlite'", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.file": { + "path": "{{var_wiki_js_database_data_sqlite_path}}", + "state": "touch" + } + }, + { + "name": "database | sqlite | setup", + "when": "var_wiki_js_database_kind == 'sqlite'", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.command": { + "chdir": "{{var_wiki_js_directory}}", + "cmd": "npm rebuild sqlite3" + } + }, + { + "name": "conf | base", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.template": { + "src": "config.yml.j2", + "dest": "{{var_wiki_js_directory}}/config.yml" + } + }, + { + "name": "conf | authentication | authelia", + "when": "var_wiki_js_authentication_kind == 'authelia'", + }, + { + "name": "systemd-unit", + "become": true, + "ansible.builtin.template": { + "src": "systemd-unit.j2", + "dest": "/etc/systemd/system/wiki_js.service" + } + }, + { + "name": "apply", + "become": true, + "ansible.builtin.systemd_service": { + "state": "restarted", + "enabled": true, + "name": "wiki_js" + } + } +] diff --git a/roles/wiki_js/templates/config.yml.j2 b/roles/wiki_js/templates/config.yml.j2 new file mode 100644 index 0000000..b52747a --- /dev/null +++ b/roles/wiki_js/templates/config.yml.j2 @@ -0,0 +1,49 @@ +port: {{var_wiki_js_port | string}} + +{% if var_wiki_js_database_kind == 'sqlite' %} +db: + type: sqlite + storage: {{var_wiki_js_database_data_sqlite_path}} +{% endif %} + +{% if var_wiki_js_database_kind == 'postgresql' %} +db: + type: postgres + host: {{var_wiki_js_database_data_postgresql_host}} + port: {{var_wiki_js_database_data_postgresql_port | to_yaml}} + user: {{var_wiki_js_database_data_postgresql_username}} + pass: {{var_wiki_js_database_data_postgresql_password}} + db: {{var_wiki_js_database_data_postgresql_schema}} + ssl: false + # schema: public +{% endif %} + +ssl: + enabled: false + port: 3443 + + # Provider to use, possible values: custom, letsencrypt + provider: custom + + format: pem + key: path/to/key.pem + cert: path/to/cert.pem + pfx: path/to/cert.pfx + passphrase: null + dhparam: null + + domain: wiki.yourdomain.com + subscriberEmail: admin@example.com + +bindIP: 0.0.0.0 + +logLevel: {{var_wiki_js_log_level}} +logFormat: {{var_wiki_js_log_format}} + +offline: false + +ha: {{var_wiki_js_distributed | to_yaml}} + +dataPath: {{var_wiki_js_data_path}} + +bodyParserLimit: 5mb diff --git a/roles/wiki_js/templates/systemd-unit.j2 b/roles/wiki_js/templates/systemd-unit.j2 new file mode 100644 index 0000000..3d6433a --- /dev/null +++ b/roles/wiki_js/templates/systemd-unit.j2 @@ -0,0 +1,14 @@ +[Unit] +Description=Wiki.js +After=network.target + +[Service] +Type=simple +ExecStart=/usr/bin/node server +Restart=always +User={{var_wiki_js_user}} +Environment=NODE_ENV=production +WorkingDirectory={{var_wiki_js_directory}} + +[Install] +WantedBy=multi-user.target diff --git a/roles/wiki_js/vardef.json b/roles/wiki_js/vardef.json new file mode 100644 index 0000000..61ecd9b --- /dev/null +++ b/roles/wiki_js/vardef.json @@ -0,0 +1,106 @@ +{ + "port": { + "mandatory": false, + "type": "integer" + }, + "distributed": { + "mandatory": false, + "type": "boolean" + }, + "user": { + "mandatory": false, + "type": "string" + }, + "directory": { + "mandatory": false, + "type": "string" + }, + "log_level": { + "mandatory": false, + "type": "string", + "options": [ + "error", + "warn", + "info", + "verbose", + "debug", + "silly" + ] + }, + "log_format": { + "mandatory": false, + "type": "string", + "options": [ + "default", + "json" + ] + }, + "data_path": { + "mandatory": false, + "type": "string" + }, + "database_kind": { + "mandatory": false, + "type": "string", + "options": [ + "sqlite", + "postgresql" + ] + }, + "database_data_sqlite_path": { + "mandatory": false, + "type": "string" + }, + "database_data_postgresql_host": { + "mandatory": false, + "type": "string" + }, + "database_data_postgresql_port": { + "mandatory": false, + "type": "integer" + }, + "database_data_postgresql_username": { + "mandatory": false, + "type": "string" + }, + "database_data_postgresql_password": { + "mandatory": false, + "type": "string" + }, + "database_data_postgresql_schema": { + "mandatory": false, + "type": "string" + }, + "authentication_kind": { + "mandatory": false, + "type": "string", + "options": [ + "internal", + "authelia" + ] + }, + "authentication_data_authelia_provider_id": { + "type": "string", + "mandatory": false + }, + "authentication_data_authelia_provider_name": { + "type": "string", + "mandatory": false + }, + "authentication_data_authelia_client_id": { + "type": "string", + "mandatory": false + }, + "authentication_data_authelia_client_secret": { + "type": "string", + "mandatory": false + }, + "authentication_data_authelia_url_base": { + "type": "string", + "mandatory": false + }, + "authentication_data_authelia_uuid": { + "type": "string", + "mandatory": false + }, +} From 8dc07a1bc56a06f3100cd8cae495639d54f0f18d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Wed, 4 Sep 2024 00:06:52 +0200 Subject: [PATCH 02/10] [mod] wiki_js roles --- roles/authelia-for-wiki_js/defaults/main.json | 2 +- roles/wiki_js/data.json | 11 - roles/wiki_js/defaults/main.json | 10 +- roles/wiki_js/files/cli.js | 951 ++++++++++++++++++ roles/wiki_js/info.md | 6 + roles/wiki_js/tasks/main.json | 46 +- roles/wiki_js/vardef.json | 38 +- 7 files changed, 1042 insertions(+), 22 deletions(-) delete mode 100644 roles/wiki_js/data.json create mode 100644 roles/wiki_js/files/cli.js diff --git a/roles/authelia-for-wiki_js/defaults/main.json b/roles/authelia-for-wiki_js/defaults/main.json index adb7105..98ccb23 100644 --- a/roles/authelia-for-wiki_js/defaults/main.json +++ b/roles/authelia-for-wiki_js/defaults/main.json @@ -2,5 +2,5 @@ "var_authelia_for_wiki_js_wiki_js_url_base": "https://wiki_js.example.org", "var_authelia_for_wiki_js_client_id": "wiki_js", "var_authelia_for_wiki_js_client_secret": "REPLACE_ME", - "var_authelia_for_wiki_js_uuid": "REPLACE_ME", + "var_authelia_for_wiki_js_uuid": "REPLACE_ME" } diff --git a/roles/wiki_js/data.json b/roles/wiki_js/data.json deleted file mode 100644 index 1ffd054..0000000 --- a/roles/wiki_js/data.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "key": "{{var_wiki_js_authentication_data_uuid}}", - "isEnabled": true, - "config": "{\"clientId\":\"{{var_wiki_js_authentication_data_authelia_client_id}}\",\"clientSecret\":\"{{var_wiki_js_authentication_data_authelia_client_secret}}\",\"authorizationURL\":\"{{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/authorization\",\"tokenURL\":\"{{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/token\",\"userInfoURL\":\"{{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/userinfo\",\"userIdClaim\":\"id\",\"displayNameClaim\":\"name\",\"emailClaim\":\"email\",\"mapGroups\":false,\"groupsClaim\":\"groups\",\"logoutURL\":\"\",\"scope\":\"openid profile email\",\"useQueryStringForAccessToken\":false,\"enableCSRFProtection\":true}", - "selfRegistration": true, - "domainWhitelist": "{\"v\":[]}", - "autoEnrollGroups": "{\"v\":[]}", - "order": 1, - "strategyKey": "oauth2", - "displayName": "{{var_wiki_js_authentication_data_authelia_provider_name}}" -} diff --git a/roles/wiki_js/defaults/main.json b/roles/wiki_js/defaults/main.json index 88216bd..d26205a 100644 --- a/roles/wiki_js/defaults/main.json +++ b/roles/wiki_js/defaults/main.json @@ -1,6 +1,7 @@ { "var_wiki_js_port": 5632, "var_wiki_js_distributed": false, + "var_wiki_js_domain": "wiki-js.example.org", "var_wiki_js_user": "wiki_js", "var_wiki_js_directory": "/opt/wiki_js", "var_wiki_js_data_path": "/var/wiki_js/data", @@ -19,5 +20,12 @@ "var_wiki_js_authentication_data_authelia_client_id": "wiki_js", "var_wiki_js_authentication_data_authelia_client_secret": "REPLACE_ME", "var_wiki_js_authentication_data_authelia_url_base": "https://authelia.example.org", - "var_wiki_js_authentication_data_uuid": "REPLACE_ME", + "var_wiki_js_smtp_host": "smtp.example.org", + "var_wiki_js_smtp_port": 465, + "var_wiki_js_smtp_username": "REPLACE_ME", + "var_wiki_js_smtp_password": "REPLACE_ME", + "email_sending_sender_name": "Wiki.js", + "email_sending_sender_email_address": "wiki-js@example.org", + "var_wiki_js_admin_email_address": "wiki-js-admin@example.org", + "var_wiki_js_admin_password": "REPLACE_ME" } diff --git a/roles/wiki_js/files/cli.js b/roles/wiki_js/files/cli.js new file mode 100644 index 0000000..f488a2b --- /dev/null +++ b/roles/wiki_js/files/cli.js @@ -0,0 +1,951 @@ +#!/usr/bin/env node + + +var wiki_js; +wiki_js = (wiki_js || {}); +wiki_js.cli = (wiki_js.cli || {}); +wiki_js.cli.helpers = (wiki_js.cli.helpers || {}); +wiki_js.cli.helpers.string = (wiki_js.cli.helpers.string || {}); +(function (exports) { + + /** + */ + function coin( + template, + arguments_ + ) + { + let result = template; + Object.entries(arguments_).forEach( + ([key, value]) => { + result = result.replace(new RegExp("{{" + key + "}}", "g"), value); + } + ); + return result; + } + exports.coin = coin; + +}) (wiki_js.cli.helpers.string) + + +var wiki_js; +wiki_js = (wiki_js || {}); +wiki_js.cli = (wiki_js.cli || {}); +wiki_js.cli.helpers = (wiki_js.cli.helpers || {}); +wiki_js.cli.helpers.file = (wiki_js.cli.helpers.file || {}); +(function (exports) { + + /** + */ + function read( + path + ) + { + const nm_fs = require("fs"); + return ( + new Promise( + (resolve, reject) => { + nm_fs.readFile( + path, + { + }, + (err, data) => { + if (err) { + reject(err); + } + else { + resolve(data.toString()); + } + } + ); + } + ) + ); + } + exports.read = read; + +}) (wiki_js.cli.helpers.file) + + +var wiki_js; +wiki_js = (wiki_js || {}); +wiki_js.cli = (wiki_js.cli || {}); +wiki_js.cli.helpers = (wiki_js.cli.helpers || {}); +wiki_js.cli.helpers.http = (wiki_js.cli.helpers.http || {}); +(function (exports) { + + /** + */ + async function call( + http_request + ) + { + wiki_js.cli.helpers.log.write( + "debug", + "http_call_request", + http_request + ); + const fetch_request = new Request( + http_request.target, + { + "method": http_request.method, + "headers": http_request.headers, + "body": http_request.body, + } + ); + const fetch_response = await fetch(fetch_request); + const http_response = { + "status_code": fetch_response.status, + "headers": fetch_response.headers, + "body": await fetch_response.text(), + }; + wiki_js.cli.helpers.log.write( + "debug", + "http_call_response", + http_response + ); + return http_response; + } + exports.call = call; + +}) (wiki_js.cli.helpers.http) + + +var wiki_js; +wiki_js = (wiki_js || {}); +wiki_js.cli = (wiki_js.cli || {}); +wiki_js.cli.helpers.log = (wiki_js.cli.helpers.log || {}); +(function (exports) { + + /** + */ + const _level_order = [ + "debug", + "info", + "notice", + "warning", + "error", + ]; + + + /** + */ + var _threshold = "info"; + + + /** + */ + function setup( + threshold + ) + { + _threshold = threshold; + } + exports.setup = setup; + + + /** + */ + function write( + level, + incident, + details + ) + { + if (_level_order.indexOf(level) < _level_order.indexOf(_threshold)) { + // do nothing + } + else { + process.stderr.write( + wiki_js.cli.helpers.string.coin( + "\n<{{datetime}}> [{{level}}] {{incident}}\n{{details}}\n\n", + { + "datetime": (new Date()).toISOString(), + "level": level, + "incident": incident, + "details": JSON.stringify(details, undefined, "\t"), + } + ) + ); + } + } + exports.write = write; + +}) (wiki_js.cli.helpers.log); + + +var wiki_js; +wiki_js = (wiki_js || {}); +wiki_js.cli = (wiki_js.cli || {}); +wiki_js.cli.helpers.args = (wiki_js.cli.helpers.args || {}); +(function (exports) { + + /** + */ + function parse( + args_raw + ) + { + let result = { + "positional": [], + "volatile": {}, + }; + let state = "free"; + let key = null; + args_raw.forEach( + (arg_raw) => { + switch (state) { + case "free": { + if (arg_raw.startsWith("-")) { + key = arg_raw.slice(1); + state = "bound"; + } + else { + if (key === null) { + result.positional.push(arg_raw); + key = null; + state = "free"; + } + else { + wiki_js.cli.helpers.log.write( + "warning", + "arg_discarded", + { + "arg_raw": arg_raw, + } + ); + key = null; + state = "free"; + } + } + break; + } + case "bound": { + if (! (key in result["volatile"])) { + result["volatile"][key] = []; + } + else { + // do nothing + } + result["volatile"][key].push(arg_raw); + key = null; + state = "free"; + } + } + } + ); + return result; + } + exports.parse = parse; + +}) (wiki_js.cli.helpers.args); + + +var wiki_js; +wiki_js = (wiki_js || {}); +wiki_js.cli = (wiki_js.cli || {}); +wiki_js.cli.conf = (wiki_js.cli.conf || {}); +(function (exports) { + + /** + */ + var _data = null; + + + /** + */ + async function load( + path + ) + { + let data_raw; + if (path === null) { + data_raw = {}; + } + else { + const content = await wiki_js.cli.helpers.file.read(path); + data_raw = JSON.parse(content); + } + wiki_js.cli.helpers.log.write( + "debug", + "conf_raw", + data_raw + ); + _data = { + "api": { + "url_base": ( + data_raw?.api?.url_base + ?? + "http://localhost:3000" + ), + }, + "login": { + "username": ( + data_raw?.login?.username + ?? + "admin" + ), + "password": ( + data_raw?.login?.password + ?? + "admin" + ), + }, + "log": { + "threshold": ( + data_raw?.log?.threshold + ?? + "debug" + ), + } + }; + return Promise.resolve(undefined); + } + exports.load = load; + + + /** + */ + function set( + data + ) + { + _data = data; + } + exports.set = set; + + + /** + */ + function get( + ) + { + return _data; + } + exports.get = get; + +}) (wiki_js.cli.conf); + + +var wiki_js; +wiki_js = (wiki_js || {}); +wiki_js.cli = (wiki_js.cli || {}); +wiki_js.cli.api = (wiki_js.cli.api || {}); +(function (exports) { + + /** + */ + async function call_finalize( + admin_email, + admin_password, + site_url, + telemetry + ) + { + const http_request = { + "target": (wiki_js.cli.conf.get().api.url_base + "/finalize"), + "method": "POST", + "headers": { + "Content-Type": "application/json", + }, + "body": JSON.stringify( + { + "adminEmail": admin_email, + "adminPassword": admin_password, + "adminPasswordConfirm": admin_password, + "siteUrl": site_url, + "telemetry": telemetry, + } + ), + }; + http_response = await wiki_js.cli.helpers.http.call(http_request); + const data = JSON.parse(http_response.body); + return Promise.resolve(undefined); + } + exports.call_finalize = call_finalize; + + + /** + */ + async function call_generic_graphql( + graphql_query, + options + ) + { + options = Object.assign( + { + "login_token": null, + "variables": {}, + }, + options + ); + const http_request = { + "target": (wiki_js.cli.conf.get().api.url_base + "/graphql"), + "method": "POST", + "headers": Object.assign( + { + "Content-Type": "application/json", + }, + ( + (options.login_token === null) + ? + {} + : + {"Cookie": ("jwt=" + options.login_token)} + ) + ), + "body": JSON.stringify( + [ + { + "operationName": null, + "variables": options.variables, + "extensions": {}, + "query": graphql_query, + } + ] + ), + }; + http_response = await wiki_js.cli.helpers.http.call(http_request); + const data = JSON.parse(http_response.body); + return Promise.resolve(data[0]["data"]); + } + + + /** + * executes a local login and returns the JWT + */ + function call_login_local( + ) + { + wiki_js.cli.helpers.log.write( + "info", + "api_call_login_local", + { + } + ); + return ( + call_generic_graphql( + "mutation ($username: String!, $password: String!, $strategy: String!) {authentication {login(username: $username, password: $password, strategy: $strategy) {responseResult {succeeded errorCode slug message __typename} jwt mustChangePwd mustProvideTFA mustSetupTFA continuationToken redirect tfaQRImage __typename} __typename}}", + { + "variables": { + "strategy": "local", + "username": wiki_js.cli.conf.get().login.username, + "password": wiki_js.cli.conf.get().login.password, + } + } + ) + .then( + (data) => ( + data["authentication"]["login"]["responseResult"]["succeeded"] + ? + Promise.resolve(data["authentication"]["login"]["jwt"]) + : + Promise.reject(new Error("login failed")) + ) + ) + ); + } + exports.call_login_local = call_login_local; + + + /** + */ + function call_email_settings_set( + login_token, + settings + ) + { + wiki_js.cli.helpers.log.write( + "info", + "api_call_email_settings_set", + { + "settings": settings, + } + ); + return ( + call_generic_graphql( + "mutation ($senderName: String!, $senderEmail: String!, $host: String!, $port: Int!, $name: String!, $secure: Boolean!, $verifySSL: Boolean!, $user: String!, $pass: String!, $useDKIM: Boolean!, $dkimDomainName: String!, $dkimKeySelector: String!, $dkimPrivateKey: String!) {mail {updateConfig(senderName: $senderName, senderEmail: $senderEmail, host: $host, port: $port, name: $name, secure: $secure, verifySSL: $verifySSL, user: $user, pass: $pass, useDKIM: $useDKIM, dkimDomainName: $dkimDomainName, dkimKeySelector: $dkimKeySelector, dkimPrivateKey: $dkimPrivateKey) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", + { + "login_token": login_token, + "variables": { + "senderName": settings.sender_name, + "senderEmail": settings.sender_email_address, + "host": settings.smtp_host, + "port": settings.smtp_port, + "name": settings.name, + "secure": settings.secure, + "verifySSL": settings.verify_ssl, + "user": settings.smtp_username, + "pass": settings.smtp_password, + "useDKIM": settings.use_dkim, + "dkimDomainName": settings.dkim_domain_name, + "dkimKeySelector": settings.dkim_key_selector, + "dkimPrivateKey": settings.dkim_private_key, + } + } + ) + ); + } + exports.call_email_settings_set = call_email_settings_set; + + + /** + */ + function call_authentication_strategy_list( + login_token + ) + { + wiki_js.cli.helpers.log.write( + "info", + "api_call_authentication_strategy_list", + { + } + ); + return ( + call_generic_graphql( + "{authentication {activeStrategies {key strategy {key title description useForm logo website __typename} config {key value __typename} order isEnabled displayName selfRegistration domainWhitelist autoEnrollGroups __typename} __typename}}", + { + "login_token": login_token, + } + ) + .then( + (data) => Promise.resolve(data["authentication"]["activeStrategies"]) + ) + ); + } + exports.call_authentication_strategy_list = call_authentication_strategy_list; + + + /** + */ + function call_authentication_strategy_set( + login_token, + strategies + ) + { + wiki_js.cli.helpers.log.write( + "info", + "api_call_authentication_strategy_set", + { + "strategies": strategies, + } + ); + return ( + call_generic_graphql( + "mutation ($strategies: [AuthenticationStrategyInput]!) {authentication {updateStrategies(strategies: $strategies) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", + { + "login_token": login_token, + "variables": { + "strategies": strategies, + } + } + ) + ); + } + exports.call_authentication_strategy_set = call_authentication_strategy_set; + +}) (wiki_js.cli.api); + + +var wiki_js; +wiki_js = (wiki_js || {}); +wiki_js.cli = (wiki_js.cli || {}); +wiki_js.cli.logic = (wiki_js.cli.logic || {}); +(function (exports) { + + /** + */ + async function initialize( + admin_email_address, + admin_password, + options + ) + { + options = Object.assign( + { + "site_url": "http://localhost:3000", + "allow_telemetry": false, + }, + options + ); + const result = await wiki_js.cli.api.call_finalize( + admin_email_address, + admin_password, + options.site_url, + options.allow_telemetry + ); + return Promise.resolve(undefined); + } + exports.initialize = initialize; + + + /** + */ + async function email_settings_set( + smtp_host, + smtp_port, + smtp_username, + smtp_password, + sender_name, + sender_email_address, + options + ) + { + options = Object.assign( + { + }, + options + ); + const login_token = await wiki_js.cli.api.call_login_local( + ); + const result = await wiki_js.cli.api.call_email_settings_set( + login_token, + { + "sender_name": sender_name, + "sender_email_address": sender_email_address, + "smtp_host": smtp_host, + "smtp_port": smtp_port, + "secure": true, + "verify_ssl": true, + "smtp_username": smtp_username, + "smtp_password": smtp_password, + "name": "", + "use_dkim": false, + "dkim_domain_name": "", + "dkim_key_selector": "", + "dkim_private_key": "", + } + ); + return Promise.resolve(undefined); + } + exports.email_settings_set = email_settings_set; + + + /** + */ + async function authentication_strategy_list( + ) + { + const login_token = await wiki_js.cli.api.call_login_local( + ); + const result = await wiki_js.cli.api.call_authentication_strategy_list( + login_token + ); + return Promise.resolve(result); + } + exports.authentication_strategy_list = authentication_strategy_list; + + + /** + */ + async function authentication_strategy_add( + strategy + ) + { + const login_token = await wiki_js.cli.api.call_login_local( + ); + const current = await wiki_js.cli.api.call_authentication_strategy_list( + login_token + ); + const result = await wiki_js.cli.api.call_authentication_strategy_set( + login_token, + ( + ( + current + .map( + (entry) => ({ + "key": entry["key"], + "strategyKey": entry["strategy"]["key"], + "displayName": entry["displayName"], + "order": entry["order"], + "isEnabled": entry["isEnabled"], + "config": ( + entry["config"] + .map( + (item) => ({ + "key": item["key"], + "value": JSON.stringify({"v": JSON.parse(item["value"])["value"]}), + }) + ) + ), + "selfRegistration": entry["selfRegistration"], + "domainWhitelist": entry["domainWhitelist"], + "autoEnrollGroups": entry["autoEnrollGroups"], + }) + ) + ) + .concat( + [ + { + "key": strategy.key, + "strategyKey": "oauth2", + "displayName": strategy.name, + "order": ( + ( + current + .map(x => x["order"]) + .reduce((x,y) => (((x === null) || (x < y)) ? y : x), null) + ) + + + 1 + ), + "isEnabled": true, + "config": [ + { + "key": "clientId", + "value": JSON.stringify({"v": strategy.client_id}), + }, + { + "key": "clientSecret", + "value": JSON.stringify({"v": strategy.client_secret}), + }, + { + "key": "authorizationURL", + "value": JSON.stringify({"v": strategy.authorization_url}), + }, + { + "key": "tokenURL", + "value": JSON.stringify({"v": strategy.token_url}), + }, + { + "key": "userInfoURL", + "value": JSON.stringify({"v": strategy.user_info_url}), + }, + { + "key": "userIdClaim", + "value": JSON.stringify({"v": "id"}), + }, + { + "key": "displayNameClaim", + "value": JSON.stringify({"v": "name"}), + }, + { + "key": "emailClaim", + "value": JSON.stringify({"v": "email"}), + }, + { + "key": "mapGroups", + "value": JSON.stringify({"v": false}), + }, + { + "key": "groupsClaim", + "value": JSON.stringify({"v": "groups"}), + }, + { + "key": "logoutURL", + "value": JSON.stringify({"v": ""}), + }, + { + "key": "scope", + "value": JSON.stringify({"v": "openid profile email"}), + }, + { + "key": "useQueryStringForAccessToken", + "value": JSON.stringify({"v": false}), + }, + { + "key": "enableCSRFProtection", + "value": JSON.stringify({"v": true}), + } + ], + "selfRegistration": true, + "domainWhitelist": [], + "autoEnrollGroups": [] + }, + ] + ) + ) + ); + return Promise.resolve(undefined); + } + exports.authentication_strategy_add = authentication_strategy_add; + +}) (wiki_js.cli.logic); + + +var wiki_js; +wiki_js = (wiki_js || {}); +wiki_js.cli = (wiki_js.cli || {}); +(function (exports) { + + /** + */ + async function main( + args_raw + ) + { + // args + const args = wiki_js.cli.helpers.args.parse(args_raw); + const override_url_base = ( + ( + ("b" in args.volatile) + && + (args.volatile["b"].length >= 0) + ) + ? + args.volatile["b"][0] + : + null + ); + const override_username = ( + ( + ("u" in args.volatile) + && + (args.volatile["u"].length >= 0) + ) + ? + args.volatile["u"][0] + : + null + ); + const override_password = ( + ( + ("p" in args.volatile) + && + (args.volatile["p"].length >= 0) + ) + ? + args.volatile["p"][0] + : + null + ); + + // conf + const conf_path = ( + ( + ("c" in args.volatile) + && + (args.volatile["c"].length >= 0) + ) + ? + args.volatile["c"][0] + : + null + ); + await wiki_js.cli.conf.load(conf_path); + let conf_override = wiki_js.cli.conf.get(); + ((override_url_base !== null) && (conf_override.api.url_base = override_url_base)); + ((override_username !== null) && (conf_override.login.username = override_username)); + ((override_password !== null) && (conf_override.login.password = override_password)); + wiki_js.cli.conf.set(conf_override); + wiki_js.cli.helpers.log.write( + "debug", + "conf", + wiki_js.cli.conf.get() + ); + + // init + wiki_js.cli.helpers.log.setup(wiki_js.cli.conf.get().log.threshold); + + // exec + if (args.positional.length < 1) { + return Promise.reject("SYNTAX: [node] cli.js [-c ] [-b ] [-u ] [-p ] [ [ […]]]\n\n\t = init | email-settings-set | auth-strat-list | auth-strat-add-oauth2"); + } + else { + const action = args.positional[0]; + switch (action) { + default: { + return Promise.reject("invalid action: " + action); + break; + } + case "init": { + if (args.positional.length < 3) { + return Promise.reject("SYNTAX: … init [ []]"); + } + else { + await wiki_js.cli.logic.initialize( + args.positional[1], + args.positional[2], + { + "site_url": ( + (args.positional.length >= 4) + ? + args.positional[3] + : + undefined + ), + "allow_telemtry": ( + (args.positional.length >= 5) + ? + (args.positional[4] === "1") + : + undefined + ), + } + ); + return Promise.resolve(undefined); + } + break; + } + case "email-settings-set": { + if (args.positional.length < 7) { + return Promise.reject("SYNTAX: … email-settings-set "); + } + else { + await wiki_js.cli.logic.email_settings_set( + args.positional[1], + parseInt(args.positional[2]), + args.positional[3], + args.positional[4], + args.positional[5], + args.positional[6], + { + } + ); + return Promise.resolve(undefined); + } + } + case "auth-strat-list": { + const result = await wiki_js.cli.logic.authentication_strategy_list(); + process.stdout.write( + JSON.stringify( + result, + undefined, + "\t" + ) + + + "\n" + ); + return Promise.resolve(undefined); + break; + } + case "auth-strat-add-oauth2": { + if (args.positional.length < 8) { + return Promise.reject("SYNTAX: … auth-strat-add-oauth2 "); + } + else { + await wiki_js.cli.logic.authentication_strategy_add( + { + "key": args.positional[1], + "name": args.positional[2], + "client_id": args.positional[3], + "client_secret": args.positional[4], + "authorization_url": args.positional[5], + "token_url": args.positional[6], + "user_info_url": args.positional[7], + } + ); + return Promise.resolve(undefined); + } + break; + } + } + } + } + exports.main = main; + +}) (wiki_js.cli); + + +( + wiki_js.cli.main(process.argv.slice(2)) + .then( + () => { + } + ) + .catch( + (reason) => { + process.stderr.write("-- " + String(reason) + "\n"); + } + ) +); diff --git a/roles/wiki_js/info.md b/roles/wiki_js/info.md index 424f86a..9801213 100644 --- a/roles/wiki_js/info.md +++ b/roles/wiki_js/info.md @@ -7,3 +7,9 @@ - [Wiki.js-Dokumentation | Linux-Installation](https://docs.requarks.io/install/linux) - [Wiki.js-Dokumentation | Konfiguration](https://docs.requarks.io/install/config) + + +## ToDo + +- Admin-Account +- E-Mail diff --git a/roles/wiki_js/tasks/main.json b/roles/wiki_js/tasks/main.json index 2271dc3..7a62c22 100644 --- a/roles/wiki_js/tasks/main.json +++ b/roles/wiki_js/tasks/main.json @@ -22,7 +22,7 @@ "name": "directories", "become": true, "loop": [ - "{{var_wiki_js_data_path}}", + "{{var_wiki_js_data_path}}" ], "ansible.builtin.file": { "owner": "{{var_wiki_js_user}}", @@ -49,6 +49,16 @@ "dest": "{{var_wiki_js_directory}}" } }, + { + "name": "cli client", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.copy": { + "src": "cli.js", + "dest": "{{var_wiki_js_directory}}/cli.js", + "mode": "0700" + } + }, { "name": "database | sqlite | dirctory", "when": "var_wiki_js_database_kind == 'sqlite'", @@ -69,6 +79,15 @@ "state": "touch" } }, + { + "name": "conf | base", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.template": { + "src": "config.yml.j2", + "dest": "{{var_wiki_js_directory}}/config.yml" + } + }, { "name": "database | sqlite | setup", "when": "var_wiki_js_database_kind == 'sqlite'", @@ -80,17 +99,32 @@ } }, { - "name": "conf | base", + "name": "initialize", "become": true, "become_user": "{{var_wiki_js_user}}", - "ansible.builtin.template": { - "src": "config.yml.j2", - "dest": "{{var_wiki_js_directory}}/config.yml" + "ansible.builtin.command": { + "chdir": "{{var_wiki_js_directory}}", + "cmd": "node cli.js init {{var_wiki_js_admin_email_address}} {{var_wiki_js_admin_password}} https://{{var_wiki_js_domain}} 0" } }, { - "name": "conf | authentication | authelia", + "name": "email settings", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.command": { + "chdir": "{{var_wiki_js_directory}}", + "cmd": "node cli.js email-settings-set {{var_wiki_js_smtp_host}} {{var_wiki_js_smtp_port}} {{var_wiki_js_smtp_username}} {{var_wiki_js_smtp_password}} {{email_sending_sender_name}} {{email_sending_sender_email_address}}" + } + }, + { + "name": "authentication | authelia", "when": "var_wiki_js_authentication_kind == 'authelia'", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.command": { + "chdir": "{{var_wiki_js_directory}}", + "cmd": "node cli.js auth-strat-add-oauth2 {{var_wiki_js_authentication_data_authelia_provider_id}} {{var_wiki_js_authentication_data_authelia_provider_name}} {{var_wiki_js_authentication_data_authelia_client_id}} {{var_wiki_js_authentication_data_authelia_client_secret}} {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/authorization {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/token {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/userinfo" + } }, { "name": "systemd-unit", diff --git a/roles/wiki_js/vardef.json b/roles/wiki_js/vardef.json index 61ecd9b..805c1f1 100644 --- a/roles/wiki_js/vardef.json +++ b/roles/wiki_js/vardef.json @@ -7,6 +7,10 @@ "mandatory": false, "type": "boolean" }, + "domain": { + "mandatory": false, + "type": "string" + }, "user": { "mandatory": false, "type": "string" @@ -99,8 +103,36 @@ "type": "string", "mandatory": false }, - "authentication_data_authelia_uuid": { - "type": "string", - "mandatory": false + "smtp_host": { + "mandatory": false, + "type": "string" }, + "smtp_port": { + "mandatory": false, + "type": "integer" + }, + "smtp_username": { + "mandatory": false, + "type": "string" + }, + "smtp_password": { + "mandatory": false, + "type": "string" + }, + "email_sending_sender_name": { + "mandatory": false, + "type": "string" + }, + "email_sending_sender_email_address": { + "mandatory": false, + "type": "string" + }, + "admin_email_address": { + "mandatory": false, + "type": "string" + }, + "admin_password": { + "mandatory": false, + "type": "string" + } } From b1a4da69c28edf02d20a7bd0106360b1e21cdf7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Fri, 27 Sep 2024 12:54:39 +0200 Subject: [PATCH 03/10] [fix] role:wiki.js:vars --- roles/wiki_js/defaults/main.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/wiki_js/defaults/main.json b/roles/wiki_js/defaults/main.json index d26205a..0a7f8a1 100644 --- a/roles/wiki_js/defaults/main.json +++ b/roles/wiki_js/defaults/main.json @@ -24,8 +24,8 @@ "var_wiki_js_smtp_port": 465, "var_wiki_js_smtp_username": "REPLACE_ME", "var_wiki_js_smtp_password": "REPLACE_ME", - "email_sending_sender_name": "Wiki.js", - "email_sending_sender_email_address": "wiki-js@example.org", + "var_wiki_js_email_sending_sender_name": "Wiki.js", + "var_wiki_js_email_sending_sender_email_address": "wiki-js@example.org", "var_wiki_js_admin_email_address": "wiki-js-admin@example.org", "var_wiki_js_admin_password": "REPLACE_ME" } From b0f9767f9027815e3dbc2a3574e28520dfe2c363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Fri, 27 Sep 2024 17:49:18 +0200 Subject: [PATCH 04/10] [int] --- roles/wiki_js/tasks/main.json | 56 +++++++++++++++++------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/roles/wiki_js/tasks/main.json b/roles/wiki_js/tasks/main.json index 7a62c22..117202d 100644 --- a/roles/wiki_js/tasks/main.json +++ b/roles/wiki_js/tasks/main.json @@ -98,34 +98,6 @@ "cmd": "npm rebuild sqlite3" } }, - { - "name": "initialize", - "become": true, - "become_user": "{{var_wiki_js_user}}", - "ansible.builtin.command": { - "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js init {{var_wiki_js_admin_email_address}} {{var_wiki_js_admin_password}} https://{{var_wiki_js_domain}} 0" - } - }, - { - "name": "email settings", - "become": true, - "become_user": "{{var_wiki_js_user}}", - "ansible.builtin.command": { - "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js email-settings-set {{var_wiki_js_smtp_host}} {{var_wiki_js_smtp_port}} {{var_wiki_js_smtp_username}} {{var_wiki_js_smtp_password}} {{email_sending_sender_name}} {{email_sending_sender_email_address}}" - } - }, - { - "name": "authentication | authelia", - "when": "var_wiki_js_authentication_kind == 'authelia'", - "become": true, - "become_user": "{{var_wiki_js_user}}", - "ansible.builtin.command": { - "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js auth-strat-add-oauth2 {{var_wiki_js_authentication_data_authelia_provider_id}} {{var_wiki_js_authentication_data_authelia_provider_name}} {{var_wiki_js_authentication_data_authelia_client_id}} {{var_wiki_js_authentication_data_authelia_client_secret}} {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/authorization {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/token {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/userinfo" - } - }, { "name": "systemd-unit", "become": true, @@ -142,5 +114,33 @@ "enabled": true, "name": "wiki_js" } + }, + { + "name": "initialize", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.command": { + "chdir": "{{var_wiki_js_directory}}", + "cmd": "node cli.js -b https://{{var_wiki_js_domain}} init {{var_wiki_js_admin_email_address}} {{var_wiki_js_admin_password}} https://{{var_wiki_js_domain}} 0" + } + }, + { + "name": "email settings", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.command": { + "chdir": "{{var_wiki_js_directory}}", + "cmd": "node cli.js -b https://{{var_wiki_js_domain}} -u admin -p {{var_wiki_js_admin_password}} email-settings-set {{var_wiki_js_smtp_host}} {{var_wiki_js_smtp_port}} {{var_wiki_js_smtp_username}} {{var_wiki_js_smtp_password}} {{email_sending_sender_name}} {{email_sending_sender_email_address}}" + } + }, + { + "name": "authentication | authelia", + "when": "var_wiki_js_authentication_kind == 'authelia'", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.command": { + "chdir": "{{var_wiki_js_directory}}", + "cmd": "node cli.js -b https://{{var_wiki_js_domain}} -u admin -p {{var_wiki_js_admin_password}} auth-strat-add-oauth2 {{var_wiki_js_authentication_data_authelia_provider_id}} {{var_wiki_js_authentication_data_authelia_provider_name}} {{var_wiki_js_authentication_data_authelia_client_id}} {{var_wiki_js_authentication_data_authelia_client_secret}} {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/authorization {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/token {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/userinfo" + } } ] From e516bcacc535c489aa3cba03cb8048091f4c49a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Sat, 28 Sep 2024 09:57:22 +0200 Subject: [PATCH 05/10] [mod] role:wiki.js --- roles/wiki_js/tasks/main.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/roles/wiki_js/tasks/main.json b/roles/wiki_js/tasks/main.json index 117202d..947607a 100644 --- a/roles/wiki_js/tasks/main.json +++ b/roles/wiki_js/tasks/main.json @@ -45,7 +45,7 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.unarchive": { "remote_src": true, - "src": "/tmp/wiki_js.zip", + "src": "/tmp/wiki_js.tar.gz", "dest": "{{var_wiki_js_directory}}" } }, @@ -80,7 +80,7 @@ } }, { - "name": "conf | base", + "name": "conf", "become": true, "become_user": "{{var_wiki_js_user}}", "ansible.builtin.template": { @@ -107,7 +107,7 @@ } }, { - "name": "apply", + "name": "start service", "become": true, "ansible.builtin.systemd_service": { "state": "restarted", @@ -130,7 +130,7 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b https://{{var_wiki_js_domain}} -u admin -p {{var_wiki_js_admin_password}} email-settings-set {{var_wiki_js_smtp_host}} {{var_wiki_js_smtp_port}} {{var_wiki_js_smtp_username}} {{var_wiki_js_smtp_password}} {{email_sending_sender_name}} {{email_sending_sender_email_address}}" + "cmd": "node cli.js -b https://{{var_wiki_js_domain}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} email-settings-set {{var_wiki_js_smtp_host}} {{var_wiki_js_smtp_port}} {{var_wiki_js_smtp_username}} {{var_wiki_js_smtp_password}} {{email_sending_sender_name}} {{email_sending_sender_email_address}}" } }, { @@ -140,7 +140,7 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b https://{{var_wiki_js_domain}} -u admin -p {{var_wiki_js_admin_password}} auth-strat-add-oauth2 {{var_wiki_js_authentication_data_authelia_provider_id}} {{var_wiki_js_authentication_data_authelia_provider_name}} {{var_wiki_js_authentication_data_authelia_client_id}} {{var_wiki_js_authentication_data_authelia_client_secret}} {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/authorization {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/token {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/userinfo" + "cmd": "node cli.js -b https://{{var_wiki_js_domain}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} auth-strat-add-oauth2 {{var_wiki_js_authentication_data_authelia_provider_id}} {{var_wiki_js_authentication_data_authelia_provider_name}} {{var_wiki_js_authentication_data_authelia_client_id}} {{var_wiki_js_authentication_data_authelia_client_secret}} {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/authorization {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/token {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/userinfo" } } ] From cd7db6cf4edfbabc0cf92ff057e05bba67b01d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Sat, 28 Sep 2024 13:22:17 +0200 Subject: [PATCH 06/10] [fix] wiki.js-roles --- roles/authelia-for-wiki_js/defaults/main.json | 4 +- .../templates/authelia-client-conf.json.j2 | 4 +- roles/wiki_js-and-nginx/defaults/main.json | 4 +- roles/wiki_js/defaults/main.json | 2 +- roles/wiki_js/files/cli.js | 83 ++++++++++++++++++- roles/wiki_js/info.md | 4 +- roles/wiki_js/tasks/main.json | 17 +++- 7 files changed, 102 insertions(+), 16 deletions(-) diff --git a/roles/authelia-for-wiki_js/defaults/main.json b/roles/authelia-for-wiki_js/defaults/main.json index 98ccb23..f6531bc 100644 --- a/roles/authelia-for-wiki_js/defaults/main.json +++ b/roles/authelia-for-wiki_js/defaults/main.json @@ -1,6 +1,6 @@ { - "var_authelia_for_wiki_js_wiki_js_url_base": "https://wiki_js.example.org", + "var_authelia_for_wiki_js_wiki_js_url_base": "https://wiki-js.example.org", "var_authelia_for_wiki_js_client_id": "wiki_js", "var_authelia_for_wiki_js_client_secret": "REPLACE_ME", - "var_authelia_for_wiki_js_uuid": "REPLACE_ME" + "var_authelia_for_wiki_js_strategy_id": "authelia" } diff --git a/roles/authelia-for-wiki_js/templates/authelia-client-conf.json.j2 b/roles/authelia-for-wiki_js/templates/authelia-client-conf.json.j2 index 2bdc8e6..8537aea 100644 --- a/roles/authelia-for-wiki_js/templates/authelia-client-conf.json.j2 +++ b/roles/authelia-for-wiki_js/templates/authelia-client-conf.json.j2 @@ -5,7 +5,7 @@ "public": false, "authorization_policy": "one_factor", "redirect_uris": [ - "{{var_authelia_for_wiki_js_wiki_js_url_base}}/login/{{var_authelia_for_wiki_js_uuid}}/calback" + "{{var_authelia_for_wiki_js_wiki_js_url_base}}/login/{{var_authelia_for_wiki_js_strategy_id}}/callback" ], "scopes": [ "openid", @@ -13,5 +13,5 @@ "profile" ], "userinfo_signed_response_alg": "none", - "token_endpoint_auth_method": "client_secret_basic" + "token_endpoint_auth_method": "client_secret_post" } diff --git a/roles/wiki_js-and-nginx/defaults/main.json b/roles/wiki_js-and-nginx/defaults/main.json index 654de80..b1dd624 100644 --- a/roles/wiki_js-and-nginx/defaults/main.json +++ b/roles/wiki_js-and-nginx/defaults/main.json @@ -1,5 +1,5 @@ { - "var_vikunja_and_nginx_domain": "vikunja.example.org", + "var_wiki_js_and_nginx_domain": "wiki-js.example.org", "var_wiki_js_and_nginx_internal_port": 5632, - "var_vikunja_and_nginx_tls_mode": "force" + "var_wiki_js_and_nginx_tls_mode": "force" } diff --git a/roles/wiki_js/defaults/main.json b/roles/wiki_js/defaults/main.json index 0a7f8a1..07a1bda 100644 --- a/roles/wiki_js/defaults/main.json +++ b/roles/wiki_js/defaults/main.json @@ -8,7 +8,7 @@ "var_wiki_js_log_level": "info", "var_wiki_js_log_format": "default", "var_wiki_js_database_kind": "sqlite", - "var_wiki_js_database_data_sqlite_path": "/var/wiki.js/data.sqlite", + "var_wiki_js_database_data_sqlite_path": "/var/wiki_js/data.sqlite", "var_wiki_js_database_data_postgresql_host": "postgresql.example.org", "var_wiki_js_database_data_postgresql_port": 5432, "var_wiki_js_database_data_postgresql_username": "wiki_js_user", diff --git a/roles/wiki_js/files/cli.js b/roles/wiki_js/files/cli.js index f488a2b..bfa6cb8 100644 --- a/roles/wiki_js/files/cli.js +++ b/roles/wiki_js/files/cli.js @@ -544,6 +544,43 @@ wiki_js.cli.api = (wiki_js.cli.api || {}); } exports.call_authentication_strategy_set = call_authentication_strategy_set; + + /** + */ + function call_theming_set( + login_token, + dark_mode, + toc_position + ) + { + wiki_js.cli.helpers.log.write( + "info", + "api_call_theming_set", + { + "dark_mode": dark_mode, + "toc_position": toc_position, + } + ); + return ( + call_generic_graphql( + "mutation ($theme: String!, $iconset: String!, $darkMode: Boolean!, $tocPosition: String, $injectCSS: String, $injectHead: String, $injectBody: String) {theming {setConfig(theme: $theme, iconset: $iconset, darkMode: $darkMode, tocPosition: $tocPosition, injectCSS: $injectCSS, injectHead: $injectHead, injectBody: $injectBody) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", + { + "login_token": login_token, + "variables": { + "theme": "default", + "iconset": "mdi", + "darkMode": dark_mode, + "tocPosition": "left", + "injectCSS": "", + "injectHead": "", + "injectBody": "" + } + } + ) + ); + } + exports.call_theming_set = call_theming_set; + }) (wiki_js.cli.api); @@ -760,6 +797,31 @@ wiki_js.cli.logic = (wiki_js.cli.logic || {}); } exports.authentication_strategy_add = authentication_strategy_add; + + /** + */ + async function theming_set( + options = {} + ) + { + options = Object.assign( + { + "dark_mode": false, + "toc_position": "left", + }, + options + ); + const login_token = await wiki_js.cli.api.call_login_local( + ); + const result = await wiki_js.cli.api.call_theming_set( + login_token, + options.dark_mode, + options.toc_position + ); + return Promise.resolve(result); + } + exports.theming_set = theming_set; + }) (wiki_js.cli.logic); @@ -849,7 +911,7 @@ wiki_js.cli = (wiki_js.cli || {}); break; } case "init": { - if (args.positional.length < 3) { + if (args.positional.length <= 2) { return Promise.reject("SYNTAX: … init [ []]"); } else { @@ -878,7 +940,7 @@ wiki_js.cli = (wiki_js.cli || {}); break; } case "email-settings-set": { - if (args.positional.length < 7) { + if (args.positional.length <= 6) { return Promise.reject("SYNTAX: … email-settings-set "); } else { @@ -910,7 +972,7 @@ wiki_js.cli = (wiki_js.cli || {}); break; } case "auth-strat-add-oauth2": { - if (args.positional.length < 8) { + if (args.positional.length <= 7) { return Promise.reject("SYNTAX: … auth-strat-add-oauth2 "); } else { @@ -929,6 +991,21 @@ wiki_js.cli = (wiki_js.cli || {}); } break; } + case "theming-set": { + if (args.positional.length <= 2) { + return Promise.reject("SYNTAX: … theming-set []"); + } + else { + await wiki_js.cli.logic.theming_set( + { + "dark_mode": (args.positional[1] === "1"), + "toc_position": args.positional[2], + } + ); + return Promise.resolve(undefined); + } + break; + } } } } diff --git a/roles/wiki_js/info.md b/roles/wiki_js/info.md index 9801213..55e275c 100644 --- a/roles/wiki_js/info.md +++ b/roles/wiki_js/info.md @@ -11,5 +11,5 @@ ## ToDo -- Admin-Account -- E-Mail +- Locale +- Start Page diff --git a/roles/wiki_js/tasks/main.json b/roles/wiki_js/tasks/main.json index 947607a..57f4c47 100644 --- a/roles/wiki_js/tasks/main.json +++ b/roles/wiki_js/tasks/main.json @@ -36,7 +36,7 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.get_url": { "url": "https://github.com/Requarks/wiki/releases/latest/download/wiki-js.tar.gz", - "dest": "/tmp/wiki_js.zip" + "dest": "/tmp/wiki_js.tar.gz" } }, { @@ -121,7 +121,7 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b https://{{var_wiki_js_domain}} init {{var_wiki_js_admin_email_address}} {{var_wiki_js_admin_password}} https://{{var_wiki_js_domain}} 0" + "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} init {{var_wiki_js_admin_email_address}} {{var_wiki_js_admin_password}} https://{{var_wiki_js_domain}} 0" } }, { @@ -130,7 +130,16 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b https://{{var_wiki_js_domain}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} email-settings-set {{var_wiki_js_smtp_host}} {{var_wiki_js_smtp_port}} {{var_wiki_js_smtp_username}} {{var_wiki_js_smtp_password}} {{email_sending_sender_name}} {{email_sending_sender_email_address}}" + "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} email-settings-set {{var_wiki_js_smtp_host}} {{var_wiki_js_smtp_port}} {{var_wiki_js_smtp_username}} {{var_wiki_js_smtp_password}} {{email_sending_sender_name}} {{email_sending_sender_email_address}}" + } + }, + { + "name": "theming", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.command": { + "chdir": "{{var_wiki_js_directory}}", + "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} theming-set 1 left" } }, { @@ -140,7 +149,7 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b https://{{var_wiki_js_domain}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} auth-strat-add-oauth2 {{var_wiki_js_authentication_data_authelia_provider_id}} {{var_wiki_js_authentication_data_authelia_provider_name}} {{var_wiki_js_authentication_data_authelia_client_id}} {{var_wiki_js_authentication_data_authelia_client_secret}} {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/authorization {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/token {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/userinfo" + "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} auth-strat-add-oauth2 {{var_wiki_js_authentication_data_authelia_provider_id}} {{var_wiki_js_authentication_data_authelia_provider_name}} {{var_wiki_js_authentication_data_authelia_client_id}} {{var_wiki_js_authentication_data_authelia_client_secret}} {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/authorization {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/token {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/userinfo" } } ] From 064c47b27019860d940a135491e128418b6db891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Sat, 28 Sep 2024 23:35:36 +0200 Subject: [PATCH 07/10] [mod] wiki_js --- roles/wiki_js/defaults/main.json | 5 +- roles/wiki_js/files/cli.js | 398 +++++++++++++++++++++++++++---- roles/wiki_js/info.md | 3 +- roles/wiki_js/tasks/main.json | 65 ++++- roles/wiki_js/vardef.json | 16 ++ 5 files changed, 423 insertions(+), 64 deletions(-) diff --git a/roles/wiki_js/defaults/main.json b/roles/wiki_js/defaults/main.json index 07a1bda..6e94256 100644 --- a/roles/wiki_js/defaults/main.json +++ b/roles/wiki_js/defaults/main.json @@ -27,5 +27,8 @@ "var_wiki_js_email_sending_sender_name": "Wiki.js", "var_wiki_js_email_sending_sender_email_address": "wiki-js@example.org", "var_wiki_js_admin_email_address": "wiki-js-admin@example.org", - "var_wiki_js_admin_password": "REPLACE_ME" + "var_wiki_js_admin_password": "REPLACE_ME", + "var_wiki_js_additional_locales": [], + "var_wiki_js_user_group_name": "Default", + "var_wiki_js_allow_guest_view": true } diff --git a/roles/wiki_js/files/cli.js b/roles/wiki_js/files/cli.js index bfa6cb8..dd1b87e 100644 --- a/roles/wiki_js/files/cli.js +++ b/roles/wiki_js/files/cli.js @@ -67,50 +67,6 @@ wiki_js.cli.helpers.file = (wiki_js.cli.helpers.file || {}); }) (wiki_js.cli.helpers.file) -var wiki_js; -wiki_js = (wiki_js || {}); -wiki_js.cli = (wiki_js.cli || {}); -wiki_js.cli.helpers = (wiki_js.cli.helpers || {}); -wiki_js.cli.helpers.http = (wiki_js.cli.helpers.http || {}); -(function (exports) { - - /** - */ - async function call( - http_request - ) - { - wiki_js.cli.helpers.log.write( - "debug", - "http_call_request", - http_request - ); - const fetch_request = new Request( - http_request.target, - { - "method": http_request.method, - "headers": http_request.headers, - "body": http_request.body, - } - ); - const fetch_response = await fetch(fetch_request); - const http_response = { - "status_code": fetch_response.status, - "headers": fetch_response.headers, - "body": await fetch_response.text(), - }; - wiki_js.cli.helpers.log.write( - "debug", - "http_call_response", - http_response - ); - return http_response; - } - exports.call = call; - -}) (wiki_js.cli.helpers.http) - - var wiki_js; wiki_js = (wiki_js || {}); wiki_js.cli = (wiki_js.cli || {}); @@ -174,6 +130,50 @@ wiki_js.cli.helpers.log = (wiki_js.cli.helpers.log || {}); }) (wiki_js.cli.helpers.log); +var wiki_js; +wiki_js = (wiki_js || {}); +wiki_js.cli = (wiki_js.cli || {}); +wiki_js.cli.helpers = (wiki_js.cli.helpers || {}); +wiki_js.cli.helpers.http = (wiki_js.cli.helpers.http || {}); +(function (exports) { + + /** + */ + async function call( + http_request + ) + { + wiki_js.cli.helpers.log.write( + "debug", + "http_call_request", + http_request + ); + const fetch_request = new Request( + http_request.target, + { + "method": http_request.method, + "headers": http_request.headers, + "body": http_request.body, + } + ); + const fetch_response = await fetch(fetch_request); + const http_response = { + "status_code": fetch_response.status, + "headers": fetch_response.headers, + "body": await fetch_response.text(), + }; + wiki_js.cli.helpers.log.write( + "debug", + "http_call_response", + http_response + ); + return http_response; + } + exports.call = call; + +}) (wiki_js.cli.helpers.http) + + var wiki_js; wiki_js = (wiki_js || {}); wiki_js.cli = (wiki_js.cli || {}); @@ -489,6 +489,146 @@ wiki_js.cli.api = (wiki_js.cli.api || {}); exports.call_email_settings_set = call_email_settings_set; + /** + */ + function call_locale_download( + locale + ) + { + wiki_js.cli.helpers.log.write( + "info", + "api_call_locale_download", + { + "locale": locale, + } + ); + return ( + call_generic_graphql( + "mutation ($locale: String!) {localization {downloadLocale(locale: $locale) {responseResult {succeeded errorCode slug message __typename} __typename}__typename}}", + { + "login_token": login_token, + "variables": { + "locale": locale, + } + } + ) + ); + } + exports.call_locale_download = call_locale_download; + + + /** + */ + function call_group_list( + login_token, + name + ) + { + wiki_js.cli.helpers.log.write( + "info", + "api_call_group_list", + { + } + ); + return ( + call_generic_graphql( + "{groups {list {id name isSystem userCount createdAt updatedAt __typename} __typename}}", + { + "login_token": login_token, + "variables": { + } + } + ) + ); + } + exports.call_group_list = call_group_list; + + + /** + */ + function call_group_create( + login_token, + name + ) + { + wiki_js.cli.helpers.log.write( + "info", + "api_call_group_create", + { + "name": name, + } + ); + return ( + call_generic_graphql( + "mutation ($name: String!) {groups {create(name: $name) {responseResult {succeeded errorCode slug message __typename} group {id name createdAt updatedAt __typename} __typename} __typename}}", + { + "login_token": login_token, + "variables": { + "name": name, + } + } + ) + ); + } + exports.call_group_create = call_group_create; + + + /** + * @param permissions_general { + * Array< + * string + * > + * } + * @param permissions_page_specific { + * Array< + * { + * id:string; + * path:string; + * roles:Array< + * string + * >; + * match:string; + * deny:boolean; + * locales:Array< + * string + * >; + * } + * > + * } + */ + function call_group_update( + login_token, + group_id, + name, + permissions_general, + permissions_page_specific + ) + { + wiki_js.cli.helpers.log.write( + "info", + "api_call_group_update", + { + } + ); + return ( + call_generic_graphql( + "mutation ($id: Int!, $name: String!, $redirectOnLogin: String!, $permissions: [String]!, $pageRules: [PageRuleInput]!) {groups {update(id: $id, name: $name, redirectOnLogin: $redirectOnLogin, permissions: $permissions, pageRules: $pageRules) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", + { + "login_token": login_token, + "variables": { + "id": group_id, + "name": name, + "redirectOnLogin": "/", + "permissions": permissions_general, + "pageRules": permissions_page_specific, + } + } + ) + ); + } + exports.call_group_update = call_group_update; + + /** */ function call_authentication_strategy_list( @@ -580,7 +720,7 @@ wiki_js.cli.api = (wiki_js.cli.api || {}); ); } exports.call_theming_set = call_theming_set; - + }) (wiki_js.cli.api); @@ -658,6 +798,91 @@ wiki_js.cli.logic = (wiki_js.cli.logic || {}); exports.email_settings_set = email_settings_set; + /** + */ + async function group_identify( + name + ) + { + const data = await wiki_js.cli.api.call_group_list(); + const hits = ( + data["groups"]["list"] + .filter( + (entry) => (entry["name"] === name) + ) + ); + if (hits.length !== 1) { + return Promise.reject(new Error("not found or ambiguous")); + } + else { + return Promise.resolve(hits[0]["id"]); + } + } + exports.group_identify = group_identify; + + + /** + * returns the ID of the generated group + */ + async function group_add( + name, + options = {} + ) + { + options = Object.assign( + { + "permissions_general": [], + "permissions_specific": [], + }, + options + ); + const login_token = await wiki_js.cli.api.call_login_local( + ); + const result_1 = await wiki_js.cli.api.call_group_create( + login_token, + name + ); + const id = result_1["groups"]["create"]["group"]["id"]; + const result_2 = await wiki_js.cli.api.call_group_update( + login_token, + id, + name, + options.permissions_general, + options.permissions_specific + ); + return Promise.resolve(id); + } + exports.group_add = group_add; + + + /** + */ + async function group_modify( + id, + options = {} + ) + { + options = Object.assign( + { + "permissions_general": [], + "permissions_specific": [], + }, + options + ); + const login_token = await wiki_js.cli.api.call_login_local( + ); + const result = await wiki_js.cli.api.call_group_update( + login_token, + id, + name, + options.permissions_general, + options.permissions_specific + ); + return Promise.resolve(undefined); + } + exports.group_modify = group_modify; + + /** */ async function authentication_strategy_list( @@ -674,6 +899,17 @@ wiki_js.cli.logic = (wiki_js.cli.logic || {}); /** + * @param strategy { + * { + * key:string; + * name:string; + * client_id:string; + * client_secret:string; + * authorization_url:string; + * token_url:string; + * user_info_url:string; + * group_assignments:Array; + * } */ async function authentication_strategy_add( strategy @@ -787,7 +1023,10 @@ wiki_js.cli.logic = (wiki_js.cli.logic || {}); ], "selfRegistration": true, "domainWhitelist": [], - "autoEnrollGroups": [] + "autoEnrollGroups": ( + strategy.group_assignments + .map(x => group_identify(x)) + ), }, ] ) @@ -901,7 +1140,7 @@ wiki_js.cli = (wiki_js.cli || {}); // exec if (args.positional.length < 1) { - return Promise.reject("SYNTAX: [node] cli.js [-c ] [-b ] [-u ] [-p ] [ [ […]]]\n\n\t = init | email-settings-set | auth-strat-list | auth-strat-add-oauth2"); + return Promise.reject("SYNTAX: [node] cli.js [-c ] [-b ] [-u ] [-p ] [ [ […]]]\n\n\t = init | email-settings-set | group-add | auth-strat-list | auth-strat-add-oauth2 | theming-set"); } else { const action = args.positional[0]; @@ -957,6 +1196,68 @@ wiki_js.cli = (wiki_js.cli || {}); return Promise.resolve(undefined); } } + case "group-add": { + if (args.positional.length <= 1) { + return Promise.reject("SYNTAX: … group-add [ [ [ […]]]]"); + } + else { + const name = args.positional[1]; + const permissions = args.positional.slice(2); + const result = await wiki_js.cli.logic.group_add( + name, + { + "permissions_general": permissions, + "permissions_specific": [ + { + "id": "default", + "path": "", + "roles": permissions, + "match": "START", + "deny": false, + "locales": [] + } + ], + } + ); + process.stdout.write( + JSON.stringify( + result, + undefined, + "\t" + ) + + + "\n" + ); + } + break; + } + case "group-modify": { + if (args.positional.length <= 2) { + return Promise.reject("SYNTAX: … group-modify [ [ [ […]]]]"); + } + else { + const name = args.positional[1]; + const id = group_identify(name); + const permissions = args.positional.slice(2); + const result = await wiki_js.cli.logic.group_modify( + id, + { + "permissions_general": permissions, + "permissions_specific": [ + { + "id": "default", + "path": "", + "roles": permissions, + "match": "START", + "deny": false, + "locales": [] + } + ], + } + ); + } + break; + } case "auth-strat-list": { const result = await wiki_js.cli.logic.authentication_strategy_list(); process.stdout.write( @@ -973,7 +1274,7 @@ wiki_js.cli = (wiki_js.cli || {}); } case "auth-strat-add-oauth2": { if (args.positional.length <= 7) { - return Promise.reject("SYNTAX: … auth-strat-add-oauth2 "); + return Promise.reject("SYNTAX: … auth-strat-add-oauth2 [ [ [ […]]]]"); } else { await wiki_js.cli.logic.authentication_strategy_add( @@ -985,6 +1286,7 @@ wiki_js.cli = (wiki_js.cli || {}); "authorization_url": args.positional[5], "token_url": args.positional[6], "user_info_url": args.positional[7], + "group_assignments": args.positional.slice(8), } ); return Promise.resolve(undefined); diff --git a/roles/wiki_js/info.md b/roles/wiki_js/info.md index 55e275c..9730dc5 100644 --- a/roles/wiki_js/info.md +++ b/roles/wiki_js/info.md @@ -11,5 +11,4 @@ ## ToDo -- Locale -- Start Page +- start page diff --git a/roles/wiki_js/tasks/main.json b/roles/wiki_js/tasks/main.json index 57f4c47..9c5ecfd 100644 --- a/roles/wiki_js/tasks/main.json +++ b/roles/wiki_js/tasks/main.json @@ -116,7 +116,7 @@ } }, { - "name": "initialize", + "name": "setup | initialize", "become": true, "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { @@ -125,7 +125,7 @@ } }, { - "name": "email settings", + "name": "setup | email settings", "become": true, "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { @@ -134,22 +134,61 @@ } }, { - "name": "theming", + "name": "setup | locales", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "loop": "{{var_wiki_js_additional_locales}}", + "ansible.builtin.command": { + "chdir": "{{var_wiki_js_directory}}", + "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} locale-add {{item}}" + } + }, + { + "name": "setup | set guest access | negative", + "when": "not var_wiki_js_allow_guest_view", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.command": { + "chdir": "{{var_wiki_js_directory}}", + "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} group-modify Guests" + } + }, + { + "name": "setup | set guest access | positive", + "when": "var_wiki_js_allow_guest_view", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.command": { + "chdir": "{{var_wiki_js_directory}}", + "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} group-modify Guests read:pages read:assets read:comments" + } + }, + { + "name": "setup | define user group", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.command": { + "chdir": "{{var_wiki_js_directory}}", + "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} group-add {{var_wiki_js_user_group_name}} read:pages read:assets read:comments write:comments write:pages manage:pages delete:pages write:styles write:scripts read:source read:history write:assets manage:assets manage:comments" + } + }, + { + "name": "setup | authentication | authelia", + "when": "var_wiki_js_authentication_kind == 'authelia'", + "become": true, + "become_user": "{{var_wiki_js_user}}", + "ansible.builtin.command": { + "chdir": "{{var_wiki_js_directory}}", + "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} auth-strat-add-oauth2 {{var_wiki_js_authentication_data_authelia_provider_id}} {{var_wiki_js_authentication_data_authelia_provider_name}} {{var_wiki_js_authentication_data_authelia_client_id}} {{var_wiki_js_authentication_data_authelia_client_secret}} {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/authorization {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/token {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/userinfo {{var_wiki_js_user_group_name}}" + } + }, + { + "name": "setup | theming", "become": true, "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} theming-set 1 left" } - }, - { - "name": "authentication | authelia", - "when": "var_wiki_js_authentication_kind == 'authelia'", - "become": true, - "become_user": "{{var_wiki_js_user}}", - "ansible.builtin.command": { - "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} auth-strat-add-oauth2 {{var_wiki_js_authentication_data_authelia_provider_id}} {{var_wiki_js_authentication_data_authelia_provider_name}} {{var_wiki_js_authentication_data_authelia_client_id}} {{var_wiki_js_authentication_data_authelia_client_secret}} {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/authorization {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/token {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/userinfo" - } } ] diff --git a/roles/wiki_js/vardef.json b/roles/wiki_js/vardef.json index 805c1f1..3b68b3f 100644 --- a/roles/wiki_js/vardef.json +++ b/roles/wiki_js/vardef.json @@ -134,5 +134,21 @@ "admin_password": { "mandatory": false, "type": "string" + }, + "additional_locales": { + "mandatory": false, + "type": "array", + "items": { + "nullable": false, + "type": "string" + } + }, + "user_group_name": { + "mandatory": false, + "type": "string" + }, + "allow_guest_view": { + "mandatory": false, + "type": "boolean" } } From 4dde5388bc4945702402ce1e2f106be8c44e2537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Mon, 30 Sep 2024 08:23:32 +0200 Subject: [PATCH 08/10] [mod] role:wiki_js:cli --- roles/wiki_js/files/cli.js | 1330 ------------------------------- roles/wiki_js/files/wiki-js-cli | 896 +++++++++++++++++++++ roles/wiki_js/tasks/main.json | 5 +- 3 files changed, 898 insertions(+), 1333 deletions(-) delete mode 100644 roles/wiki_js/files/cli.js create mode 100755 roles/wiki_js/files/wiki-js-cli diff --git a/roles/wiki_js/files/cli.js b/roles/wiki_js/files/cli.js deleted file mode 100644 index dd1b87e..0000000 --- a/roles/wiki_js/files/cli.js +++ /dev/null @@ -1,1330 +0,0 @@ -#!/usr/bin/env node - - -var wiki_js; -wiki_js = (wiki_js || {}); -wiki_js.cli = (wiki_js.cli || {}); -wiki_js.cli.helpers = (wiki_js.cli.helpers || {}); -wiki_js.cli.helpers.string = (wiki_js.cli.helpers.string || {}); -(function (exports) { - - /** - */ - function coin( - template, - arguments_ - ) - { - let result = template; - Object.entries(arguments_).forEach( - ([key, value]) => { - result = result.replace(new RegExp("{{" + key + "}}", "g"), value); - } - ); - return result; - } - exports.coin = coin; - -}) (wiki_js.cli.helpers.string) - - -var wiki_js; -wiki_js = (wiki_js || {}); -wiki_js.cli = (wiki_js.cli || {}); -wiki_js.cli.helpers = (wiki_js.cli.helpers || {}); -wiki_js.cli.helpers.file = (wiki_js.cli.helpers.file || {}); -(function (exports) { - - /** - */ - function read( - path - ) - { - const nm_fs = require("fs"); - return ( - new Promise( - (resolve, reject) => { - nm_fs.readFile( - path, - { - }, - (err, data) => { - if (err) { - reject(err); - } - else { - resolve(data.toString()); - } - } - ); - } - ) - ); - } - exports.read = read; - -}) (wiki_js.cli.helpers.file) - - -var wiki_js; -wiki_js = (wiki_js || {}); -wiki_js.cli = (wiki_js.cli || {}); -wiki_js.cli.helpers.log = (wiki_js.cli.helpers.log || {}); -(function (exports) { - - /** - */ - const _level_order = [ - "debug", - "info", - "notice", - "warning", - "error", - ]; - - - /** - */ - var _threshold = "info"; - - - /** - */ - function setup( - threshold - ) - { - _threshold = threshold; - } - exports.setup = setup; - - - /** - */ - function write( - level, - incident, - details - ) - { - if (_level_order.indexOf(level) < _level_order.indexOf(_threshold)) { - // do nothing - } - else { - process.stderr.write( - wiki_js.cli.helpers.string.coin( - "\n<{{datetime}}> [{{level}}] {{incident}}\n{{details}}\n\n", - { - "datetime": (new Date()).toISOString(), - "level": level, - "incident": incident, - "details": JSON.stringify(details, undefined, "\t"), - } - ) - ); - } - } - exports.write = write; - -}) (wiki_js.cli.helpers.log); - - -var wiki_js; -wiki_js = (wiki_js || {}); -wiki_js.cli = (wiki_js.cli || {}); -wiki_js.cli.helpers = (wiki_js.cli.helpers || {}); -wiki_js.cli.helpers.http = (wiki_js.cli.helpers.http || {}); -(function (exports) { - - /** - */ - async function call( - http_request - ) - { - wiki_js.cli.helpers.log.write( - "debug", - "http_call_request", - http_request - ); - const fetch_request = new Request( - http_request.target, - { - "method": http_request.method, - "headers": http_request.headers, - "body": http_request.body, - } - ); - const fetch_response = await fetch(fetch_request); - const http_response = { - "status_code": fetch_response.status, - "headers": fetch_response.headers, - "body": await fetch_response.text(), - }; - wiki_js.cli.helpers.log.write( - "debug", - "http_call_response", - http_response - ); - return http_response; - } - exports.call = call; - -}) (wiki_js.cli.helpers.http) - - -var wiki_js; -wiki_js = (wiki_js || {}); -wiki_js.cli = (wiki_js.cli || {}); -wiki_js.cli.helpers.args = (wiki_js.cli.helpers.args || {}); -(function (exports) { - - /** - */ - function parse( - args_raw - ) - { - let result = { - "positional": [], - "volatile": {}, - }; - let state = "free"; - let key = null; - args_raw.forEach( - (arg_raw) => { - switch (state) { - case "free": { - if (arg_raw.startsWith("-")) { - key = arg_raw.slice(1); - state = "bound"; - } - else { - if (key === null) { - result.positional.push(arg_raw); - key = null; - state = "free"; - } - else { - wiki_js.cli.helpers.log.write( - "warning", - "arg_discarded", - { - "arg_raw": arg_raw, - } - ); - key = null; - state = "free"; - } - } - break; - } - case "bound": { - if (! (key in result["volatile"])) { - result["volatile"][key] = []; - } - else { - // do nothing - } - result["volatile"][key].push(arg_raw); - key = null; - state = "free"; - } - } - } - ); - return result; - } - exports.parse = parse; - -}) (wiki_js.cli.helpers.args); - - -var wiki_js; -wiki_js = (wiki_js || {}); -wiki_js.cli = (wiki_js.cli || {}); -wiki_js.cli.conf = (wiki_js.cli.conf || {}); -(function (exports) { - - /** - */ - var _data = null; - - - /** - */ - async function load( - path - ) - { - let data_raw; - if (path === null) { - data_raw = {}; - } - else { - const content = await wiki_js.cli.helpers.file.read(path); - data_raw = JSON.parse(content); - } - wiki_js.cli.helpers.log.write( - "debug", - "conf_raw", - data_raw - ); - _data = { - "api": { - "url_base": ( - data_raw?.api?.url_base - ?? - "http://localhost:3000" - ), - }, - "login": { - "username": ( - data_raw?.login?.username - ?? - "admin" - ), - "password": ( - data_raw?.login?.password - ?? - "admin" - ), - }, - "log": { - "threshold": ( - data_raw?.log?.threshold - ?? - "debug" - ), - } - }; - return Promise.resolve(undefined); - } - exports.load = load; - - - /** - */ - function set( - data - ) - { - _data = data; - } - exports.set = set; - - - /** - */ - function get( - ) - { - return _data; - } - exports.get = get; - -}) (wiki_js.cli.conf); - - -var wiki_js; -wiki_js = (wiki_js || {}); -wiki_js.cli = (wiki_js.cli || {}); -wiki_js.cli.api = (wiki_js.cli.api || {}); -(function (exports) { - - /** - */ - async function call_finalize( - admin_email, - admin_password, - site_url, - telemetry - ) - { - const http_request = { - "target": (wiki_js.cli.conf.get().api.url_base + "/finalize"), - "method": "POST", - "headers": { - "Content-Type": "application/json", - }, - "body": JSON.stringify( - { - "adminEmail": admin_email, - "adminPassword": admin_password, - "adminPasswordConfirm": admin_password, - "siteUrl": site_url, - "telemetry": telemetry, - } - ), - }; - http_response = await wiki_js.cli.helpers.http.call(http_request); - const data = JSON.parse(http_response.body); - return Promise.resolve(undefined); - } - exports.call_finalize = call_finalize; - - - /** - */ - async function call_generic_graphql( - graphql_query, - options - ) - { - options = Object.assign( - { - "login_token": null, - "variables": {}, - }, - options - ); - const http_request = { - "target": (wiki_js.cli.conf.get().api.url_base + "/graphql"), - "method": "POST", - "headers": Object.assign( - { - "Content-Type": "application/json", - }, - ( - (options.login_token === null) - ? - {} - : - {"Cookie": ("jwt=" + options.login_token)} - ) - ), - "body": JSON.stringify( - [ - { - "operationName": null, - "variables": options.variables, - "extensions": {}, - "query": graphql_query, - } - ] - ), - }; - http_response = await wiki_js.cli.helpers.http.call(http_request); - const data = JSON.parse(http_response.body); - return Promise.resolve(data[0]["data"]); - } - - - /** - * executes a local login and returns the JWT - */ - function call_login_local( - ) - { - wiki_js.cli.helpers.log.write( - "info", - "api_call_login_local", - { - } - ); - return ( - call_generic_graphql( - "mutation ($username: String!, $password: String!, $strategy: String!) {authentication {login(username: $username, password: $password, strategy: $strategy) {responseResult {succeeded errorCode slug message __typename} jwt mustChangePwd mustProvideTFA mustSetupTFA continuationToken redirect tfaQRImage __typename} __typename}}", - { - "variables": { - "strategy": "local", - "username": wiki_js.cli.conf.get().login.username, - "password": wiki_js.cli.conf.get().login.password, - } - } - ) - .then( - (data) => ( - data["authentication"]["login"]["responseResult"]["succeeded"] - ? - Promise.resolve(data["authentication"]["login"]["jwt"]) - : - Promise.reject(new Error("login failed")) - ) - ) - ); - } - exports.call_login_local = call_login_local; - - - /** - */ - function call_email_settings_set( - login_token, - settings - ) - { - wiki_js.cli.helpers.log.write( - "info", - "api_call_email_settings_set", - { - "settings": settings, - } - ); - return ( - call_generic_graphql( - "mutation ($senderName: String!, $senderEmail: String!, $host: String!, $port: Int!, $name: String!, $secure: Boolean!, $verifySSL: Boolean!, $user: String!, $pass: String!, $useDKIM: Boolean!, $dkimDomainName: String!, $dkimKeySelector: String!, $dkimPrivateKey: String!) {mail {updateConfig(senderName: $senderName, senderEmail: $senderEmail, host: $host, port: $port, name: $name, secure: $secure, verifySSL: $verifySSL, user: $user, pass: $pass, useDKIM: $useDKIM, dkimDomainName: $dkimDomainName, dkimKeySelector: $dkimKeySelector, dkimPrivateKey: $dkimPrivateKey) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", - { - "login_token": login_token, - "variables": { - "senderName": settings.sender_name, - "senderEmail": settings.sender_email_address, - "host": settings.smtp_host, - "port": settings.smtp_port, - "name": settings.name, - "secure": settings.secure, - "verifySSL": settings.verify_ssl, - "user": settings.smtp_username, - "pass": settings.smtp_password, - "useDKIM": settings.use_dkim, - "dkimDomainName": settings.dkim_domain_name, - "dkimKeySelector": settings.dkim_key_selector, - "dkimPrivateKey": settings.dkim_private_key, - } - } - ) - ); - } - exports.call_email_settings_set = call_email_settings_set; - - - /** - */ - function call_locale_download( - locale - ) - { - wiki_js.cli.helpers.log.write( - "info", - "api_call_locale_download", - { - "locale": locale, - } - ); - return ( - call_generic_graphql( - "mutation ($locale: String!) {localization {downloadLocale(locale: $locale) {responseResult {succeeded errorCode slug message __typename} __typename}__typename}}", - { - "login_token": login_token, - "variables": { - "locale": locale, - } - } - ) - ); - } - exports.call_locale_download = call_locale_download; - - - /** - */ - function call_group_list( - login_token, - name - ) - { - wiki_js.cli.helpers.log.write( - "info", - "api_call_group_list", - { - } - ); - return ( - call_generic_graphql( - "{groups {list {id name isSystem userCount createdAt updatedAt __typename} __typename}}", - { - "login_token": login_token, - "variables": { - } - } - ) - ); - } - exports.call_group_list = call_group_list; - - - /** - */ - function call_group_create( - login_token, - name - ) - { - wiki_js.cli.helpers.log.write( - "info", - "api_call_group_create", - { - "name": name, - } - ); - return ( - call_generic_graphql( - "mutation ($name: String!) {groups {create(name: $name) {responseResult {succeeded errorCode slug message __typename} group {id name createdAt updatedAt __typename} __typename} __typename}}", - { - "login_token": login_token, - "variables": { - "name": name, - } - } - ) - ); - } - exports.call_group_create = call_group_create; - - - /** - * @param permissions_general { - * Array< - * string - * > - * } - * @param permissions_page_specific { - * Array< - * { - * id:string; - * path:string; - * roles:Array< - * string - * >; - * match:string; - * deny:boolean; - * locales:Array< - * string - * >; - * } - * > - * } - */ - function call_group_update( - login_token, - group_id, - name, - permissions_general, - permissions_page_specific - ) - { - wiki_js.cli.helpers.log.write( - "info", - "api_call_group_update", - { - } - ); - return ( - call_generic_graphql( - "mutation ($id: Int!, $name: String!, $redirectOnLogin: String!, $permissions: [String]!, $pageRules: [PageRuleInput]!) {groups {update(id: $id, name: $name, redirectOnLogin: $redirectOnLogin, permissions: $permissions, pageRules: $pageRules) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", - { - "login_token": login_token, - "variables": { - "id": group_id, - "name": name, - "redirectOnLogin": "/", - "permissions": permissions_general, - "pageRules": permissions_page_specific, - } - } - ) - ); - } - exports.call_group_update = call_group_update; - - - /** - */ - function call_authentication_strategy_list( - login_token - ) - { - wiki_js.cli.helpers.log.write( - "info", - "api_call_authentication_strategy_list", - { - } - ); - return ( - call_generic_graphql( - "{authentication {activeStrategies {key strategy {key title description useForm logo website __typename} config {key value __typename} order isEnabled displayName selfRegistration domainWhitelist autoEnrollGroups __typename} __typename}}", - { - "login_token": login_token, - } - ) - .then( - (data) => Promise.resolve(data["authentication"]["activeStrategies"]) - ) - ); - } - exports.call_authentication_strategy_list = call_authentication_strategy_list; - - - /** - */ - function call_authentication_strategy_set( - login_token, - strategies - ) - { - wiki_js.cli.helpers.log.write( - "info", - "api_call_authentication_strategy_set", - { - "strategies": strategies, - } - ); - return ( - call_generic_graphql( - "mutation ($strategies: [AuthenticationStrategyInput]!) {authentication {updateStrategies(strategies: $strategies) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", - { - "login_token": login_token, - "variables": { - "strategies": strategies, - } - } - ) - ); - } - exports.call_authentication_strategy_set = call_authentication_strategy_set; - - - /** - */ - function call_theming_set( - login_token, - dark_mode, - toc_position - ) - { - wiki_js.cli.helpers.log.write( - "info", - "api_call_theming_set", - { - "dark_mode": dark_mode, - "toc_position": toc_position, - } - ); - return ( - call_generic_graphql( - "mutation ($theme: String!, $iconset: String!, $darkMode: Boolean!, $tocPosition: String, $injectCSS: String, $injectHead: String, $injectBody: String) {theming {setConfig(theme: $theme, iconset: $iconset, darkMode: $darkMode, tocPosition: $tocPosition, injectCSS: $injectCSS, injectHead: $injectHead, injectBody: $injectBody) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", - { - "login_token": login_token, - "variables": { - "theme": "default", - "iconset": "mdi", - "darkMode": dark_mode, - "tocPosition": "left", - "injectCSS": "", - "injectHead": "", - "injectBody": "" - } - } - ) - ); - } - exports.call_theming_set = call_theming_set; - -}) (wiki_js.cli.api); - - -var wiki_js; -wiki_js = (wiki_js || {}); -wiki_js.cli = (wiki_js.cli || {}); -wiki_js.cli.logic = (wiki_js.cli.logic || {}); -(function (exports) { - - /** - */ - async function initialize( - admin_email_address, - admin_password, - options - ) - { - options = Object.assign( - { - "site_url": "http://localhost:3000", - "allow_telemetry": false, - }, - options - ); - const result = await wiki_js.cli.api.call_finalize( - admin_email_address, - admin_password, - options.site_url, - options.allow_telemetry - ); - return Promise.resolve(undefined); - } - exports.initialize = initialize; - - - /** - */ - async function email_settings_set( - smtp_host, - smtp_port, - smtp_username, - smtp_password, - sender_name, - sender_email_address, - options - ) - { - options = Object.assign( - { - }, - options - ); - const login_token = await wiki_js.cli.api.call_login_local( - ); - const result = await wiki_js.cli.api.call_email_settings_set( - login_token, - { - "sender_name": sender_name, - "sender_email_address": sender_email_address, - "smtp_host": smtp_host, - "smtp_port": smtp_port, - "secure": true, - "verify_ssl": true, - "smtp_username": smtp_username, - "smtp_password": smtp_password, - "name": "", - "use_dkim": false, - "dkim_domain_name": "", - "dkim_key_selector": "", - "dkim_private_key": "", - } - ); - return Promise.resolve(undefined); - } - exports.email_settings_set = email_settings_set; - - - /** - */ - async function group_identify( - name - ) - { - const data = await wiki_js.cli.api.call_group_list(); - const hits = ( - data["groups"]["list"] - .filter( - (entry) => (entry["name"] === name) - ) - ); - if (hits.length !== 1) { - return Promise.reject(new Error("not found or ambiguous")); - } - else { - return Promise.resolve(hits[0]["id"]); - } - } - exports.group_identify = group_identify; - - - /** - * returns the ID of the generated group - */ - async function group_add( - name, - options = {} - ) - { - options = Object.assign( - { - "permissions_general": [], - "permissions_specific": [], - }, - options - ); - const login_token = await wiki_js.cli.api.call_login_local( - ); - const result_1 = await wiki_js.cli.api.call_group_create( - login_token, - name - ); - const id = result_1["groups"]["create"]["group"]["id"]; - const result_2 = await wiki_js.cli.api.call_group_update( - login_token, - id, - name, - options.permissions_general, - options.permissions_specific - ); - return Promise.resolve(id); - } - exports.group_add = group_add; - - - /** - */ - async function group_modify( - id, - options = {} - ) - { - options = Object.assign( - { - "permissions_general": [], - "permissions_specific": [], - }, - options - ); - const login_token = await wiki_js.cli.api.call_login_local( - ); - const result = await wiki_js.cli.api.call_group_update( - login_token, - id, - name, - options.permissions_general, - options.permissions_specific - ); - return Promise.resolve(undefined); - } - exports.group_modify = group_modify; - - - /** - */ - async function authentication_strategy_list( - ) - { - const login_token = await wiki_js.cli.api.call_login_local( - ); - const result = await wiki_js.cli.api.call_authentication_strategy_list( - login_token - ); - return Promise.resolve(result); - } - exports.authentication_strategy_list = authentication_strategy_list; - - - /** - * @param strategy { - * { - * key:string; - * name:string; - * client_id:string; - * client_secret:string; - * authorization_url:string; - * token_url:string; - * user_info_url:string; - * group_assignments:Array; - * } - */ - async function authentication_strategy_add( - strategy - ) - { - const login_token = await wiki_js.cli.api.call_login_local( - ); - const current = await wiki_js.cli.api.call_authentication_strategy_list( - login_token - ); - const result = await wiki_js.cli.api.call_authentication_strategy_set( - login_token, - ( - ( - current - .map( - (entry) => ({ - "key": entry["key"], - "strategyKey": entry["strategy"]["key"], - "displayName": entry["displayName"], - "order": entry["order"], - "isEnabled": entry["isEnabled"], - "config": ( - entry["config"] - .map( - (item) => ({ - "key": item["key"], - "value": JSON.stringify({"v": JSON.parse(item["value"])["value"]}), - }) - ) - ), - "selfRegistration": entry["selfRegistration"], - "domainWhitelist": entry["domainWhitelist"], - "autoEnrollGroups": entry["autoEnrollGroups"], - }) - ) - ) - .concat( - [ - { - "key": strategy.key, - "strategyKey": "oauth2", - "displayName": strategy.name, - "order": ( - ( - current - .map(x => x["order"]) - .reduce((x,y) => (((x === null) || (x < y)) ? y : x), null) - ) - + - 1 - ), - "isEnabled": true, - "config": [ - { - "key": "clientId", - "value": JSON.stringify({"v": strategy.client_id}), - }, - { - "key": "clientSecret", - "value": JSON.stringify({"v": strategy.client_secret}), - }, - { - "key": "authorizationURL", - "value": JSON.stringify({"v": strategy.authorization_url}), - }, - { - "key": "tokenURL", - "value": JSON.stringify({"v": strategy.token_url}), - }, - { - "key": "userInfoURL", - "value": JSON.stringify({"v": strategy.user_info_url}), - }, - { - "key": "userIdClaim", - "value": JSON.stringify({"v": "id"}), - }, - { - "key": "displayNameClaim", - "value": JSON.stringify({"v": "name"}), - }, - { - "key": "emailClaim", - "value": JSON.stringify({"v": "email"}), - }, - { - "key": "mapGroups", - "value": JSON.stringify({"v": false}), - }, - { - "key": "groupsClaim", - "value": JSON.stringify({"v": "groups"}), - }, - { - "key": "logoutURL", - "value": JSON.stringify({"v": ""}), - }, - { - "key": "scope", - "value": JSON.stringify({"v": "openid profile email"}), - }, - { - "key": "useQueryStringForAccessToken", - "value": JSON.stringify({"v": false}), - }, - { - "key": "enableCSRFProtection", - "value": JSON.stringify({"v": true}), - } - ], - "selfRegistration": true, - "domainWhitelist": [], - "autoEnrollGroups": ( - strategy.group_assignments - .map(x => group_identify(x)) - ), - }, - ] - ) - ) - ); - return Promise.resolve(undefined); - } - exports.authentication_strategy_add = authentication_strategy_add; - - - /** - */ - async function theming_set( - options = {} - ) - { - options = Object.assign( - { - "dark_mode": false, - "toc_position": "left", - }, - options - ); - const login_token = await wiki_js.cli.api.call_login_local( - ); - const result = await wiki_js.cli.api.call_theming_set( - login_token, - options.dark_mode, - options.toc_position - ); - return Promise.resolve(result); - } - exports.theming_set = theming_set; - -}) (wiki_js.cli.logic); - - -var wiki_js; -wiki_js = (wiki_js || {}); -wiki_js.cli = (wiki_js.cli || {}); -(function (exports) { - - /** - */ - async function main( - args_raw - ) - { - // args - const args = wiki_js.cli.helpers.args.parse(args_raw); - const override_url_base = ( - ( - ("b" in args.volatile) - && - (args.volatile["b"].length >= 0) - ) - ? - args.volatile["b"][0] - : - null - ); - const override_username = ( - ( - ("u" in args.volatile) - && - (args.volatile["u"].length >= 0) - ) - ? - args.volatile["u"][0] - : - null - ); - const override_password = ( - ( - ("p" in args.volatile) - && - (args.volatile["p"].length >= 0) - ) - ? - args.volatile["p"][0] - : - null - ); - - // conf - const conf_path = ( - ( - ("c" in args.volatile) - && - (args.volatile["c"].length >= 0) - ) - ? - args.volatile["c"][0] - : - null - ); - await wiki_js.cli.conf.load(conf_path); - let conf_override = wiki_js.cli.conf.get(); - ((override_url_base !== null) && (conf_override.api.url_base = override_url_base)); - ((override_username !== null) && (conf_override.login.username = override_username)); - ((override_password !== null) && (conf_override.login.password = override_password)); - wiki_js.cli.conf.set(conf_override); - wiki_js.cli.helpers.log.write( - "debug", - "conf", - wiki_js.cli.conf.get() - ); - - // init - wiki_js.cli.helpers.log.setup(wiki_js.cli.conf.get().log.threshold); - - // exec - if (args.positional.length < 1) { - return Promise.reject("SYNTAX: [node] cli.js [-c ] [-b ] [-u ] [-p ] [ [ […]]]\n\n\t = init | email-settings-set | group-add | auth-strat-list | auth-strat-add-oauth2 | theming-set"); - } - else { - const action = args.positional[0]; - switch (action) { - default: { - return Promise.reject("invalid action: " + action); - break; - } - case "init": { - if (args.positional.length <= 2) { - return Promise.reject("SYNTAX: … init [ []]"); - } - else { - await wiki_js.cli.logic.initialize( - args.positional[1], - args.positional[2], - { - "site_url": ( - (args.positional.length >= 4) - ? - args.positional[3] - : - undefined - ), - "allow_telemtry": ( - (args.positional.length >= 5) - ? - (args.positional[4] === "1") - : - undefined - ), - } - ); - return Promise.resolve(undefined); - } - break; - } - case "email-settings-set": { - if (args.positional.length <= 6) { - return Promise.reject("SYNTAX: … email-settings-set "); - } - else { - await wiki_js.cli.logic.email_settings_set( - args.positional[1], - parseInt(args.positional[2]), - args.positional[3], - args.positional[4], - args.positional[5], - args.positional[6], - { - } - ); - return Promise.resolve(undefined); - } - } - case "group-add": { - if (args.positional.length <= 1) { - return Promise.reject("SYNTAX: … group-add [ [ [ […]]]]"); - } - else { - const name = args.positional[1]; - const permissions = args.positional.slice(2); - const result = await wiki_js.cli.logic.group_add( - name, - { - "permissions_general": permissions, - "permissions_specific": [ - { - "id": "default", - "path": "", - "roles": permissions, - "match": "START", - "deny": false, - "locales": [] - } - ], - } - ); - process.stdout.write( - JSON.stringify( - result, - undefined, - "\t" - ) - + - "\n" - ); - } - break; - } - case "group-modify": { - if (args.positional.length <= 2) { - return Promise.reject("SYNTAX: … group-modify [ [ [ […]]]]"); - } - else { - const name = args.positional[1]; - const id = group_identify(name); - const permissions = args.positional.slice(2); - const result = await wiki_js.cli.logic.group_modify( - id, - { - "permissions_general": permissions, - "permissions_specific": [ - { - "id": "default", - "path": "", - "roles": permissions, - "match": "START", - "deny": false, - "locales": [] - } - ], - } - ); - } - break; - } - case "auth-strat-list": { - const result = await wiki_js.cli.logic.authentication_strategy_list(); - process.stdout.write( - JSON.stringify( - result, - undefined, - "\t" - ) - + - "\n" - ); - return Promise.resolve(undefined); - break; - } - case "auth-strat-add-oauth2": { - if (args.positional.length <= 7) { - return Promise.reject("SYNTAX: … auth-strat-add-oauth2 [ [ [ […]]]]"); - } - else { - await wiki_js.cli.logic.authentication_strategy_add( - { - "key": args.positional[1], - "name": args.positional[2], - "client_id": args.positional[3], - "client_secret": args.positional[4], - "authorization_url": args.positional[5], - "token_url": args.positional[6], - "user_info_url": args.positional[7], - "group_assignments": args.positional.slice(8), - } - ); - return Promise.resolve(undefined); - } - break; - } - case "theming-set": { - if (args.positional.length <= 2) { - return Promise.reject("SYNTAX: … theming-set []"); - } - else { - await wiki_js.cli.logic.theming_set( - { - "dark_mode": (args.positional[1] === "1"), - "toc_position": args.positional[2], - } - ); - return Promise.resolve(undefined); - } - break; - } - } - } - } - exports.main = main; - -}) (wiki_js.cli); - - -( - wiki_js.cli.main(process.argv.slice(2)) - .then( - () => { - } - ) - .catch( - (reason) => { - process.stderr.write("-- " + String(reason) + "\n"); - } - ) -); diff --git a/roles/wiki_js/files/wiki-js-cli b/roles/wiki_js/files/wiki-js-cli new file mode 100755 index 0000000..a8981b9 --- /dev/null +++ b/roles/wiki_js/files/wiki-js-cli @@ -0,0 +1,896 @@ +#!/usr/bin/env node +var _wiki_js_cli; +(function (_wiki_js_cli) { + var helpers; + (function (helpers) { + var string; + (function (string) { + /** + */ + function coin(template, arguments_) { + let result = template; + Object.entries(arguments_).forEach(([key, value]) => { + result = result.replace(new RegExp("{{" + key + "}}", "g"), value); + }); + return result; + } + string.coin = coin; + })(string = helpers.string || (helpers.string = {})); + })(helpers = _wiki_js_cli.helpers || (_wiki_js_cli.helpers = {})); +})(_wiki_js_cli || (_wiki_js_cli = {})); +var _wiki_js_cli; +(function (_wiki_js_cli) { + var helpers; + (function (helpers) { + var file; + (function (file) { + /** + */ + function read(path) { + const nm_fs = require("fs"); + return (new Promise((resolve, reject) => { + nm_fs.readFile(path, {}, (err, data) => { + if (err) { + reject(err); + } + else { + resolve(data.toString()); + } + }); + })); + } + file.read = read; + })(file = helpers.file || (helpers.file = {})); + })(helpers = _wiki_js_cli.helpers || (_wiki_js_cli.helpers = {})); +})(_wiki_js_cli || (_wiki_js_cli = {})); +var _wiki_js_cli; +(function (_wiki_js_cli) { + var helpers; + (function (helpers) { + var log; + (function (log) { + /** + */ + const _level_order = [ + "debug", + "info", + "notice", + "warning", + "error", + ]; + /** + */ + var _threshold = "info"; + /** + */ + function setup(threshold) { + _threshold = threshold; + } + log.setup = setup; + /** + */ + function write(level, incident, details) { + if (_level_order.indexOf(level) < _level_order.indexOf(_threshold)) { + // do nothing + } + else { + process.stderr.write(_wiki_js_cli.helpers.string.coin("\n<{{datetime}}> [{{level}}] {{incident}}\n{{details}}\n\n", { + "datetime": (new Date()).toISOString(), + "level": level, + "incident": incident, + "details": JSON.stringify(details, undefined, "\t"), + })); + } + } + log.write = write; + })(log = helpers.log || (helpers.log = {})); + })(helpers = _wiki_js_cli.helpers || (_wiki_js_cli.helpers = {})); +})(_wiki_js_cli || (_wiki_js_cli = {})); +var _wiki_js_cli; +(function (_wiki_js_cli) { + var helpers; + (function (helpers) { + var http; + (function (http) { + /** + */ + async function call(http_request) { + _wiki_js_cli.helpers.log.write("debug", "http_call_request", http_request); + const fetch_request = new Request(http_request.target, { + "method": http_request.method, + "headers": http_request.headers, + "body": http_request.body, + }); + const fetch_response = await fetch(fetch_request); + const http_response = { + "status_code": fetch_response.status, + "headers": fetch_response.headers, + "body": await fetch_response.text(), + }; + _wiki_js_cli.helpers.log.write("debug", "http_call_response", http_response); + return http_response; + } + http.call = call; + })(http = helpers.http || (helpers.http = {})); + })(helpers = _wiki_js_cli.helpers || (_wiki_js_cli.helpers = {})); +})(_wiki_js_cli || (_wiki_js_cli = {})); +var _wiki_js_cli; +(function (_wiki_js_cli) { + var helpers; + (function (helpers) { + var args; + (function (args) { + /** + */ + function parse(args_raw) { + let result = { + "positional": [], + "volatile": {}, + }; + let state = "free"; + let key = null; + args_raw.forEach((arg_raw) => { + switch (state) { + case "free": { + if (arg_raw.startsWith("-")) { + key = arg_raw.slice(1); + state = "bound"; + } + else { + if (key === null) { + result.positional.push(arg_raw); + key = null; + state = "free"; + } + else { + _wiki_js_cli.helpers.log.write("warning", "arg_discarded", { + "arg_raw": arg_raw, + }); + key = null; + state = "free"; + } + } + break; + } + case "bound": { + if (!(key in result["volatile"])) { + result["volatile"][key] = []; + } + else { + // do nothing + } + result["volatile"][key].push(arg_raw); + key = null; + state = "free"; + } + } + }); + return result; + } + args.parse = parse; + })(args = helpers.args || (helpers.args = {})); + })(helpers = _wiki_js_cli.helpers || (_wiki_js_cli.helpers = {})); +})(_wiki_js_cli || (_wiki_js_cli = {})); +var _wiki_js_cli; +(function (_wiki_js_cli) { + var conf; + (function (conf) { + /** + */ + var _data = null; + /** + */ + async function load(path) { + let data_raw; + if (path === null) { + data_raw = {}; + } + else { + const content = await _wiki_js_cli.helpers.file.read(path); + data_raw = JSON.parse(content); + } + _wiki_js_cli.helpers.log.write("debug", "conf_raw", data_raw); + _data = { + "api": { + "url_base": (data_raw?.api?.url_base + ?? + "http://localhost:3000"), + }, + "login": { + "username": (data_raw?.login?.username + ?? + "admin"), + "password": (data_raw?.login?.password + ?? + "admin"), + }, + "log": { + "threshold": (data_raw?.log?.threshold + ?? + "info"), + } + }; + return Promise.resolve(undefined); + } + conf.load = load; + /** + */ + function set(data) { + _data = data; + } + conf.set = set; + /** + */ + function get() { + return _data; + } + conf.get = get; + })(conf = _wiki_js_cli.conf || (_wiki_js_cli.conf = {})); +})(_wiki_js_cli || (_wiki_js_cli = {})); +var _wiki_js_cli; +(function (_wiki_js_cli) { + var api; + (function (api) { + /** + */ + var _login_token = null; + /** + */ + var _url_base = null; + /** + */ + function init(url_base) { + _url_base = url_base; + return Promise.resolve(undefined); + } + api.init = init; + /** + */ + async function call_generic_graphql(graphql_query, options) { + options = Object.assign({ + "variables": {}, + }, options); + const http_request = { + "target": (_url_base + "/graphql"), + "method": "POST", + "headers": Object.assign({ + "Content-Type": "application/json", + }, ((_login_token === null) + ? + {} + : + { "Cookie": ("jwt=" + _login_token) })), + "body": JSON.stringify([ + { + "operationName": null, + "variables": options.variables, + "extensions": {}, + "query": graphql_query, + } + ]), + }; + const http_response = await _wiki_js_cli.helpers.http.call(http_request); + const data = JSON.parse(http_response.body); + return Promise.resolve(data[0]["data"]); + } + /** + */ + async function call_finalize(admin_email, admin_password, site_url, telemetry) { + const http_request = { + "target": (_wiki_js_cli.conf.get().api.url_base + "/finalize"), + "method": "POST", + "headers": { + "Content-Type": "application/json", + }, + "body": JSON.stringify({ + "adminEmail": admin_email, + "adminPassword": admin_password, + "adminPasswordConfirm": admin_password, + "siteUrl": site_url, + "telemetry": telemetry, + }), + }; + const http_response = await _wiki_js_cli.helpers.http.call(http_request); + const data = JSON.parse(http_response.body); + return Promise.resolve(undefined); + } + api.call_finalize = call_finalize; + /** + * executes a local login + */ + async function call_login_local(username, password) { + _wiki_js_cli.helpers.log.write("info", "api_call_login_local", {}); + return (call_generic_graphql("mutation ($username: String!, $password: String!, $strategy: String!) {authentication {login(username: $username, password: $password, strategy: $strategy) {responseResult {succeeded errorCode slug message __typename} jwt mustChangePwd mustProvideTFA mustSetupTFA continuationToken redirect tfaQRImage __typename} __typename}}", { + "variables": { + "strategy": "local", + "username": username, + "password": password, + } + }) + .then((data) => { + if (data["authentication"]["login"]["responseResult"]["succeeded"]) { + _login_token = data["authentication"]["login"]["jwt"]; + return Promise.resolve(undefined); + } + else { + return Promise.reject(new Error("login failed")); + } + })); + } + api.call_login_local = call_login_local; + /** + */ + function call_email_settings_set(settings) { + _wiki_js_cli.helpers.log.write("info", "api_call_email_settings_set", { + "settings": settings, + }); + return (call_generic_graphql("mutation ($senderName: String!, $senderEmail: String!, $host: String!, $port: Int!, $name: String!, $secure: Boolean!, $verifySSL: Boolean!, $user: String!, $pass: String!, $useDKIM: Boolean!, $dkimDomainName: String!, $dkimKeySelector: String!, $dkimPrivateKey: String!) {mail {updateConfig(senderName: $senderName, senderEmail: $senderEmail, host: $host, port: $port, name: $name, secure: $secure, verifySSL: $verifySSL, user: $user, pass: $pass, useDKIM: $useDKIM, dkimDomainName: $dkimDomainName, dkimKeySelector: $dkimKeySelector, dkimPrivateKey: $dkimPrivateKey) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", { + "variables": { + "senderName": settings.sender_name, + "senderEmail": settings.sender_email_address, + "host": settings.smtp_host, + "port": settings.smtp_port, + "name": settings.name, + "secure": settings.secure, + "verifySSL": settings.verify_ssl, + "user": settings.smtp_username, + "pass": settings.smtp_password, + "useDKIM": settings.use_dkim, + "dkimDomainName": settings.dkim_domain_name, + "dkimKeySelector": settings.dkim_key_selector, + "dkimPrivateKey": settings.dkim_private_key, + } + })); + } + api.call_email_settings_set = call_email_settings_set; + /** + */ + function call_locale_download(locale) { + _wiki_js_cli.helpers.log.write("info", "api_call_locale_download", { + "locale": locale, + }); + return (call_generic_graphql("mutation ($locale: String!) {localization {downloadLocale(locale: $locale) {responseResult {succeeded errorCode slug message __typename} __typename}__typename}}", { + "variables": { + "locale": locale, + } + })); + } + api.call_locale_download = call_locale_download; + /** + */ + function call_group_list(name) { + _wiki_js_cli.helpers.log.write("info", "api_call_group_list", {}); + return (call_generic_graphql("{groups {list {id name isSystem userCount createdAt updatedAt __typename} __typename}}", { + "variables": {} + })); + } + api.call_group_list = call_group_list; + /** + */ + function call_group_create(name) { + _wiki_js_cli.helpers.log.write("info", "api_call_group_create", { + "name": name, + }); + return (call_generic_graphql("mutation ($name: String!) {groups {create(name: $name) {responseResult {succeeded errorCode slug message __typename} group {id name createdAt updatedAt __typename} __typename} __typename}}", { + "variables": { + "name": name, + } + })); + } + api.call_group_create = call_group_create; + /** + * @param permissions_general { + * Array< + * string + * > + * } + * @param permissions_page_specific { + * Array< + * { + * id:string; + * path:string; + * roles:Array< + * string + * >; + * match:string; + * deny:boolean; + * locales:Array< + * string + * >; + * } + * > + * } + */ + function call_group_update(group_id, name, permissions_general, permissions_page_specific) { + _wiki_js_cli.helpers.log.write("info", "api_call_group_update", {}); + return (call_generic_graphql("mutation ($id: Int!, $name: String!, $redirectOnLogin: String!, $permissions: [String]!, $pageRules: [PageRuleInput]!) {groups {update(id: $id, name: $name, redirectOnLogin: $redirectOnLogin, permissions: $permissions, pageRules: $pageRules) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", { + "variables": { + "id": group_id, + "name": name, + "redirectOnLogin": "/", + "permissions": permissions_general, + "pageRules": permissions_page_specific, + } + })); + } + api.call_group_update = call_group_update; + /** + */ + function call_authentication_strategy_list() { + _wiki_js_cli.helpers.log.write("info", "api_call_authentication_strategy_list", {}); + return (call_generic_graphql("{authentication {activeStrategies {key strategy {key title description useForm logo website __typename} config {key value __typename} order isEnabled displayName selfRegistration domainWhitelist autoEnrollGroups __typename} __typename}}", {}) + .then((data) => Promise.resolve(data["authentication"]["activeStrategies"]))); + } + api.call_authentication_strategy_list = call_authentication_strategy_list; + /** + */ + function call_authentication_strategy_set(strategies) { + _wiki_js_cli.helpers.log.write("info", "api_call_authentication_strategy_set", { + "strategies": strategies, + }); + return (call_generic_graphql("mutation ($strategies: [AuthenticationStrategyInput]!) {authentication {updateStrategies(strategies: $strategies) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", { + "variables": { + "strategies": strategies, + } + })); + } + api.call_authentication_strategy_set = call_authentication_strategy_set; + /** + */ + function call_theming_set(dark_mode, toc_position) { + _wiki_js_cli.helpers.log.write("info", "api_call_theming_set", { + "dark_mode": dark_mode, + "toc_position": toc_position, + }); + return (call_generic_graphql("mutation ($theme: String!, $iconset: String!, $darkMode: Boolean!, $tocPosition: String, $injectCSS: String, $injectHead: String, $injectBody: String) {theming {setConfig(theme: $theme, iconset: $iconset, darkMode: $darkMode, tocPosition: $tocPosition, injectCSS: $injectCSS, injectHead: $injectHead, injectBody: $injectBody) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", { + "variables": { + "theme": "default", + "iconset": "mdi", + "darkMode": dark_mode, + "tocPosition": "left", + "injectCSS": "", + "injectHead": "", + "injectBody": "" + } + })); + } + api.call_theming_set = call_theming_set; + })(api = _wiki_js_cli.api || (_wiki_js_cli.api = {})); +})(_wiki_js_cli || (_wiki_js_cli = {})); +var _wiki_js_cli; +(function (_wiki_js_cli) { + var logic; + (function (logic) { + /** + */ + async function login(options = {}) { + options = Object.assign({ + "username": _wiki_js_cli.conf.get().login.username, + "password": _wiki_js_cli.conf.get().login.password, + }, options); + await _wiki_js_cli.api.call_login_local(options.username, options.password); + return Promise.resolve(undefined); + } + logic.login = login; + /** + */ + async function initialize(admin_email_address, admin_password, options = {}) { + options = Object.assign({ + "site_url": "http://localhost:3000", + "allow_telemetry": false, + }, options); + await _wiki_js_cli.api.call_finalize(admin_email_address, admin_password, options.site_url, options.allow_telemetry); + return Promise.resolve(undefined); + } + logic.initialize = initialize; + /** + */ + async function email_settings_set(smtp_host, smtp_port, smtp_username, smtp_password, sender_name, sender_email_address, options = {}) { + options = Object.assign({}, options); + const result = await _wiki_js_cli.api.call_email_settings_set({ + "sender_name": sender_name, + "sender_email_address": sender_email_address, + "smtp_host": smtp_host, + "smtp_port": smtp_port, + "secure": true, + "verify_ssl": true, + "smtp_username": smtp_username, + "smtp_password": smtp_password, + "name": "", + "use_dkim": false, + "dkim_domain_name": "", + "dkim_key_selector": "", + "dkim_private_key": "", + }); + return Promise.resolve(undefined); + } + logic.email_settings_set = email_settings_set; + /** + */ + async function locale_add(locale_code) { + _wiki_js_cli.api.call_locale_download(locale_code); + return Promise.resolve(undefined); + } + logic.locale_add = locale_add; + /** + */ + async function group_identify(name) { + const data = await _wiki_js_cli.api.call_group_list(name); + const hits = (data["groups"]["list"] + .filter((entry) => (entry["name"] === name))); + if (hits.length !== 1) { + return Promise.reject(new Error("not found or ambiguous")); + } + else { + return Promise.resolve(hits[0]["id"]); + } + } + logic.group_identify = group_identify; + /** + * returns the ID of the generated group + */ + async function group_add(name, options = {}) { + options = Object.assign({ + "permissions_general": [], + "permissions_specific": [], + }, options); + const result_1 = await _wiki_js_cli.api.call_group_create(name); + const id = result_1["groups"]["create"]["group"]["id"]; + const result_2 = await _wiki_js_cli.api.call_group_update(id, name, options.permissions_general, options.permissions_specific); + return Promise.resolve(id); + } + logic.group_add = group_add; + /** + */ + async function group_modify(id, options = {}) { + options = Object.assign({ + "permissions_general": [], + "permissions_specific": [], + }, options); + const result = await _wiki_js_cli.api.call_group_update(id, name, options.permissions_general, options.permissions_specific); + return Promise.resolve(undefined); + } + logic.group_modify = group_modify; + /** + */ + async function authentication_strategy_list() { + const result = await _wiki_js_cli.api.call_authentication_strategy_list(); + return Promise.resolve(result); + } + logic.authentication_strategy_list = authentication_strategy_list; + /** + */ + async function authentication_strategy_add(strategy) { + const current = await _wiki_js_cli.api.call_authentication_strategy_list(); + const result = await _wiki_js_cli.api.call_authentication_strategy_set(((current + .map((entry) => ({ + "key": entry["key"], + "strategyKey": entry["strategy"]["key"], + "displayName": entry["displayName"], + "order": entry["order"], + "isEnabled": entry["isEnabled"], + "config": (entry["config"] + .map((item) => ({ + "key": item["key"], + "value": JSON.stringify({ "v": JSON.parse(item["value"])["value"] }), + }))), + "selfRegistration": entry["selfRegistration"], + "domainWhitelist": entry["domainWhitelist"], + "autoEnrollGroups": entry["autoEnrollGroups"], + }))) + .concat([ + { + "key": strategy.key, + "strategyKey": "oauth2", + "displayName": strategy.name, + "order": ((current + .map(x => x["order"]) + .reduce((x, y) => (((x === null) || (x < y)) ? y : x), null)) + + + 1), + "isEnabled": true, + "config": [ + { + "key": "clientId", + "value": JSON.stringify({ "v": strategy.client_id }), + }, + { + "key": "clientSecret", + "value": JSON.stringify({ "v": strategy.client_secret }), + }, + { + "key": "authorizationURL", + "value": JSON.stringify({ "v": strategy.authorization_url }), + }, + { + "key": "tokenURL", + "value": JSON.stringify({ "v": strategy.token_url }), + }, + { + "key": "userInfoURL", + "value": JSON.stringify({ "v": strategy.user_info_url }), + }, + { + "key": "userIdClaim", + "value": JSON.stringify({ "v": "id" }), + }, + { + "key": "displayNameClaim", + "value": JSON.stringify({ "v": "name" }), + }, + { + "key": "emailClaim", + "value": JSON.stringify({ "v": "email" }), + }, + { + "key": "mapGroups", + "value": JSON.stringify({ "v": false }), + }, + { + "key": "groupsClaim", + "value": JSON.stringify({ "v": "groups" }), + }, + { + "key": "logoutURL", + "value": JSON.stringify({ "v": "" }), + }, + { + "key": "scope", + "value": JSON.stringify({ "v": "openid profile email" }), + }, + { + "key": "useQueryStringForAccessToken", + "value": JSON.stringify({ "v": false }), + }, + { + "key": "enableCSRFProtection", + "value": JSON.stringify({ "v": true }), + } + ], + "selfRegistration": true, + "domainWhitelist": [], + "autoEnrollGroups": await Promise.all(strategy.group_assignments + .map(x => group_identify(x))), + }, + ]))); + return Promise.resolve(undefined); + } + logic.authentication_strategy_add = authentication_strategy_add; + /** + */ + async function theming_set(options = {}) { + options = Object.assign({ + "dark_mode": false, + "toc_position": "left", + }, options); + const result = await _wiki_js_cli.api.call_theming_set(options.dark_mode, options.toc_position); + return Promise.resolve(result); + } + logic.theming_set = theming_set; + })(logic = _wiki_js_cli.logic || (_wiki_js_cli.logic = {})); +})(_wiki_js_cli || (_wiki_js_cli = {})); +var _wiki_js_cli; +(function (_wiki_js_cli) { + /** + */ + async function main(args_raw) { + // args + const args = _wiki_js_cli.helpers.args.parse(args_raw); + const override_url_base = ((("b" in args.volatile) + && + (args.volatile["b"].length >= 0)) + ? + args.volatile["b"][0] + : + null); + const override_username = ((("u" in args.volatile) + && + (args.volatile["u"].length >= 0)) + ? + args.volatile["u"][0] + : + null); + const override_password = ((("p" in args.volatile) + && + (args.volatile["p"].length >= 0)) + ? + args.volatile["p"][0] + : + null); + const override_log_level = ((("l" in args.volatile) + && + (args.volatile["l"].length >= 0)) + ? + args.volatile["l"][0] + : + null); + // conf + const conf_path = ((("c" in args.volatile) + && + (args.volatile["c"].length >= 0)) + ? + args.volatile["c"][0] + : + null); + await _wiki_js_cli.conf.load(conf_path); + _wiki_js_cli.helpers.log.write("debug", "conf", _wiki_js_cli.conf.get()); + // init + _wiki_js_cli.helpers.log.setup(override_log_level ?? _wiki_js_cli.conf.get().log.threshold); + await _wiki_js_cli.api.init((override_url_base ?? _wiki_js_cli.conf.get().api.url_base)); + // exec + if (args.positional.length < 1) { + return Promise.reject("SYNTAX: [node] cli.js [-c ] [-b ] [-u ] [-p ] [ [ […]]]\n\n\t = init | email-settings-set | locale-add | group-add | group-modify | auth-strat-add-oauth2 | theming-set"); + } + else { + const action = args.positional[0]; + switch (action) { + default: { + return Promise.reject("invalid action: " + action); + break; + } + case "init": { + if (args.positional.length <= 2) { + return Promise.reject("SYNTAX: … init [ []]"); + } + else { + await _wiki_js_cli.logic.initialize(args.positional[1], args.positional[2], { + "site_url": ((args.positional.length >= 4) + ? + args.positional[3] + : + undefined), + "allow_telemetry": ((args.positional.length >= 5) + ? + (args.positional[4] === "1") + : + undefined), + }); + return Promise.resolve(undefined); + } + break; + } + case "email-settings-set": { + if (args.positional.length <= 6) { + return Promise.reject("SYNTAX: … email-settings-set "); + } + else { + await _wiki_js_cli.logic.login({ + "username": override_username, + "password": override_password, + }); + await _wiki_js_cli.logic.email_settings_set(args.positional[1], parseInt(args.positional[2]), args.positional[3], args.positional[4], args.positional[5], args.positional[6], {}); + return Promise.resolve(undefined); + } + break; + } + case "locale-add": { + if (args.positional.length <= 1) { + return Promise.reject("SYNTAX: … locale-add "); + } + else { + await _wiki_js_cli.logic.login({ + "username": override_username, + "password": override_password, + }); + await _wiki_js_cli.logic.locale_add(args.positional[1]); + return Promise.resolve(undefined); + } + break; + } + case "group-add": { + if (args.positional.length <= 1) { + return Promise.reject("SYNTAX: … group-add [ [ [ […]]]]"); + } + else { + const name = args.positional[1]; + const permissions = args.positional.slice(2); + await _wiki_js_cli.logic.login({ + "username": override_username, + "password": override_password, + }); + const result = await _wiki_js_cli.logic.group_add(name, { + "permissions_general": permissions, + "permissions_specific": [ + { + "id": "default", + "path": "", + "roles": permissions, + "match": "START", + "deny": false, + "locales": [] + } + ], + }); + process.stdout.write(JSON.stringify(result, undefined, "\t") + + + "\n"); + } + break; + } + case "group-modify": { + if (args.positional.length <= 2) { + return Promise.reject("SYNTAX: … group-modify [ [ [ […]]]]"); + } + else { + const name = args.positional[1]; + const permissions = args.positional.slice(2); + const id = await _wiki_js_cli.logic.group_identify(name); + await _wiki_js_cli.logic.login({ + "username": override_username, + "password": override_password, + }); + const result = await _wiki_js_cli.logic.group_modify(id, { + "permissions_general": permissions, + "permissions_specific": [ + { + "id": "default", + "path": "", + "roles": permissions, + "match": "START", + "deny": false, + "locales": [] + } + ], + }); + } + break; + } + case "auth-strat-add-oauth2": { + if (args.positional.length <= 7) { + return Promise.reject("SYNTAX: … auth-strat-add-oauth2 [ [ [ […]]]]"); + } + else { + await _wiki_js_cli.logic.login({ + "username": override_username, + "password": override_password, + }); + await _wiki_js_cli.logic.authentication_strategy_add({ + "key": args.positional[1], + "name": args.positional[2], + "client_id": args.positional[3], + "client_secret": args.positional[4], + "authorization_url": args.positional[5], + "token_url": args.positional[6], + "user_info_url": args.positional[7], + "group_assignments": args.positional.slice(8), + }); + return Promise.resolve(undefined); + } + break; + } + case "theming-set": { + if (args.positional.length <= 1) { + return Promise.reject("SYNTAX: … theming-set []"); + } + else { + await _wiki_js_cli.logic.login({ + "username": override_username, + "password": override_password, + }); + await _wiki_js_cli.logic.theming_set({ + "dark_mode": (args.positional[1] === "1"), + "toc_position": ((args.positional.length <= 2) + ? + "left" + : + ((args.positional[2] === "right") + ? + "right" + : + "left")), + }); + return Promise.resolve(undefined); + } + break; + } + } + } + } + _wiki_js_cli.main = main; +})(_wiki_js_cli || (_wiki_js_cli = {})); +(_wiki_js_cli.main(process.argv.slice(2)) + .then(() => { +}) + .catch((reason) => { + process.stderr.write("-- " + String(reason) + "\n"); +})); diff --git a/roles/wiki_js/tasks/main.json b/roles/wiki_js/tasks/main.json index 9c5ecfd..2572af3 100644 --- a/roles/wiki_js/tasks/main.json +++ b/roles/wiki_js/tasks/main.json @@ -52,10 +52,9 @@ { "name": "cli client", "become": true, - "become_user": "{{var_wiki_js_user}}", "ansible.builtin.copy": { - "src": "cli.js", - "dest": "{{var_wiki_js_directory}}/cli.js", + "src": "wiki-js-cli", + "dest": "/usr/local/bin/wiki-js-cli", "mode": "0700" } }, From e6ee5fb35fbf9141033c11b0949dfc1479b5f898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Mon, 30 Sep 2024 09:51:07 +0200 Subject: [PATCH 09/10] [mod] role:wiki_js --- roles/wiki_js/defaults/main.json | 4 +- roles/wiki_js/files/wiki-js-cli | 195 ++++++++++++++++++++----------- roles/wiki_js/info.md | 5 + roles/wiki_js/tasks/main.json | 16 +-- roles/wiki_js/vardef.json | 8 ++ 5 files changed, 153 insertions(+), 75 deletions(-) diff --git a/roles/wiki_js/defaults/main.json b/roles/wiki_js/defaults/main.json index 6e94256..2de7c99 100644 --- a/roles/wiki_js/defaults/main.json +++ b/roles/wiki_js/defaults/main.json @@ -30,5 +30,7 @@ "var_wiki_js_admin_password": "REPLACE_ME", "var_wiki_js_additional_locales": [], "var_wiki_js_user_group_name": "Default", - "var_wiki_js_allow_guest_view": true + "var_wiki_js_allow_guest_view": true, + "var_wiki_js_dark_mode": false, + "var_wiki_js_toc_position": "left" } diff --git a/roles/wiki_js/files/wiki-js-cli b/roles/wiki_js/files/wiki-js-cli index a8981b9..5ae027b 100755 --- a/roles/wiki_js/files/wiki-js-cli +++ b/roles/wiki_js/files/wiki-js-cli @@ -49,22 +49,33 @@ var _wiki_js_cli; (function (helpers) { var log; (function (log) { + /** + */ + let enum_level; + (function (enum_level) { + enum_level["debug"] = "debug"; + enum_level["info"] = "info"; + enum_level["notice"] = "notice"; + enum_level["warning"] = "warning"; + enum_level["error"] = "error"; + })(enum_level = log.enum_level || (log.enum_level = {})); /** */ const _level_order = [ - "debug", - "info", - "notice", - "warning", - "error", + enum_level.debug, + enum_level.info, + enum_level.notice, + enum_level.warning, + enum_level.error, ]; /** */ - var _threshold = "info"; + var _threshold = enum_level.info; /** */ function setup(threshold) { _threshold = threshold; + return Promise.resolve(undefined); } log.setup = setup; /** @@ -95,7 +106,7 @@ var _wiki_js_cli; /** */ async function call(http_request) { - _wiki_js_cli.helpers.log.write("debug", "http_call_request", http_request); + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.debug, "http_call_request", http_request); const fetch_request = new Request(http_request.target, { "method": http_request.method, "headers": http_request.headers, @@ -104,10 +115,10 @@ var _wiki_js_cli; const fetch_response = await fetch(fetch_request); const http_response = { "status_code": fetch_response.status, - "headers": fetch_response.headers, + "headers": Object.fromEntries(fetch_response.headers.entries()), "body": await fetch_response.text(), }; - _wiki_js_cli.helpers.log.write("debug", "http_call_response", http_response); + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.debug, "http_call_response", http_response); return http_response; } http.call = call; @@ -143,7 +154,7 @@ var _wiki_js_cli; state = "free"; } else { - _wiki_js_cli.helpers.log.write("warning", "arg_discarded", { + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.warning, "arg_discarded", { "arg_raw": arg_raw, }); key = null; @@ -189,7 +200,7 @@ var _wiki_js_cli; const content = await _wiki_js_cli.helpers.file.read(path); data_raw = JSON.parse(content); } - _wiki_js_cli.helpers.log.write("debug", "conf_raw", data_raw); + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.debug, "conf_raw", data_raw); _data = { "api": { "url_base": (data_raw?.api?.url_base @@ -299,7 +310,7 @@ var _wiki_js_cli; * executes a local login */ async function call_login_local(username, password) { - _wiki_js_cli.helpers.log.write("info", "api_call_login_local", {}); + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.info, "api_call_login_local", {}); return (call_generic_graphql("mutation ($username: String!, $password: String!, $strategy: String!) {authentication {login(username: $username, password: $password, strategy: $strategy) {responseResult {succeeded errorCode slug message __typename} jwt mustChangePwd mustProvideTFA mustSetupTFA continuationToken redirect tfaQRImage __typename} __typename}}", { "variables": { "strategy": "local", @@ -321,7 +332,7 @@ var _wiki_js_cli; /** */ function call_email_settings_set(settings) { - _wiki_js_cli.helpers.log.write("info", "api_call_email_settings_set", { + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.info, "api_call_email_settings_set", { "settings": settings, }); return (call_generic_graphql("mutation ($senderName: String!, $senderEmail: String!, $host: String!, $port: Int!, $name: String!, $secure: Boolean!, $verifySSL: Boolean!, $user: String!, $pass: String!, $useDKIM: Boolean!, $dkimDomainName: String!, $dkimKeySelector: String!, $dkimPrivateKey: String!) {mail {updateConfig(senderName: $senderName, senderEmail: $senderEmail, host: $host, port: $port, name: $name, secure: $secure, verifySSL: $verifySSL, user: $user, pass: $pass, useDKIM: $useDKIM, dkimDomainName: $dkimDomainName, dkimKeySelector: $dkimKeySelector, dkimPrivateKey: $dkimPrivateKey) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", { @@ -346,7 +357,7 @@ var _wiki_js_cli; /** */ function call_locale_download(locale) { - _wiki_js_cli.helpers.log.write("info", "api_call_locale_download", { + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.info, "api_call_locale_download", { "locale": locale, }); return (call_generic_graphql("mutation ($locale: String!) {localization {downloadLocale(locale: $locale) {responseResult {succeeded errorCode slug message __typename} __typename}__typename}}", { @@ -359,7 +370,7 @@ var _wiki_js_cli; /** */ function call_group_list(name) { - _wiki_js_cli.helpers.log.write("info", "api_call_group_list", {}); + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.info, "api_call_group_list", {}); return (call_generic_graphql("{groups {list {id name isSystem userCount createdAt updatedAt __typename} __typename}}", { "variables": {} })); @@ -368,7 +379,7 @@ var _wiki_js_cli; /** */ function call_group_create(name) { - _wiki_js_cli.helpers.log.write("info", "api_call_group_create", { + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.info, "api_call_group_create", { "name": name, }); return (call_generic_graphql("mutation ($name: String!) {groups {create(name: $name) {responseResult {succeeded errorCode slug message __typename} group {id name createdAt updatedAt __typename} __typename} __typename}}", { @@ -402,7 +413,7 @@ var _wiki_js_cli; * } */ function call_group_update(group_id, name, permissions_general, permissions_page_specific) { - _wiki_js_cli.helpers.log.write("info", "api_call_group_update", {}); + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.info, "api_call_group_update", {}); return (call_generic_graphql("mutation ($id: Int!, $name: String!, $redirectOnLogin: String!, $permissions: [String]!, $pageRules: [PageRuleInput]!) {groups {update(id: $id, name: $name, redirectOnLogin: $redirectOnLogin, permissions: $permissions, pageRules: $pageRules) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", { "variables": { "id": group_id, @@ -417,7 +428,7 @@ var _wiki_js_cli; /** */ function call_authentication_strategy_list() { - _wiki_js_cli.helpers.log.write("info", "api_call_authentication_strategy_list", {}); + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.info, "api_call_authentication_strategy_list", {}); return (call_generic_graphql("{authentication {activeStrategies {key strategy {key title description useForm logo website __typename} config {key value __typename} order isEnabled displayName selfRegistration domainWhitelist autoEnrollGroups __typename} __typename}}", {}) .then((data) => Promise.resolve(data["authentication"]["activeStrategies"]))); } @@ -425,7 +436,7 @@ var _wiki_js_cli; /** */ function call_authentication_strategy_set(strategies) { - _wiki_js_cli.helpers.log.write("info", "api_call_authentication_strategy_set", { + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.info, "api_call_authentication_strategy_set", { "strategies": strategies, }); return (call_generic_graphql("mutation ($strategies: [AuthenticationStrategyInput]!) {authentication {updateStrategies(strategies: $strategies) {responseResult {succeeded errorCode slug message __typename} __typename} __typename}}", { @@ -438,7 +449,7 @@ var _wiki_js_cli; /** */ function call_theming_set(dark_mode, toc_position) { - _wiki_js_cli.helpers.log.write("info", "api_call_theming_set", { + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.info, "api_call_theming_set", { "dark_mode": dark_mode, "toc_position": toc_position, }); @@ -447,7 +458,7 @@ var _wiki_js_cli; "theme": "default", "iconset": "mdi", "darkMode": dark_mode, - "tocPosition": "left", + "tocPosition": toc_position, "injectCSS": "", "injectHead": "", "injectBody": "" @@ -671,6 +682,33 @@ var _wiki_js_cli; })(_wiki_js_cli || (_wiki_js_cli = {})); var _wiki_js_cli; (function (_wiki_js_cli) { + /** + */ + function parse_boolean(indicator) { + if ((indicator === "1") + || + (indicator === "yes") + || + (indicator === "on") + || + (indicator === "true")) { + return true; + } + else { + if ((indicator === "0") + || + (indicator === "no") + || + (indicator === "off") + || + (indicator === "false")) { + return false; + } + else { + throw (new Error("invalid boolean indicator: " + indicator)); + } + } + } /** */ async function main(args_raw) { @@ -713,9 +751,9 @@ var _wiki_js_cli; : null); await _wiki_js_cli.conf.load(conf_path); - _wiki_js_cli.helpers.log.write("debug", "conf", _wiki_js_cli.conf.get()); + _wiki_js_cli.helpers.log.write(_wiki_js_cli.helpers.log.enum_level.debug, "conf", _wiki_js_cli.conf.get()); // init - _wiki_js_cli.helpers.log.setup(override_log_level ?? _wiki_js_cli.conf.get().log.threshold); + await _wiki_js_cli.helpers.log.setup(override_log_level ?? _wiki_js_cli.conf.get().log.threshold); await _wiki_js_cli.api.init((override_url_base ?? _wiki_js_cli.conf.get().api.url_base)); // exec if (args.positional.length < 1) { @@ -733,17 +771,21 @@ var _wiki_js_cli; return Promise.reject("SYNTAX: … init [ []]"); } else { - await _wiki_js_cli.logic.initialize(args.positional[1], args.positional[2], { - "site_url": ((args.positional.length >= 4) - ? - args.positional[3] - : - undefined), - "allow_telemetry": ((args.positional.length >= 5) - ? - (args.positional[4] === "1") - : - undefined), + const admin_email_address = args.positional[1]; + const admin_password = args.positional[2]; + const site_url = ((args.positional.length >= 4) + ? + args.positional[3] + : + undefined); + const allow_telemetry = ((args.positional.length >= 5) + ? + parse_boolean(args.positional[4]) + : + undefined); + await _wiki_js_cli.logic.initialize(admin_email_address, admin_password, { + "site_url": site_url, + "allow_telemetry": allow_telemetry }); return Promise.resolve(undefined); } @@ -754,11 +796,17 @@ var _wiki_js_cli; return Promise.reject("SYNTAX: … email-settings-set "); } else { + const smtp_host = args.positional[1]; + const smtp_port = parseInt(args.positional[2]); + const smtp_username = args.positional[3]; + const smtp_password = args.positional[4]; + const sender_name = args.positional[5]; + const sender_email_address = args.positional[6]; await _wiki_js_cli.logic.login({ "username": override_username, "password": override_password, }); - await _wiki_js_cli.logic.email_settings_set(args.positional[1], parseInt(args.positional[2]), args.positional[3], args.positional[4], args.positional[5], args.positional[6], {}); + await _wiki_js_cli.logic.email_settings_set(smtp_host, smtp_port, smtp_username, smtp_password, sender_name, sender_email_address, {}); return Promise.resolve(undefined); } break; @@ -768,22 +816,23 @@ var _wiki_js_cli; return Promise.reject("SYNTAX: … locale-add "); } else { + const locale_code = args.positional[1]; await _wiki_js_cli.logic.login({ "username": override_username, "password": override_password, }); - await _wiki_js_cli.logic.locale_add(args.positional[1]); + await _wiki_js_cli.logic.locale_add(locale_code); return Promise.resolve(undefined); } break; } case "group-add": { - if (args.positional.length <= 1) { - return Promise.reject("SYNTAX: … group-add [ [ [ […]]]]"); + if (args.positional.length <= 2) { + return Promise.reject("SYNTAX: … group-add "); } else { const name = args.positional[1]; - const permissions = args.positional.slice(2); + const permissions = args.positional[2].split(","); await _wiki_js_cli.logic.login({ "username": override_username, "password": override_password, @@ -809,11 +858,11 @@ var _wiki_js_cli; } case "group-modify": { if (args.positional.length <= 2) { - return Promise.reject("SYNTAX: … group-modify [ [ [ […]]]]"); + return Promise.reject("SYNTAX: … group-modify "); } else { const name = args.positional[1]; - const permissions = args.positional.slice(2); + const permissions = args.positional[2].split(","); const id = await _wiki_js_cli.logic.group_identify(name); await _wiki_js_cli.logic.login({ "username": override_username, @@ -836,15 +885,11 @@ var _wiki_js_cli; break; } case "auth-strat-add-oauth2": { - if (args.positional.length <= 7) { - return Promise.reject("SYNTAX: … auth-strat-add-oauth2 [ [ [ […]]]]"); + if (args.positional.length <= 8) { + return Promise.reject("SYNTAX: … auth-strat-add-oauth2 "); } else { - await _wiki_js_cli.logic.login({ - "username": override_username, - "password": override_password, - }); - await _wiki_js_cli.logic.authentication_strategy_add({ + const strategy = { "key": args.positional[1], "name": args.positional[2], "client_id": args.positional[3], @@ -852,8 +897,13 @@ var _wiki_js_cli; "authorization_url": args.positional[5], "token_url": args.positional[6], "user_info_url": args.positional[7], - "group_assignments": args.positional.slice(8), + "group_assignments": args.positional[8].split(","), + }; + await _wiki_js_cli.logic.login({ + "username": override_username, + "password": override_password, }); + await _wiki_js_cli.logic.authentication_strategy_add(strategy); return Promise.resolve(undefined); } break; @@ -863,23 +913,36 @@ var _wiki_js_cli; return Promise.reject("SYNTAX: … theming-set []"); } else { - await _wiki_js_cli.logic.login({ - "username": override_username, - "password": override_password, - }); - await _wiki_js_cli.logic.theming_set({ - "dark_mode": (args.positional[1] === "1"), - "toc_position": ((args.positional.length <= 2) - ? - "left" - : - ((args.positional[2] === "right") - ? - "right" - : - "left")), - }); - return Promise.resolve(undefined); + const dark_mode = parse_boolean(args.positional[1]); + const toc_position_raw = ((args.positional.length <= 2) + ? + "left" + : + args.positional[2]); + const toc_position = (() => { + switch (toc_position_raw) { + case "left": return "left"; + case "right": return "right"; + case "hidden": return "off"; + default: { + return null; + } + } + })(); + if (toc_position === null) { + return Promise.reject("invalid toc-position: " + toc_position_raw + "; valid values are: left,right,hidden"); + } + else { + await _wiki_js_cli.logic.login({ + "username": override_username, + "password": override_password, + }); + await _wiki_js_cli.logic.theming_set({ + "dark_mode": dark_mode, + "toc_position": toc_position, + }); + return Promise.resolve(undefined); + } } break; } diff --git a/roles/wiki_js/info.md b/roles/wiki_js/info.md index 9730dc5..7fa2df9 100644 --- a/roles/wiki_js/info.md +++ b/roles/wiki_js/info.md @@ -9,6 +9,11 @@ - [Wiki.js-Dokumentation | Konfiguration](https://docs.requarks.io/install/config) +## Anmerkungen + +- `files/wiki-js-cli` stammt aus einem kleinen Projekt von _roydfalk_ + + ## ToDo - start page diff --git a/roles/wiki_js/tasks/main.json b/roles/wiki_js/tasks/main.json index 2572af3..019b07a 100644 --- a/roles/wiki_js/tasks/main.json +++ b/roles/wiki_js/tasks/main.json @@ -120,7 +120,7 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} init {{var_wiki_js_admin_email_address}} {{var_wiki_js_admin_password}} https://{{var_wiki_js_domain}} 0" + "cmd": "/usr/local/bin/wiki-js-cli -b http://127.0.0.1:{{var_wiki_js_port | string}} init {{var_wiki_js_admin_email_address}} {{var_wiki_js_admin_password}} https://{{var_wiki_js_domain}} no" } }, { @@ -129,7 +129,7 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} email-settings-set {{var_wiki_js_smtp_host}} {{var_wiki_js_smtp_port}} {{var_wiki_js_smtp_username}} {{var_wiki_js_smtp_password}} {{email_sending_sender_name}} {{email_sending_sender_email_address}}" + "cmd": "/usr/local/bin/wiki-js-cli -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} email-settings-set {{var_wiki_js_smtp_host}} {{var_wiki_js_smtp_port}} {{var_wiki_js_smtp_username}} {{var_wiki_js_smtp_password}} {{email_sending_sender_name}} {{email_sending_sender_email_address}}" } }, { @@ -139,7 +139,7 @@ "loop": "{{var_wiki_js_additional_locales}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} locale-add {{item}}" + "cmd": "/usr/local/bin/wiki-js-cli -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} locale-add {{item}}" } }, { @@ -149,7 +149,7 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} group-modify Guests" + "cmd": "/usr/local/bin/wiki-js-cli -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} group-modify Guests" } }, { @@ -159,7 +159,7 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} group-modify Guests read:pages read:assets read:comments" + "cmd": "/usr/local/bin/wiki-js-cli -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} group-modify Guests read:pages read:assets read:comments" } }, { @@ -168,7 +168,7 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} group-add {{var_wiki_js_user_group_name}} read:pages read:assets read:comments write:comments write:pages manage:pages delete:pages write:styles write:scripts read:source read:history write:assets manage:assets manage:comments" + "cmd": "/usr/local/bin/wiki-js-cli -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} group-add {{var_wiki_js_user_group_name}} {{var_wiki_js_allow_guest_view | ternary('read:pages,read:assets,read:comments,write:comments,write:pages,manage:pages,delete:pages,write:styles,write:scripts,read:source,read:history,write:assets,manage:assets,manage:comments','')}}" } }, { @@ -178,7 +178,7 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} auth-strat-add-oauth2 {{var_wiki_js_authentication_data_authelia_provider_id}} {{var_wiki_js_authentication_data_authelia_provider_name}} {{var_wiki_js_authentication_data_authelia_client_id}} {{var_wiki_js_authentication_data_authelia_client_secret}} {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/authorization {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/token {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/userinfo {{var_wiki_js_user_group_name}}" + "cmd": "/usr/local/bin/wiki-js-cli -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} auth-strat-add-oauth2 {{var_wiki_js_authentication_data_authelia_provider_id}} {{var_wiki_js_authentication_data_authelia_provider_name}} {{var_wiki_js_authentication_data_authelia_client_id}} {{var_wiki_js_authentication_data_authelia_client_secret}} {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/authorization {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/token {{var_wiki_js_authentication_data_authelia_url_base}}/api/oidc/userinfo {{var_wiki_js_user_group_name}}" } }, { @@ -187,7 +187,7 @@ "become_user": "{{var_wiki_js_user}}", "ansible.builtin.command": { "chdir": "{{var_wiki_js_directory}}", - "cmd": "node cli.js -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} theming-set 1 left" + "cmd": "/usr/local/bin/wiki-js-cli -b http://127.0.0.1:{{var_wiki_js_port | string}} -u {{var_wiki_js_admin_email_address}} -p {{var_wiki_js_admin_password}} theming-set {{var_wiki_js_dark_mode | ternary('yes','no')}} {{var_wiki_js_toc_position}}" } } ] diff --git a/roles/wiki_js/vardef.json b/roles/wiki_js/vardef.json index 3b68b3f..6bb5756 100644 --- a/roles/wiki_js/vardef.json +++ b/roles/wiki_js/vardef.json @@ -150,5 +150,13 @@ "allow_guest_view": { "mandatory": false, "type": "boolean" + }, + "dark_mode": { + "mandatory": false, + "type": "boolean" + }, + "toc_position": { + "mandatory": false, + "type": "string" } } From 97622f5c7aa8792ac553e13118d6a77fc12b0cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Mon, 30 Sep 2024 10:15:40 +0200 Subject: [PATCH 10/10] =?UTF-8?q?[mod]=20role:wiki.js:info:cli-projekt-lin?= =?UTF-8?q?k=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- roles/wiki_js/info.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/wiki_js/info.md b/roles/wiki_js/info.md index 7fa2df9..0a44b8a 100644 --- a/roles/wiki_js/info.md +++ b/roles/wiki_js/info.md @@ -11,7 +11,7 @@ ## Anmerkungen -- `files/wiki-js-cli` stammt aus einem kleinen Projekt von _roydfalk_ +- `files/wiki-js-cli` stammt aus dem Projekt [wiki-js-cli](https://forgejo.linke.sx/misc/wiki-js-cli) ## ToDo