From 1a2ed6b377415b94c9fe10270e64b047d55fbf10 Mon Sep 17 00:00:00 2001 From: abdulmohsen Date: Wed, 1 May 2024 17:26:02 +0300 Subject: [PATCH] Compile the WebUI and response with it if webui is enabled. --- .dockerignore | 2 + Dockerfile | 10 +- FAQ.md | 28 +- config/config.php | 3 + container/files/Caddyfile | 14 +- frontend/assets/css/style.css | 4 + frontend/components/NoApi.vue | 14 + frontend/layouts/default.vue | 138 ++- frontend/nuxt.config.ts | 1 + frontend/package.json | 1 + frontend/pages/index.vue | 18 +- frontend/yarn.lock | 856 +++++++----------- src/Libs/Extends/RouterStrategy.php | 28 +- src/Libs/Initializer.php | 26 +- .../Middlewares/APIKeyRequiredMiddleware.php | 4 + src/Libs/Traits/APITraits.php | 6 +- 16 files changed, 590 insertions(+), 563 deletions(-) create mode 100644 frontend/components/NoApi.vue diff --git a/.dockerignore b/.dockerignore index 48d9f90d..29bd6798 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,3 +4,5 @@ ./var/* !./var/.gitignore .phpunit.result.cache +frontend/.nuxt +frontend/node_modules diff --git a/Dockerfile b/Dockerfile index 42e93d45..b152dc98 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,9 @@ +FROM node:lts-alpine as npm_builder + +WORKDIR /frontend +COPY frontend ./ +RUN yarn install --frozen-lockfile && npx nuxi@latest generate + FROM alpine:edge COPY --from=composer:2 /usr/bin/composer /opt/bin/composer @@ -35,9 +41,11 @@ RUN ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime && echo ${TZ} > /etc/timezo useradd -u ${USER_ID:-1000} -U -d /config -s /bin/bash user # Copy source code to container. -# COPY ./ /opt/app +# Copy frontend to public directory. +COPY --chown=app:app --from=npm_builder /frontend/exported/ /opt/app/public/exported/ + # Link PHP if needed. RUN if [ ! -f /usr/bin/php ]; then ln -s /usr/bin/php${PHP_V:3} /usr/bin/php; fi diff --git a/FAQ.md b/FAQ.md index bd22dc52..30d1c13d 100644 --- a/FAQ.md +++ b/FAQ.md @@ -315,6 +315,7 @@ These environment variables relates to the tool itself, you can load them via th | WS_TRUST_HEADER | string | Which header contain user true IP. | `X-Forwarded-For` | | WS_LIBRARY_SEGMENT | integer | Paginate backend library items request. Per request get total X number. | `1000` | | WS_CACHE_URL | string | Cache server URL. | `redis://127.0.0.1:6379` | +| WS_WEBUI_ENABLED | bool | Enable Web UI. | `false` | > [!IMPORTANT] > for environment variables that has `{TASK}` tag, you **MUST** replace it with one @@ -342,7 +343,8 @@ $ docker exec -ti watchstate console system:tasks The Webhook URL is backend specific, the request path is `/v1/api/backends/[BACKEND_NAME]/webhook?apikey=[APIKEY]`, Where `[BACKEND_NAME]` is the name of the backend you want to add webhook for, and `[APIKEY]` is the global api key -which you can get via the `system:apikey` command. Typically, the full path is `http://localhost:8080/v1/api/backends/[BACKEND_NAME]/webhook?apikey=[APIKEY]`. if the tool +which you can get via the `system:apikey` command. Typically, the full path +is `http://localhost:8080/v1/api/backends/[BACKEND_NAME]/webhook?apikey=[APIKEY]`. if the tool port is directly exposed or via the reverse proxy you have setup. If your media backend support sending headers then remove query parameter `?apikey=[APIKEY]`, and add this header @@ -540,7 +542,8 @@ https://watchstate.example.org { Set this environment variable in your `docker-compose.yaml` file `WS_DISABLE_CACHE` with value of `1`. to use external redis server you need to alter the value of `WS_CACHE_URL` environment variable. the format for this variable is `redis://host:port?password=auth&db=db_num`, for example to use redis from another container you could use -something like `redis://172.23.1.10:6379?password=my_secert_password&db=8`. We only support `redis` and API compatible alternative. +something like `redis://172.23.1.10:6379?password=my_secert_password&db=8`. We only support `redis` and API compatible +alternative. Once that done, restart the container. @@ -624,7 +627,8 @@ If everything is working correctly you should see something like this previous j ### I keep receiving this warning in log `INFO: Ignoring [xxx] Episode range, and treating it as single episode. Backend says it covers [00-00]`? -We recently added guard clause to prevent backends from sending possibly invalid episode ranges, as such if you see this, +We recently added guard clause to prevent backends from sending possibly invalid episode ranges, as such if you see +this, this likely means your backend mis-identified episodes range. By default, we allow an episode to cover up to 4 episodes. If this is not enough for your library content. fear not we have you covered you can increase the limit by running the @@ -644,17 +648,20 @@ to inform you about the issue. ### I Keep receiving [jellyfin] item [id: name] is marked as [played] vs local state [unplayed], However due to the remote item date [date] being older than the last backend sync date [date]. it was not considered as valid state. -Sadly, this is due to bug in jellyfin, where it marks the item as played without updating the LastPlayedDate, and as such, watchstate doesn't really know the item has changed since last sync. +Sadly, this is due to bug in jellyfin, where it marks the item as played without updating the LastPlayedDate, and as +such, watchstate doesn't really know the item has changed since last sync. Unfortunately, there is no way to fix this issue from our side for the `state:import` task as it working as intended. -However, we managed to somewhat implement a workaround for this issue using the webhooks feature as temporary fix. Until jellyfin devs fixes the issue. Please take look at +However, we managed to somewhat implement a workaround for this issue using the webhooks feature as temporary fix. Until +jellyfin devs fixes the issue. Please take look at the webhooks section to enable it. --- ### Bare metal installation -We officially only support the docker container, however for the brave souls who want to install the tool directly on their server, +We officially only support the docker container, however for the brave souls who want to install the tool directly on +their server, You can follow these steps. #### Requirements @@ -662,8 +669,10 @@ You can follow these steps. * [PHP 8.3](http://https://www.php.net/downloads.php) with both the `CLI` and `fpm` mode. * PHP Extensions `pdo`, `pdo-sqlite`, `mbstring`, `json`, `ctype`, `curl`, `redis`, `sodium` and `simplexml`. * [Composer](https://getcomposer.org/download/) for dependency management. -* [Redis-server](https://redis.io/) for caching or a compatible implementation that works with [php-redis](https://github.com/phpredis/phpredis). -* [Caddy](https://caddyserver.com/) for frontend handling. However, you can use whatever you like. As long as it has support for fastcgi. +* [Redis-server](https://redis.io/) for caching or a compatible implementation that works + with [php-redis](https://github.com/phpredis/phpredis). +* [Caddy](https://caddyserver.com/) for frontend handling. However, you can use whatever you like. As long as it has + support for fastcgi. #### Installation @@ -680,7 +689,8 @@ $ cd watchstate $ composer install --no-dev ``` -3. Create `.env` inside `./var/config/` if you need to change any of the environment variables refer to [Tool specific environment variables](#tool-specific-environment-variables) for more information. For example, +3. Create `.env` inside `./var/config/` if you need to change any of the environment variables refer + to [Tool specific environment variables](#tool-specific-environment-variables) for more information. For example, if your `redis` server is not on the same server or requires a password you can add the following to the `.env` file. ```dotenv diff --git a/config/config.php b/config/config.php index e5443ca6..096a448a 100644 --- a/config/config.php +++ b/config/config.php @@ -36,6 +36,9 @@ return (function () { 'backend' => '[a-zA-Z0-9_-]+', ], ], + 'webui' => [ + 'enabled' => (bool)env('WS_WEBUI_ENABLED', false), + ], 'database' => [ 'version' => 'v01', ], diff --git a/container/files/Caddyfile b/container/files/Caddyfile index 030f5a0a..1cabac59 100644 --- a/container/files/Caddyfile +++ b/container/files/Caddyfile @@ -9,18 +9,16 @@ http:// { header * ?X-Request-Id "{http.request.uuid}" + try_files {path} exported/{path} /index.php + php_fastcgi 127.0.0.1:9000 { trusted_proxies private_ranges env X_REQUEST_ID "{http.request.uuid}" } - log + file_server { + hide .* + } - # Disabled as workaround for arm/v7 build. - # - #log { - # format transform `{request>headers>X-Forwarded-For>[0]:request>remote_ip} - [{ts}] "{request>method} {request>uri} {request>proto}" {status} {size} "{request>headers>Referer>[0]}" "{request>headers>User-Agent>[0]}" - "{resp_headers>X-Request-Id>[0]}" - "{resp_headers>X-Application-Version>[0]}"` { - # time_format "02/Jan/2006:15:04:05 -0700" - # } - #} + log } diff --git a/frontend/assets/css/style.css b/frontend/assets/css/style.css index 11e8e42c..1909fcd3 100644 --- a/frontend/assets/css/style.css +++ b/frontend/assets/css/style.css @@ -107,3 +107,7 @@ hr { .is-paddingless { padding: 0 !important; } + +.is-bold { + font-weight: bold; +} diff --git a/frontend/components/NoApi.vue b/frontend/components/NoApi.vue new file mode 100644 index 00000000..da2399e5 --- /dev/null +++ b/frontend/components/NoApi.vue @@ -0,0 +1,14 @@ + + + diff --git a/frontend/layouts/default.vue b/frontend/layouts/default.vue index 78a4cd13..53053cba 100644 --- a/frontend/layouts/default.vue +++ b/frontend/layouts/default.vue @@ -1,6 +1,6 @@