Commit Graph
36 Commits
Author SHA1 Message Date
Lars Kiesow f56d9f128f Separator between multiple series
If a book is part of multiple series, this patch adds a separator
between the series on the library item details page. With no separator,
it is not immediately clear that they are separate series.
2024-04-04 21:55:52 +02:00
Lars Kiesow 79d32274aa Fix log source in log file
The logger should include a source containing the location where the
logger was called. This works well for logging to `stdout`. Unfortunately,
the file logs contain the locations where the file logging is called
inside of the logger. This is not helpful:

```
{"timestamp":"2023-11-19 16:35:43","source":"Logger.js:114","message":"[oldDbFiles] Processed db data file with 1 entities","levelName":"INFO","level":2}
{"timestamp":"2023-11-19 16:35:43","source":"Logger.js:114","message":"[oldDbFiles] Finished loading db data with 2 entities","levelName":"INFO","level":2}
{"timestamp":"2023-11-19 16:35:43","source":"Logger.js:114","message":"[oldDbFiles] 2 settings loaded","levelName":"INFO","level":2}
```

This patch fixes the issue, ensureing that the actual source location
will be logged:

```
{"timestamp":"2024-02-29 18:12:59.832","source":"DailyLog.js:132","message":"[DailyLog] 2024-02-29: Loaded 20 Logs","levelName":"DEBUG","level":1}
{"timestamp":"2024-02-29 18:12:59.638","source":"Server.js:172","message":"=== Starting Server ===","levelName":"INFO","level":2}
{"timestamp":"2024-02-29 18:12:59.638","source":"Server.js:103","message":"[Server] Init v2.8.0","levelName":"INFO","level":2}
```
2024-02-29 18:16:29 +01:00
Lars Kiesow 987842ed04 Fix file names with URL control characters
This patch ensures that files names like `series #3 xy.jpg` are actually
handled correctly instead of the part after `#` being interpreted as
fragment and being discarded.

I noticed that in a few rare cases the App wouldn't properly display
cover images. It turns out that due the file names containing a `#`, the
file path got corrupted, causing Audiobookshelf to return a 403.
2024-02-29 17:56:55 +01:00
Lars Kiesow 7b6aa3ba5a Allow enabling dev logs
This patch allows users to enable dev logs on production systems by
setting the `HIDE_DEV_LOGS` environment variable.

Before, you could only use this on a non-production environment. On
production, the logs would be disabled. This patch changes the behavior
and uses the `NODE_ENV` only as default. On production they are disabled
if `HIDE_DEV_LOGS` is undefined but can be enabled by setting
`HIDE_DEV_LOGS=0` on dev, they are enabled if undefined, but can be
disabled by setting `HIDE_DEV_LOGS=1`.
2023-11-19 21:00:54 +01:00
Lars Kiesow 91fa78d740 Add milliseconds to logging
This patch adds milliseconds to the time string used for logging. This
helps when debugging some timing issues and should have no real negative
side effect.
2023-11-19 20:36:04 +01:00
Lars Kiesow d2512d324a Integration Test
This patch adds a minimal integration test building Audiobookshelf as a
binary, running it and checking if the server is available on each push
and pull request.

We can easily extend this with a Selenium or Playwright test later, but
it should already alert us about problems in the build pipeline without
the need for any developer to take a look at the new patches.
2023-02-02 00:48:09 +01:00
Lars Kiesow a65859f575 One Default Bookshelf View
This patch updates the default value of the home page bookshelf view so
that it is identical to the default library view. Having different
styles by default seems odd. I picked the non-wooden view as default
based on the recent discussion on Matrx/Discord that that one looks more
modern.
2023-01-28 23:17:31 +01:00
Lars Kiesow 08250e266e Implement X-Accel Redirect
This patch implements [X-Accel](https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/)
redirect headers as an optional way for offloading static file delivery
from Express to Nginx, which is far better optimized for static file
delivery.

This provides a really easy to configure way for getting a huge
performance boost over delivering all files through Audiobookshelf.

How it works
------------

The way this works is basically that Audiobookshelf gets an HTTP request
for delivering a static file (let's say an audiobook). It will first
check the user is authorized and then convert the API path to a local
file path.

Now, instead of reading and delivering the file, Audiobookshelf will
return just the HTTP header with an additional `X-Accel-Redirect`
pointing to the file location on the file syste.

This header is picked up by Nginx which will then deliver the file.

Configuration
-------------

The configuration for this is very simple. You need to run Nginx as
reverse proxy and it must have access to your Audiobookshelf data
folder.

You then configure Audiobookshelf to use X-Accel by setting
`USE_X_ACCEL=/protected`. The path is the internal redirect path used by
Nginx.

In the Nginx configuration you then configure this location and map it
to the storage area to serve like this:

```
location /protected/ {
  internal;
  alias /;
}
```

That's all.

Impact
------

I just did a very simple performance test, downloading a 1170620819
bytes large audiobook file from another machine on the same network
like this, using `time -p` to measure how log the process took:

```sh
URL='https://url to audiobook…'

for i in `seq 1 50`
do
  echo "$i"
  curl -s -o /dev/null "${URL}"
done
```

This sequential test with 50 iterations and without x-accel resulted in:

```
real 413.42
user 197.11
sys 82.04
```

That is an average download speed of about 1080 MBit/s.

With X-Accel enabled, serving the files through Nginx, the same test
yielded the following results:

```
real 200.37
user 86.95
sys 29.79
```

That is an average download speed of about 2229 MBit/s, more than
doubling the previous speed.

I have also run the same test with 4 parallel processes and 25 downloads
each. Without x-accel, that test resulted in:

```
real 364.89
user 273.09
sys 112.75
```

That is an average speed of about 2448 MBit/s.

With X-Accel enabled, the parallel test also shows a significant
speedup:

```
real 167.19
user 195.62
sys 78.61
```

That is an average speed of about 5342 MBit/s.

While doing that, I also peaked at the system load which was a bit lower
when using X-Accel. Even though the system was delivering far more data.
But I just looked at the `load1` values and did not build a proper test
for that. That means, I cant provide any definitive data.

Supported Media
---------------

The current implementation works for audio files and book covers. There
are other media files which would benefit from this mechanism like feed
covers or author pictures.

But that's something for a future developer ;-)
2023-01-23 00:02:27 +01:00
Lars Kiesow 274b0e48be Skip AUDIOBOOKSHELF_UID/GID if undefined
This patch slightly changes the behavior of the `AUDIOBOOKSHELF_UID` and
`AUDIOBOOKSHELF_GID` options. Instead of defining a default user and
group, trying to modify files and silently failing if the filesystem
mode cannot be changed, this patch will just skip the entire process in
the first place.

If these options are defined, Audiobookshelf should behave exactly as
before. If they are not defined, Audiobookshelf will now cause fewer
file modifications (or less failures when trying to modify files).

If this patch gets applied, it should probably be highlighted in the
release notes. This usually shouldn't cause problems for migrations
since the Docker guides explicitly configure the options and the
package installations do not seem to use this at all, but there is still
a change that it will and users should be aware of that.

If a problem arises, users can easily fix the problem by either setting
the permissions once manually to the audiobookshelf user or by simply
defining the `AUDIOBOOKSHELF_UID/GID` options.
2023-01-22 12:30:36 +01:00
Lars Kiesow 4d8ffc5d99 Ensure default are similar in different environments
This patch tries to make sure that defaults and options work in the same
way regardless of users using Docker or a package deployment.

- Commit 10295b0 updated `Host` to be empty by default to better support
  IPv6. This fixes a missed occurrence of the old default.
- This makes sure the `SOURCE` environment variable is honored when
  installing the packages. The `--source` option will still take
  precedence though.
2023-01-22 00:53:10 +01:00
Lars Kiesow a1b49f5fcf Reduce Fingerprinting
As DieselTech#6997 pointed out in Matrix, it is a good idea to reduce
fingerprinting by removing the `X-Powered-By` response header as pointed
out by the Express security best practices:

See http://expressjs.com/en/advanced/best-practice-security.html#reduce-fingerprinting
2023-01-21 23:18:06 +01:00
Lars Kiesow aaede2752c Don't list book twice in continue series
Sometimes, a book belongs to more than one series. If you listen to and
finish such a book, Audiobookshelf will list the next book in “Continue
Series” twice, right next to each other. That is not helpful.

This patch fixes the problem by not adding books to the list if they are
already in the list.
2023-01-13 00:50:04 +01:00
Lars Kiesow 59ad1e5e36 Toggle switch shouldn't submit form
This patch fixes the problem that toggling one of the options in the
user account dialog will automatically submit the form.

The problem got introduced as a combination of the recent accessibility
fixes where some elements got turned into HTML button elements to make
them keyboard accessible. Doing that, I did not realize that the default
type of a button is `submit` [1]. This causes no problems at most places,
but will cause problem within a form (e.g. the user account settings)
where toggling an option is now identical to clicking submit.

This patch fixes the issue by setting the `type` attribute to `button`.
Not only for the toggle switch, but also for a few other elements which
have been recently converted to buttons.

[1] https://www.w3.org/TR/2011/WD-html5-20110525/the-button-element.html#attr-button-type
2023-01-10 22:58:20 +01:00
Lars Kiesow 02c4b21d3f Show next book only if previous book is finished
This patch changes the books displayed in “Continue Series”, avoiding
books if another book from the series is played back right now. This
prevents Audiobookshelf suggesting books to which users will not listen
to because they are still listening to the last one.

Once a book is finished, the next book in the series will pop still be
suggested to the user.

This fixes  #1382
2023-01-10 21:50:33 +01:00
Lars Kiesow e9a84dd7dd Update Gentium Book Basic Font
This patch updates the Gentium Book Basic font file [1]. While I
couldn't get any client to use the previous file, it doesn't seem to be
a problem with this file and now the text is being rendered correctly.

[1] https://gwfh.mranftl.com/fonts/gentium-book-basic?subsets=latin
2023-01-07 20:25:11 +01:00
Lars Kiesow 10fd51498c Add Source to Logging
The Audiobookshelf logs sometimes contain information about the source
of the log statement, but sometimes they don't This really depends on
developers adding these information to the log messages.

But even then, the information is usually just a hint about the module
logging this, like `[Db]` or [Watcher]`, and finding the exact line can
be hard.

This patch automatically adds the source of the log statement to the
logs. This means if someone calls `Logger.info(…)` in line `22` of
`foo.js`, the log statement will contain this file and line:

```
[2023-01-05 19:04:12[ (LogManager.js:85:18) DEBUG: Daily Log file found 2023-01-05.txt
[2023-01-05 19:04:12] (LogManager.js:59:12)  INFO: [LogManager] Init current daily log filename: 2023-01-05.txt
```

This should make it much easier to identify the code where the log
statement originated from.

Long-term, this also means that we can probably remove the manually set
identifiers contained in the log messages, like the `[LogManager]` in
the example above.
2023-01-05 19:13:31 +01:00
Lars Kiesow f095d89980 Update Server Libraries
This patch updates the server libraries to their latest state.
2023-01-05 00:46:23 +01:00
Lars Kiesow 452af43916 Fix Hidden Settings Menu
This patch fixes several problems of the settings menu related to
display on mobile devices or small(ish) windows:

- The `isMobileLandscape` is now calculated correctly. Previously, this
  was set to `true` if a device was in portrait mode.

- Showing the button to collapse the settings menu and making the menu
  collapsible now use the same mechanism. Previously, it could happen
  that the menu was opened and not fixed, but no button to close it
  again was shown.

- The icons fore opening and closing the settings menu are now both
  arrows, indicating that their functionality is reversed.

- The button to open the menu now always has the string “Settings”,
  instead of using the name of the current page. The current page hader
  is listed below that anyway and this is the action component to open
  the settings menu after all.

This fixes #1334
2023-01-01 19:49:43 +01:00
Lars Kiesow f1329d2847 Accessibility Improvements for Main Settings
This patch fixes some accessibility problems on the main settings page.
Most notably, it makes sure that the different options have labels which
are picked up by screen readers.

As a more generic addition, this also makes sure that the dropdown
component will always have a proper label constructed, explaining what
the dropdown is for and what its current value is.
2022-12-30 19:14:04 +01:00
Lars Kiesow 4e61185136 Fix keyboard navigation in user settings
This patch makes sure that the option in the user settings are
accessible via keyboard navigation and that the labels, if users use a
screen reader, actually make sense.

This patch introduces new strings which need to be translated. Although
I did already provide a German translation.
2022-12-29 21:36:42 +01:00
Lars Kiesow 2c344a0bc0 Make User Settings Accessible via Screen Reader
This patch should fix most of the problems for users trying to access
the user settings via screen reader. It makes sure user interface
elements can be reached via keyboard and provides proper labels, roles
and values so you not only can interact with elements but also know what
you are actually changing.

While not focused on other views, this should also already fix a number
of accessibility issues with other settings pages.
2022-12-29 05:00:40 +01:00
Lars Kiesow fc6aa1f91f Fix keyboard navigation in library selection
This patch fixes the keyboard navigation in the library selection of the
main app bar. Without this patch, no options are selectable via keyboard
and selecting an option and hitting return has no effect.
2022-12-29 00:09:22 +01:00
Lars Kiesow 4b0c59b174 Highlight items when navigating via keyboard
This patch highlights items in the app bar if a user uses the keyboard
to navigate in audiobookshelf. This ensures that users actually know
which item they have selected.

This also modifies the text for the library selector, so that users
which are using a screen reader understand that it is a selector for
libraries and not only a button related to the current library.
2022-12-28 22:59:27 +01:00
Lars Kiesow a0840d2a08 Text description of home link
This patch adds the missing alt attribute to the image linking the home
page of audiobookshelf. This allows screen readers to explain to users
where this link leads to.
2022-12-28 22:55:11 +01:00
Lars Kiesow 128796bd36 Fix undefined string assignment
Assigning something to `process.env.profile`, Node stringifies the value. This
means that assigning `undefined` to an environment variable in Node will result
in it holding the string `undefined`.

This means, for example, that `module.exports.FFPROBE_PATH || 'ffprobe'` in
`server/libs/nodeFfprobe/index.js` will actually result in the string
`undefined`.

This patch fixes several such assignments in the `index.js`, potentially
causing problems in the development mode.
2022-12-26 23:55:14 +01:00
Lars Kiesow 90299e348c Fix Sub-path Detection
If the scanner detects new files with a path containing part of the name
of an already existing library item, the new item will incorrectly be
detected as being a parent directory of the already existing item and
the import will be aborted.

You can follow these steps to reproduce the issue:

```
❯ mkdir audiobooks/author/

❯ mv title\ 10 audiobooks/author
[2022-12-18 22:14:12] DEBUG: [Watcher] File Added /home/lars/dev/audiobookshelf/audiobooks/author/title 10/dictaphone.mp3
[2022-12-18 22:14:16] DEBUG: [DB] Library Items inserted 1

❯ mv title\ 1 audiobooks/author
[2022-12-18 22:15:03] DEBUG: [Watcher] File Added /home/lars/dev/audiobookshelf/audiobooks/author/title 1/dictaphone.mp3
[2022-12-18 22:15:07]  WARN: [Scanner] Files were modified in a parent directory of a library item "title 10" - ignoring
```

Since `'title 10'.startsWith('title 1')` is `true`, the current code
makes this false assumption.

This patch fixes the issue by requiring a path separator to be part of
the matching path. This should ensure that only true parent directories
are detected.

This patch requires audiobookshelf to always use Unix file separators.
But that shouldn't be a problem since audiobookshelf always seems to use
these kinds of separators. Even on Windows.
2022-12-18 22:23:50 +01:00
Lars Kiesow b47ce4fb24 Use HTTPS for Google Books Images
The API for Google Books will return HTTP image URLs when matiching any
books using it as a search provider. In a secure environment, this
causes browser warnings.

All Google image links support HTTPS and we can safely switch to HTTOS
to avoid these warnings.
2022-12-18 00:18:11 +01:00
Lars Kiesow 91cbe45839 No PermissionsStartOnly=true
This patch removes `PermissionsStartOnly=true` from the systemd unit
file used for packaging. This shouldn't be necessary for any commands
run by the unit.
2022-12-06 00:52:23 +01:00
Lars Kiesow 616caecdf1 Add Missing Tooltips
This patch adds a few more missing tooltips to the user interface.
2022-12-05 23:16:27 +01:00
Lars Kiesow 45434b16e0 Fix startedAt in progress API
If no progress had been set before, setting `startedAt` did not work and
it would always been set to `finishedAt` or `Date.now()`. Settings this
if any progress had already been recorded did work.

This fixes the problem so that setting `startedAt` it properly works in
both cases.
2022-11-24 00:16:20 +01:00
Lars Kiesow a8162b57ba Respond with bad request to unvalid request data
This patch updates the batch progress update endpoint to respond with a
`400 Bad Request` instead of a `500 Internal Server Error` if a user
sends an invalid request with no body. This is a user error after all.

```
❯ curl -i -X PATCH \
  'http://127.0.0.1:3333/api/me/progress/batch/update' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5Q_MoRptP0oI' \
  -H 'Content-Type: application/json'
HTTP/1.1 400 Bad Request
…

Missing request payload
```
2022-11-23 02:15:36 +01:00
Lars Kiesow b0edac4234 Allow specifying start and end of progress via API
This patch is a minor extension to the update progress and batch update
progress API and allows you to specify `finishedAt` and `startedAt` when
updating a progress.

If not specified, both values are still automatically set to the current
time. If just `finishedAt` is specified, `startedAt` is set to the same
value.

Example API request:

```
❯ curl -i -X PATCH \
  'http://127.0.0.1:3333/api/me/progress/li_ywupqxw5d22adcadpa' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJyb290IiwidXNlcm5hbWUiOiJyb290IiwiaWF0IjoxNjY4OTYxNjAxfQ._NbilCoFy_hfoqy7uvbV4E_0X6qgLYapQ_MoRptP0oI' \
  -H 'Content-Type: application/json' \
  --data-raw '{"isFinished":true, "finishedAt": 1668556852000, "startedAt": 1668056852000}'
```
2022-11-23 01:32:52 +01:00
Lars Kiesow c307b1e6fb No feed log level
This patch drops the log level for logging requests to non-existing
feeds from error to debug. The reasoning behind this is that this is a
client error and a client error is returned and can be handled by the
client.

Otherwise anyone can easily spam the logs with error messages by just
requesting non-existing feeds.
2022-11-21 01:54:25 +01:00
Lars Kiesow d387d5b758 Update Author Modal on Changes
If you are on the home page and open the edit author modal, you can
automatically update all data by clicking “Quick Match” or you can
remove a set image by clicking 🗑.

Both options will update the actual data, but not the data in the open
modal. This means that, for example, a picture is still shown in the
modal after deleting it. That's confusing.

This patch fixes the bug and makes sure the modal is updated if the data
is updated.
2022-11-21 01:48:19 +01:00
Lars Kiesow ee0ac00f80 Make Tooltips Accessible
When using accessibility tools like screen magnifiers, dynamic screen
content can be quite problematic. In particular content, which only
appears if you interact with elements somewhere else on the screen. That
is the case, for example, with the current implementation of tooltips
used by audiobookshelf.

This patch provides a slight adjustment, keeping the tooltips open if
you hover over them. This allows users to have better access to the
content.
2022-11-20 20:02:31 +01:00
Lars Kiesow fdfb07ff2c Add a few tooltips
Starting to use audiobookshelf, the function of some buttons weren't
very clear to me and while some buttons have tooltips, others have not.

This patch adds some additional tooltips to the user interface,
further explaining some of the functionality.
2022-11-20 18:50:34 +01:00