finalizing the move to user/pass auth.
This commit is contained in:
242
FAQ.md
242
FAQ.md
@@ -1,57 +1,5 @@
|
||||
# FAQ
|
||||
|
||||
# How to find the API key?
|
||||
|
||||
There are two ways to locate the API key:
|
||||
|
||||
## Via `.env` file
|
||||
|
||||
The API key is stored in the following file `/config/config/.env`, Open the file and look for the line starting with:
|
||||
|
||||
```
|
||||
WS_API_KEY=random_string
|
||||
```
|
||||
|
||||
The value after the equals sign is your API key.
|
||||
|
||||
## Via command
|
||||
|
||||
You can also retrieve the API key by running the following command on the docker host machine:
|
||||
|
||||
```bash
|
||||
docker exec watchstate console system:apikey
|
||||
```
|
||||
|
||||
This command will show the following lines:
|
||||
|
||||
```
|
||||
Current API key:
|
||||
random_string
|
||||
```
|
||||
|
||||
The `random_string` is your API key.
|
||||
|
||||
----
|
||||
|
||||
# What Is the API key used for?
|
||||
|
||||
The API key is used to authenticate requests to the system and prevent unauthorized access.
|
||||
|
||||
It is required for all API endpoints, **except** the following:
|
||||
|
||||
```
|
||||
/v1/api/[user@backend_name]/webhook
|
||||
```
|
||||
|
||||
This webhook endpoint is open by default, unless you have enabled the `WS_SECURE_API_ENDPOINTS` environment variable.
|
||||
If enabled, the API key will also be required for webhook access.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The WebUI operates in standalone mode and is decoupled from the backend, so it requires the API key to fetch and
|
||||
> display data.
|
||||
|
||||
----
|
||||
|
||||
# How to enable scheduled/automatic tasks?
|
||||
|
||||
To turn on automatic import or export tasks:
|
||||
@@ -351,7 +299,7 @@ If there are no errors, the database has been repaired successfully. And you can
|
||||
|
||||
---
|
||||
|
||||
# Which external db ids `GUIDS` supported for Plex Media Server?
|
||||
# Which Providers id `GUIDs` supported for Plex Media Server?
|
||||
|
||||
* tvdb://(id) `New plex agent`
|
||||
* imdb://(id) `New plex agent`
|
||||
@@ -371,7 +319,7 @@ If there are no errors, the database has been repaired successfully. And you can
|
||||
|
||||
---
|
||||
|
||||
# Which external db ids supported for Jellyfin and Emby?
|
||||
# Which Providers id supported for Jellyfin and Emby?
|
||||
|
||||
* imdb://(id)
|
||||
* tvdb://(id)
|
||||
@@ -390,15 +338,14 @@ If there are no errors, the database has been repaired successfully. And you can
|
||||
|
||||
# Environment Variables
|
||||
|
||||
The recommended approach is for keys that starts with `WS_` use the `WebUI > Env` page, or `system:env` command via CLI.
|
||||
For other keys that aren't directly related to the tool, you **MUST** load them via container environment or
|
||||
the `compose.yaml` file.
|
||||
The recommended approach is for keys that starts with `WS_` use the `WebUI > Env` page. For other keys that aren't
|
||||
directly related to the tool, you **MUST** load them via container environment or the `compose.yaml` file.
|
||||
|
||||
to see list of loaded environment variables, click on `Env` page in the WebUI.
|
||||
|
||||
## Tool specific environment variables.
|
||||
## WatchState specific environment variables.
|
||||
|
||||
These environment variables relates to the tool itself, You should manage them via `WebUI > Env` page
|
||||
Should be added/managed via the `WebUI > Env` page.
|
||||
|
||||
| Key | Type | Description | Default |
|
||||
|-------------------------|---------|-------------------------------------------------------------------------|--------------------------|
|
||||
@@ -418,13 +365,11 @@ These environment variables relates to the tool itself, You should manage them v
|
||||
| WS_CACHE_URL | string | Cache server URL. | `redis://127.0.0.1:6379` |
|
||||
| WS_SECURE_API_ENDPOINTS | bool | Disregard the open route policy and require API key for all endpoints. | `false` |
|
||||
|
||||
> [!IMPORTANT]
|
||||
> [!NOTE]
|
||||
> for environment variables that has `{TASK}` tag, you **MUST** replace it with one of `IMPORT`, `EXPORT`, `BACKUP`,
|
||||
`PRUNE`, `INDEXES` or `VALIDATE`.
|
||||
|
||||
## Add tool specific environment variables
|
||||
|
||||
Go to the `Env` page, click `+` button, you will get list of all supported keys with description.
|
||||
>
|
||||
> Note, those are just sample of the environment variables, to see the entire, please visit the `Env` page in the WebUI.
|
||||
|
||||
## Container specific environment variables.
|
||||
|
||||
@@ -432,22 +377,18 @@ Go to the `Env` page, click `+` button, you will get list of all supported keys
|
||||
> These environment variables relates to the container itself, and MUST be added via container environment or by
|
||||
> the `compose.yaml` file.
|
||||
|
||||
| Key | Type | Description | Default |
|
||||
|---------------|---------|--------------------------------------|----------|
|
||||
| WEBUI_ENABLED | bool | Enable WebUI. Value casted to a bool | `true` |
|
||||
| DISABLE_HTTP | integer | Disable included `HTTP Server`. | `0` |
|
||||
| DISABLE_CRON | integer | Disable included `Task Scheduler`. | `0` |
|
||||
| DISABLE_CACHE | integer | Disable included `Cache Server`. | `0` |
|
||||
| HTTP_PORT | string | Change the `HTTP` listen port. | `"8080"` |
|
||||
| FPM_PORT | string | Change the `PHP-FPM` listen port. | `"9000"` |
|
||||
| Key | Type | Description | Default |
|
||||
|---------------|---------|------------------------------------|----------|
|
||||
| DISABLE_HTTP | integer | Disable included `HTTP Server`. | `0` |
|
||||
| DISABLE_CRON | integer | Disable included `Task Scheduler`. | `0` |
|
||||
| DISABLE_CACHE | integer | Disable included `Cache Server`. | `0` |
|
||||
| HTTP_PORT | string | Change the `HTTP` listen port. | `"8080"` |
|
||||
| FPM_PORT | string | Change the `PHP-FPM` listen port. | `"9000"` |
|
||||
|
||||
> [!NOTE]
|
||||
> You need to restart the container after changing these environment variables. those variables are not managed by the
|
||||
> WatchState tool, they are managed by the container itself.
|
||||
|
||||
---
|
||||
|
||||
|
||||
---
|
||||
|
||||
# How to disable the included HTTP server and use external server?
|
||||
@@ -620,107 +561,6 @@ jellyfin devs fixes the issue. Please take look at the webhooks section to enabl
|
||||
|
||||
---
|
||||
|
||||
# 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, You can follow these steps.
|
||||
|
||||
## Requirements
|
||||
|
||||
* [PHP 8.4](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.
|
||||
* [Node.js v20+](https://nodejs.org/en/download/) for `WebUI` compilation.
|
||||
|
||||
## Installation
|
||||
|
||||
* Clone the repository.
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/arabcoders/watchstate.git
|
||||
```
|
||||
|
||||
* Install the dependencies.
|
||||
|
||||
```bash
|
||||
$ cd watchstate
|
||||
$ composer install --no-dev
|
||||
```
|
||||
|
||||
* If you your redis server on external server, run the following command
|
||||
|
||||
```bash
|
||||
$ ./bin/console system:env -k WS_CACHE_URL -e '"redis://127.0.0.1:6379?password=your_password"'
|
||||
```
|
||||
|
||||
Change the connection string to match your redis server.
|
||||
|
||||
* Compile the `WebUI`.
|
||||
|
||||
First you need to install `yarn` as it's our package manager of choice.
|
||||
|
||||
```bash
|
||||
$ npm -g install yarn
|
||||
```
|
||||
|
||||
Once that is done you are ready to compile the `WebUI`.
|
||||
|
||||
```bash
|
||||
$ cd frontend
|
||||
$ yarn install --production --prefer-offline --frozen-lockfile && yarn run generate
|
||||
```
|
||||
|
||||
There should be a new directory called `exported`, you need to move that folder to the `public` directory.
|
||||
|
||||
```bash
|
||||
$ mv exported ../public
|
||||
```
|
||||
|
||||
If you do `ls ../public` you should see the following contents
|
||||
|
||||
```bash
|
||||
ws:/opt/app/public$ ls
|
||||
exported index.php
|
||||
```
|
||||
|
||||
There must be exactly one `index.php` file and one `exported` directory. inside that directory, or if you prefer, you
|
||||
can add `WS_WEBUI_PATH` environment variable to point to the `exported` directory.
|
||||
|
||||
* link the app to the frontend proxy. For caddy, you can use the following configuration.
|
||||
|
||||
> [!NOTE]
|
||||
> frontend server is needed All the `API`, `WebUI` and `Webhooks` operations.
|
||||
|
||||
```Caddyfile
|
||||
http://watchstate.example.org {
|
||||
# Change "[user]" to your user name.
|
||||
root * /home/[user]/watchstate/public
|
||||
|
||||
# Change "unix//var/run/php/php8.3-fpm.sock" to your php-fpm socket.
|
||||
php_fastcgi unix//var/run/php/php8.3-fpm.sock
|
||||
}
|
||||
```
|
||||
|
||||
* To access the console you can run the following command.
|
||||
|
||||
```bash
|
||||
$ ./bin/console help
|
||||
```
|
||||
|
||||
* To make the tasks scheduler work you need to add the following to your crontab.
|
||||
|
||||
```crontab
|
||||
* * * * * /home/[user]/watchstate/bin/console system:tasks --run --save-log
|
||||
```
|
||||
|
||||
For more information, please refer to the [Dockerfile](/Dockerfile). On how we do things to get the tool running.
|
||||
|
||||
---
|
||||
|
||||
# How does the file integrity feature works?
|
||||
|
||||
The feature first scan your entire history for reported media file paths. Depending on the results we do the following:
|
||||
@@ -875,58 +715,22 @@ database indexes with the new guids.
|
||||
# Sync watch progress.
|
||||
|
||||
In order to sync the watch progress between media backends, you need to enable the following environment variable
|
||||
`WS_SYNC_PROGRESS` in `(WebUI) > Env` page or via the cli using the following command:
|
||||
|
||||
```bash
|
||||
$ docker exec -ti watchstate console system:env -k WS_SYNC_PROGRESS -e true
|
||||
```
|
||||
`WS_SYNC_PROGRESS` in `WebUI > Env` page.
|
||||
|
||||
For best experience, you should enable the [webhook](guides/webhooks.md) feature for the media backends you want to sync
|
||||
the watch
|
||||
progress,
|
||||
however, if you are unable to do so, the `Tasks > import` task will also generate progress watch events. However, it's
|
||||
not as reliable as the `Webhooks` or as fast. using `Webhooks` is the recommended way and offers the best experience.
|
||||
the watch progress, however, if you are unable to do so, the `Tasks > import` task will also generate progress watch
|
||||
events. However, it's not as reliable as the `Webhooks` or as fast. using `Webhooks` is the recommended way and offers
|
||||
the best experience.
|
||||
|
||||
To check if there is any watch progress events being registered, You can go to `(WebUI) > More > Events` and check
|
||||
To check if there is any watch progress events being registered, You can go to `WebUI > More > Events` and check
|
||||
`on_progress` events, if you are seeing those, this means the progress is being synced. Check the `Tasks logs` to see
|
||||
the event log.
|
||||
|
||||
If this is setup and working you may be ok with changing the `WS_CRON_IMPORT_AT/WS_CRON_EXPORT_AT` schedule to something
|
||||
less frequenet as
|
||||
the sync progress working will update the progress near realtime. For example you could change these tasks to run daily
|
||||
instead of hourly.
|
||||
less frequent as the sync progress working will update the progress near realtime. For example you could change these
|
||||
tasks to run daily instead of hourly.
|
||||
|
||||
```
|
||||
WS_CRON_IMPORT_AT=0 11 * * *
|
||||
WS_CRON_EXPORT_AT=30 11 * * *
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Sub users support.
|
||||
|
||||
### API/WebUI endpoints that supports sub users.
|
||||
|
||||
These endpoints support sub-users via `?user=username` query parameter, or via `X-User` header. The recommended
|
||||
approach is to use the header.
|
||||
|
||||
* `/v1/api/backend/*`.
|
||||
* `/v1/api/system/parity`.
|
||||
* `/v1/api/system/integrity`.
|
||||
* `/v1/api/ignore/*`.
|
||||
* `/v1/api/history/*`.
|
||||
|
||||
### CLI commands that supports sub users.
|
||||
|
||||
These commands sub users can via `[-u, --user]` option flag.
|
||||
|
||||
* `state:import`.
|
||||
* `state:export`.
|
||||
* `state:backup`.
|
||||
* `config:list`.
|
||||
* `config:view`.
|
||||
* `config:edit`.
|
||||
* `db:list`.
|
||||
* `backend:restore`.
|
||||
* `backend:ignore:*`.
|
||||
|
||||
|
||||
53
README.md
53
README.md
@@ -9,8 +9,24 @@ box, this tool support `Jellyfin`, `Plex` and `Emby` media servers.
|
||||
|
||||
# Updates
|
||||
|
||||
### 2025-05-14
|
||||
|
||||
**Breaking change**, we have switched to using user/password form of authentication instead of API key for the WebUI,
|
||||
this will lead to better security and easier to use. The API key is still available for the API, but not for the WebUI.
|
||||
|
||||
The first time you access the WebUI after the update, you will be asked to create a new system user/password. This is a
|
||||
one time operation. Sorry about that. if you somehow lost your password, you can reset it by running the following
|
||||
command from the host machine.
|
||||
|
||||
```bash
|
||||
# change docker to podman if you are using podman
|
||||
$ docker exec watchstate console system:resetpassword
|
||||
```
|
||||
|
||||
Please refer to [NEWS](/NEWS.md) for the latest updates and changes.
|
||||
|
||||
------
|
||||
|
||||
# Features
|
||||
|
||||
* Management via WebUI.
|
||||
@@ -97,36 +113,15 @@ container, but it will be mapped to the user in which the command was run under.
|
||||
After starting the container, you can access the WebUI by visiting `http://localhost:8080` in your browser.
|
||||
|
||||
> [!NOTE]
|
||||
> The very first time you access the WebUI, we will attempt to autoconfigure your API connection. Should this fail, you
|
||||
> can manually configure the API connection by following the instructions below.
|
||||
|
||||
At the start you won't see anything as the `WebUI` is decoupled from the WatchState and need to be configured to be able
|
||||
to access the API. In the top right corner, you will see a cogwheel icon, click on it and then Configure the connection
|
||||
settings.
|
||||
|
||||

|
||||
|
||||
As shown in the screenshot, to get your `API Token`, you can do via two methods
|
||||
|
||||
### Method 1
|
||||
|
||||
view the contents of the `./data/config/.env` file, and copy the contents after `WS_API_KEY=` variable.
|
||||
|
||||
### Method 2
|
||||
|
||||
From the host machine, you can run the following command
|
||||
|
||||
```bash
|
||||
# change docker to podman if you are using podman
|
||||
$ docker exec watchstate console system:apikey
|
||||
```
|
||||
|
||||
Insert the `API key` into the `API Token` field and make sure to set the `API URL` or click the `current page URL` link.
|
||||
If everything is ok, the reset of the navbar will show up.
|
||||
> Note, For the first time, you will be prompted to create a new system user, this is a one time operation.
|
||||
|
||||
To add your backends, please click on the help button in the top right corner, and choose which method you
|
||||
want [one-way](guides/one-way-sync.md) or [two-way](guides/two-way-sync.md) sync. and follow the instructions.
|
||||
|
||||
Once you have setup your backends and imported your data you should see something like
|
||||
|
||||

|
||||
|
||||
### Supported import methods
|
||||
|
||||
Currently, the tool supports three methods to import data from backends.
|
||||
@@ -141,14 +136,12 @@ Currently, the tool supports three methods to import data from backends.
|
||||
> [!NOTE]
|
||||
> Even if all your backends support webhooks, you should keep import task enabled. This help keep healthy relationship
|
||||
> and pick up any missed events. For more information please check the [webhook guide](/guides/webhooks.md) to
|
||||
> understand
|
||||
> webhooks limitations.
|
||||
> understand webhooks limitations.
|
||||
|
||||
# FAQ
|
||||
|
||||
Take look at this [frequently asked questions](FAQ.md) page, or the [guides](/guides/) for more in-depth guides on how
|
||||
to
|
||||
configure things.
|
||||
to configure things.
|
||||
|
||||
# Social channels
|
||||
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useStorage} from '@vueuse/core'
|
||||
import {marked} from 'marked'
|
||||
import {baseUrl} from 'marked-base-url'
|
||||
import markedAlert from 'marked-alert'
|
||||
@@ -88,7 +87,6 @@ const props = defineProps({
|
||||
});
|
||||
|
||||
const content = ref('')
|
||||
const api_url = useStorage('api_url', '')
|
||||
const error = ref('')
|
||||
const isLoading = ref(true)
|
||||
|
||||
@@ -138,7 +136,7 @@ const removeListeners = () => {
|
||||
onMounted(async () => {
|
||||
try {
|
||||
isLoading.value = true
|
||||
const response = await fetch(`${api_url.value}${props.file}?_=${Date.now()}`)
|
||||
const response = await fetch(`${props.file}?_=${Date.now()}`)
|
||||
if (!response.ok) {
|
||||
const err = await parse_api_response(response)
|
||||
console.log(err)
|
||||
@@ -148,36 +146,15 @@ onMounted(async () => {
|
||||
|
||||
const text = await response.text()
|
||||
|
||||
marked.use(baseUrl(api_url.value))
|
||||
marked.use(baseUrl(window.origin))
|
||||
marked.use(markedAlert());
|
||||
marked.use({
|
||||
gfm: true,
|
||||
hooks: {
|
||||
postprocess: (text) => {
|
||||
// // -- replace GitHub [! with icon
|
||||
// text = text.replace(/\[!IMPORTANT]/g, `
|
||||
// <span class="is-block title mb-2 is-5">
|
||||
// <span class="icon-text">
|
||||
// <span class="icon"><i class="fas fa-exclamation-triangle has-text-danger"></i></span>
|
||||
// <span>IMPORTANT</span>
|
||||
// </span>
|
||||
// </span>`)
|
||||
//
|
||||
// text = text.replace(/\[!NOTE]/g, `
|
||||
// <span class="is-block title is-5">
|
||||
// <span class="icon-text">
|
||||
// <span class="icon"><i class="fas fa-info has-text-info-50"></i></span>
|
||||
// <span>NOTE</span>
|
||||
// </span>
|
||||
// </span>`)
|
||||
|
||||
text = text.replace(
|
||||
/<!--\s*?i:([\w.-]+)\s*?-->/gi,
|
||||
(_, list) => `<span class="icon"><i class="fas ${list.split('.').map(n => n.trim()).join(' ')}"></i></span>`
|
||||
);
|
||||
|
||||
return text
|
||||
}
|
||||
postprocess: (text) => text.replace(
|
||||
/<!--\s*?i:([\w.-]+)\s*?-->/gi,
|
||||
(_, list) => `<span class="icon"><i class="fas ${list.split('.').map(n => n.trim()).join(' ')}"></i></span>`
|
||||
)
|
||||
},
|
||||
walkTokens: token => {
|
||||
if ('link' !== token.type) {
|
||||
@@ -187,16 +164,19 @@ onMounted(async () => {
|
||||
if (true === token.href.startsWith('#')) {
|
||||
return;
|
||||
}
|
||||
const urls = ['/FAQ.md', '/README.md', '/NEWS.md'];
|
||||
const list = ['/guides/', ...urls];
|
||||
const urls = ['FAQ.md', 'README.md', 'NEWS.md'];
|
||||
const list = ['guides/', ...urls];
|
||||
if (false === list.some(l => token.href.includes(l))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (urls.some(l => token.href.includes(l))) {
|
||||
const url = new URL(token.href);
|
||||
if (!token.href.startsWith('/')) {
|
||||
token.href = '/' + token.href;
|
||||
}
|
||||
const url = new URL(window.origin + token.href);
|
||||
url.pathname = `/guides${url.pathname}`;
|
||||
token.href = url.pathname;
|
||||
token.href = url.toString();
|
||||
}
|
||||
|
||||
token.href = token.href.replace('/guides/', '/help/').replace('.md', '');
|
||||
|
||||
@@ -11,7 +11,11 @@ try {
|
||||
'/v1/api/': {
|
||||
target: API_URL + '/v1/api/',
|
||||
changeOrigin: true
|
||||
}
|
||||
},
|
||||
'/guides/': {
|
||||
target: API_URL + '/guides/',
|
||||
changeOrigin: true
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +24,7 @@ try {
|
||||
|
||||
export default defineNuxtConfig({
|
||||
ssr: false,
|
||||
devtools: { enabled: true },
|
||||
devtools: {enabled: true},
|
||||
|
||||
devServer: {
|
||||
port: 8081,
|
||||
@@ -35,13 +39,13 @@ export default defineNuxtConfig({
|
||||
app: {
|
||||
head: {
|
||||
"meta": [
|
||||
{ "charset": "utf-8" },
|
||||
{ "name": "viewport", "content": "width=device-width, initial-scale=1.0, maximum-scale=1.0" },
|
||||
{ "name": "theme-color", "content": "#000000" }
|
||||
{"charset": "utf-8"},
|
||||
{"name": "viewport", "content": "width=device-width, initial-scale=1.0, maximum-scale=1.0"},
|
||||
{"name": "theme-color", "content": "#000000"}
|
||||
],
|
||||
},
|
||||
buildAssetsDir: "assets",
|
||||
pageTransition: { name: 'page', mode: 'out-in' }
|
||||
pageTransition: {name: 'page', mode: 'out-in'}
|
||||
},
|
||||
|
||||
router: {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<script setup>
|
||||
const route = useRoute()
|
||||
const slug = ref(`${route.params.slug?.length > 0 ? route.params.slug?.join('/') : ''}`)
|
||||
const slug = ref(`${route.params.slug?.length > 0 ? route.params.slug.join('/') : ''}`)
|
||||
const url = ref('')
|
||||
onMounted(async () => {
|
||||
const to_lower = String(slug.value).toLowerCase()
|
||||
@@ -19,7 +19,7 @@ onMounted(async () => {
|
||||
const special = ['faq', 'readme', 'news']
|
||||
|
||||
if (special.includes(to_lower)) {
|
||||
url.value = '/' + to_lower.toUpperCase() + '.md'
|
||||
url.value = '/guides/' + to_lower.toUpperCase() + '.md'
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 1.6 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 37 KiB |
BIN
screenshots/index.png
Normal file
BIN
screenshots/index.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
@@ -23,6 +23,12 @@ final class Auth
|
||||
|
||||
public const string URL = '%{api.prefix}/system/auth';
|
||||
|
||||
#[Get(self::URL . '/test[/]', name: 'system.auth.test')]
|
||||
public function test_open(): iResponse
|
||||
{
|
||||
return api_response(Status::OK);
|
||||
}
|
||||
|
||||
#[Get(self::URL . '/has_user[/]', name: 'system.auth.has_user')]
|
||||
public function has_user(): iResponse
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ final class ServeStatic implements LoggerAwareInterface
|
||||
use LoggerAwareTrait;
|
||||
|
||||
private finfo|null $mimeType = null;
|
||||
|
||||
|
||||
private const array CONTENT_TYPE = [
|
||||
'css' => 'text/css; charset=utf-8',
|
||||
'js' => 'text/javascript; charset=utf-8',
|
||||
@@ -39,6 +39,9 @@ final class ServeStatic implements LoggerAwareInterface
|
||||
'/NEWS.md' => __DIR__ . '/../../NEWS.md',
|
||||
'/FAQ.md' => __DIR__ . '/../../FAQ.md',
|
||||
'/CHANGELOG.md' => __DIR__ . '/../../CHANGELOG.md',
|
||||
'/guides/README.md' => __DIR__ . '/../../README.md',
|
||||
'/guides/NEWS.md' => __DIR__ . '/../../NEWS.md',
|
||||
'/guides/FAQ.md' => __DIR__ . '/../../FAQ.md',
|
||||
];
|
||||
|
||||
private const array MD_IMAGES = [
|
||||
|
||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Tests\Libs\Middlewares;
|
||||
|
||||
use App\API\System\AutoConfig;
|
||||
use App\API\System\Auth;
|
||||
use App\API\System\HealthCheck;
|
||||
use App\Libs\Config;
|
||||
use App\Libs\Enums\Http\Method;
|
||||
@@ -38,19 +38,20 @@ class AuthorizationMiddlewareTest extends TestCase
|
||||
handler: $this->getHandler()
|
||||
);
|
||||
|
||||
$this->assertSame(Status::OK->value, $result->getStatusCode(), 'Options request failed');
|
||||
$this->assertSame(Status::OK, Status::from($result->getStatusCode()), 'Options request failed');
|
||||
}
|
||||
|
||||
public function test_open_routes()
|
||||
{
|
||||
Config::save('api.prefix', '/v1/api');
|
||||
|
||||
$routes = [
|
||||
HealthCheck::URL,
|
||||
AutoConfig::URL,
|
||||
Auth::URL . '/test'
|
||||
];
|
||||
|
||||
$routesSemiOpen = [
|
||||
'/webhook',
|
||||
'%{api.prefix}/player/',
|
||||
];
|
||||
|
||||
foreach ($routes as $route) {
|
||||
@@ -59,7 +60,7 @@ class AuthorizationMiddlewareTest extends TestCase
|
||||
request: $this->getRequest(uri: $uri),
|
||||
handler: $this->getHandler()
|
||||
);
|
||||
$this->assertSame(Status::OK->value, $result->getStatusCode(), "Open route '{$route}' failed");
|
||||
$this->assertSame(Status::OK, Status::from($result->getStatusCode()), "Open route '{$uri}' failed");
|
||||
}
|
||||
|
||||
foreach ($routesSemiOpen as $route) {
|
||||
@@ -68,7 +69,7 @@ class AuthorizationMiddlewareTest extends TestCase
|
||||
request: $this->getRequest(uri: $uri),
|
||||
handler: $this->getHandler()
|
||||
);
|
||||
$this->assertSame(Status::OK->value, $result->getStatusCode(), "Open route '{$route}' failed");
|
||||
$this->assertSame(Status::OK, Status::from($result->getStatusCode()), "Open route '{$uri}' failed");
|
||||
}
|
||||
|
||||
Config::save('api.secure', true);
|
||||
@@ -80,9 +81,9 @@ class AuthorizationMiddlewareTest extends TestCase
|
||||
handler: $this->getHandler()
|
||||
);
|
||||
$this->assertSame(
|
||||
Status::BAD_REQUEST->value,
|
||||
$result->getStatusCode(),
|
||||
"Route '{$route}' should fail without API key"
|
||||
Status::BAD_REQUEST,
|
||||
Status::from($result->getStatusCode()),
|
||||
"Route '{$uri}' should fail without API key"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -93,9 +94,9 @@ class AuthorizationMiddlewareTest extends TestCase
|
||||
handler: $this->getHandler()
|
||||
);
|
||||
$this->assertSame(
|
||||
Status::UNAUTHORIZED->value,
|
||||
$result->getStatusCode(),
|
||||
"Route '{$route}' should fail without correct API key"
|
||||
Status::UNAUTHORIZED,
|
||||
Status::from($result->getStatusCode()),
|
||||
"Route '{$uri}' should fail without correct API key"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -110,9 +111,9 @@ class AuthorizationMiddlewareTest extends TestCase
|
||||
handler: $this->getHandler()
|
||||
);
|
||||
$this->assertSame(
|
||||
Status::OK->value,
|
||||
$result->getStatusCode(),
|
||||
"Route '{$route}' should pass with correct API key"
|
||||
Status::OK,
|
||||
Status::from($result->getStatusCode()),
|
||||
"Route '{$uri}' should pass with correct API key"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -100,11 +100,11 @@ class ServeStaticTest extends TestCase
|
||||
|
||||
// -- test screenshots serving, as screenshots path is not in public directory and not subject
|
||||
// -- to same path restrictions as other files.
|
||||
$response = $this->server->serve($this->createRequest('GET', '/screenshots/add_backend.png'));
|
||||
$response = $this->server->serve($this->createRequest('GET', '/screenshots/index.png'));
|
||||
$this->assertEquals(Status::OK->value, $response->getStatusCode());
|
||||
$this->assertEquals('image/png', $response->getHeaderLine('Content-Type'));
|
||||
$this->assertEquals(
|
||||
file_get_contents(__DIR__ . '/../../screenshots/add_backend.png'),
|
||||
file_get_contents(__DIR__ . '/../../screenshots/index.png'),
|
||||
(string)$response->getBody()
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user