Compare commits

..

31 Commits
7.3.1 ... 7.3.2

Author SHA1 Message Date
Athou
689c20d367 release 7.3.2 2026-08-22 08:23:13 +02:00
Athou
43588df2b4 prevent users from starring/tagging entries that are not theirs 2026-08-22 08:14:21 +02:00
renovate[bot]
d2aaddea33 Update dependency vitest to v4.1.11 2026-08-21 18:52:50 +00:00
Jérémie Panzer
de233f8ae5 Merge pull request #2280 from Athou/renovate/patch-testing-library-monorepo
Update dependency @testing-library/user-event to v14.6.5
2026-08-21 15:06:31 +02:00
renovate[bot]
3179e74dc7 Update dependency @testing-library/user-event to v14.6.5 2026-08-21 04:47:20 +00:00
renovate[bot]
6f5e9f5d49 Update dependency @biomejs/biome to v2.5.9 2026-08-21 00:00:07 +00:00
Jérémie Panzer
8a43fdf200 Merge pull request #2279 from Athou/renovate/protobuf-monorepo
Update dependency com.google.protobuf:protobuf-java to v4.36.0
2026-08-21 01:59:09 +02:00
renovate[bot]
69051e5bbb Update dependency com.google.protobuf:protobuf-java to v4.36.0 2026-08-20 18:54:00 +00:00
renovate[bot]
c648e7e0ec Update dependency dayjs to v1.11.23 2026-08-20 15:32:41 +00:00
renovate[bot]
c91cf376ad Update ibm-semeru-runtimes:open-jdk-25.0.4.0-jre Docker digest to 524f0d0 2026-08-20 09:23:52 +00:00
Jérémie Panzer
f4e07597d0 Merge pull request #2278 from canoine/patch-11
Update fr/messages.po
2026-08-20 11:22:57 +02:00
CNE
64b64d3340 Update fr/messages.po
3 new fields
2026-08-20 10:47:45 +02:00
Jérémie Panzer
57ea87871e Merge pull request #2276 from Athou/renovate/querydsl.version
Update querydsl.version to v7.6
2026-08-20 09:06:03 +02:00
renovate[bot]
6154d80bb9 Update querydsl.version to v7.6 2026-08-20 06:17:16 +00:00
renovate[bot]
ad85745f85 Update quarkus.version to v3.38.3 2026-08-20 00:35:52 +00:00
renovate[bot]
41fc77322c Update dependency dayjs to v1.11.22 2026-08-19 20:44:22 +00:00
Jérémie Panzer
1b83c26417 Merge pull request #2274 from Athou/renovate/docker-setup-buildx-action-4.x
Update docker/setup-buildx-action action to v4.3.0
2026-08-19 22:43:38 +02:00
Athou
10ea5f0b93 move exception to its own package 2026-08-19 22:32:37 +02:00
Jérémie Panzer
032684de68 Merge pull request #2272 from n200534/fix/issue-2016-translate-backend-errors
Translate login authentication errors
2026-08-19 22:31:29 +02:00
n200534
3efec5ce58 Use typed backend errors for translations 2026-08-20 01:11:30 +05:30
renovate[bot]
4ed32964d9 Update docker/setup-buildx-action action to v4.3.0 2026-08-19 16:16:18 +00:00
renovate[bot]
05c1d0cc6e Update ibm-semeru-runtimes:open-jdk-25.0.4.0-jre Docker digest to 27d8480 2026-08-18 22:09:48 +00:00
Jérémie Panzer
3c54924971 Merge pull request #2273 from Athou/renovate/com.puppycrawl.tools-checkstyle-14.x
Update dependency com.puppycrawl.tools:checkstyle to v14
2026-08-18 21:48:54 +02:00
renovate[bot]
e57dfc0e3f Update dependency com.puppycrawl.tools:checkstyle to v14 2026-08-18 17:49:50 +00:00
n200534
eff8bb16a0 Translate login authentication errors 2026-08-18 15:33:42 +05:30
Jérémie Panzer
87e681b71e Merge pull request #2271 from Athou/renovate/dev.cel-cel-0.x
Update dependency dev.cel:cel to v0.14.0
2026-08-18 07:13:13 +02:00
renovate[bot]
ac73ef4ea7 Update dependency dev.cel:cel to v0.14.0 2026-08-18 02:44:30 +00:00
Jérémie Panzer
20945e7443 Merge pull request #2270 from Athou/renovate/react-querybuilder
Update react-querybuilder to v8.23.0
2026-08-17 23:16:27 +02:00
Jérémie Panzer
b7b1278111 Merge pull request #2269 from Athou/renovate/org.mock-server-mockserver-junit-jupiter-7.x
Update dependency org.mock-server:mockserver-junit-jupiter to v7.6.0
2026-08-17 23:14:40 +02:00
renovate[bot]
6f9378404f Update react-querybuilder to v8.23.0 2026-08-17 20:36:06 +00:00
renovate[bot]
79787aca6e Update dependency org.mock-server:mockserver-junit-jupiter to v7.6.0 2026-08-17 20:35:51 +00:00
56 changed files with 482 additions and 197 deletions

View File

@@ -113,7 +113,7 @@ jobs:
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Install required packages - name: Install required packages
run: sudo apt-get install -y rename unzip run: sudo apt-get install -y rename unzip

View File

@@ -1,23 +1,30 @@
# Changelog # Changelog
## [7.3.2]
- Prevent users from starring/tagging entries that are not theirs and subsequently reading them (GHSA-prfv-88mm-5gpg)
## [7.3.1] ## [7.3.1]
- Prevent Host header injection attacks on the password recovery endpoint. A new setting - Prevent Host header injection attacks on the password recovery endpoint. A new setting
`commafeed.password-recovery-public-base-url` has been added to specify the base URL to use in password recovery `commafeed.password-recovery-public-base-url` has been added to specify the base URL to use in password recovery
(GHSA-hp8h-jqfm-v7x5)
emails. This setting is only required when the password recovery feature is enabled, which is not the default. emails. This setting is only required when the password recovery feature is enabled, which is not the default.
## [7.3.0] ## [7.3.0]
- Add support for the Google Reader API for native mobile apps that don't support the Fever API - Add support for the Google Reader API for native mobile apps that don't support the Fever API
- The profile menu now works again on mobile when action buttons are at the bottom of the screen - The profile menu now works again on mobile when action buttons are at the bottom of the screen
- More SSRF protection regarding IPv6 - More SSRF protection regarding IPv6 (GHSA-q5qw-345w-55xg)
- Changed the default value of `blockLocalAddresses` to make CommaFeed more secure out-of-the-box. See the "Access to - Changed the default value of `blockLocalAddresses` to make CommaFeed more secure out-of-the-box. See the "Access to
local address blocked" section of the README if you subscribe to feeds that are only available on your local network. local address blocked" section of the README if you subscribe to feeds that are only available on your local network.
## [7.2.1] ## [7.2.1]
- correctly handle favicons hosted at the root of the domain for feeds with non-default ports - correctly handle favicons hosted at the root of the domain for feeds with non-default ports
- prevent XXS injections in third party apps. The CommaFeed React client was already stripping malicious "javascript:" URLs, they are now filtered during feed parsing and no longer stored in the database/served through the REST API. - prevent XXS injections in third party apps. The CommaFeed React client was already stripping malicious "javascript:"
URLs, they are now filtered during feed parsing and no longer stored in the database/served through the REST API
(GHSA-44pq-9929-f8mq)
## [7.2.0] ## [7.2.0]
@@ -27,26 +34,36 @@
- Small performance improvements to the feed refresh engine - Small performance improvements to the feed refresh engine
- Removed the Pocket sharing feature because the Pocket service has been discontinued - Removed the Pocket sharing feature because the Pocket service has been discontinued
- Prevent the image proxy feature to access any URL to avoid SSRF attacks - Prevent the image proxy feature to access any URL to avoid SSRF attacks
- Strengthened the SSRF protection by also blocking ULA and CGNAT ranges - Strengthened the SSRF protection by also blocking ULA and CGNAT ranges (GHSA-hgrr-mjfp-gmr6)
- Prevent DDOS attacks by filtering OPML files during imports - Prevent DDOS attacks by filtering OPML files during imports (GHSA-83jp-rww3-57rr)
## [7.1.0] ## [7.1.0]
- Display the unread count in the header on mobile, since the tree is hidden by default and the unread count is not visible otherwise (#2055) - Display the unread count in the header on mobile, since the tree is hidden by default and the unread count is not
visible otherwise (#2055)
- The feed refresh engine is now a little bit more performant (#2089) - The feed refresh engine is now a little bit more performant (#2089)
- On shutdown, give the feed refresh engine some time to finish refreshing feeds before killing it. This is controlled by the new `commafeed.shutdown-timeout` setting, which defaults to 2 seconds - On shutdown, give the feed refresh engine some time to finish refreshing feeds before killing it. This is controlled
by the new `commafeed.shutdown-timeout` setting, which defaults to 2 seconds
## [7.0.0] ## [7.0.0]
- Replaced the JEXL filter expression for marking feed entries as read automatically with a user-friendly visual query builder. Expressions are now evaluated with Common Expression Language, which is safer than JEXL and sanboxed by default. - Replaced the JEXL filter expression for marking feed entries as read automatically with a user-friendly visual query
- Added a per-feed setting for sending push notifications to ntfy, Gotify or Pushover when new feed entries are discovered (#1610) builder. Expressions are now evaluated with Common Expression Language, which is safer than JEXL and sanboxed by
default.
- Added a per-feed setting for sending push notifications to ntfy, Gotify or Pushover when new feed entries are
discovered (#1610)
- Added a per-feed setting for marking entries as read after a number of days (#2041) - Added a per-feed setting for marking entries as read after a number of days (#2041)
- The default value of `commafeed.http-client.block-local-addresses` is now false, allowing users to subscribe to feeds only available on their local network. This may be a security risk (SSRF) if your instance is accessible by untrusted users, so you may want to set it to true if you host a public instance of CommaFeed with user registeration enabled. - The default value of `commafeed.http-client.block-local-addresses` is now false, allowing users to subscribe to feeds
- When `commafeed.http-client.block-local-addresses` is enabled, SSRF is now also mitigated by blocking public websites redirecting to local ones. only available on their local network. This may be a security risk (SSRF) if your instance is accessible by untrusted
users, so you may want to set it to true if you host a public instance of CommaFeed with user registeration enabled.
- When `commafeed.http-client.block-local-addresses` is enabled, SSRF is now also mitigated by blocking public websites
redirecting to local ones.
## [6.2.0] ## [6.2.0]
- Starred entries are no longer deleted after a certain amount of time, they are now kept indefinitely. The new `commafeed.database.cleanup.keep-starred-entries` setting can be disabled to restore the previous behavior if you want to keep deleting starred entries during normal entries cleanup (#1581) - Starred entries are no longer deleted after a certain amount of time, they are now kept indefinitely. The new
`commafeed.database.cleanup.keep-starred-entries` setting can be disabled to restore the previous behavior if you want
to keep deleting starred entries during normal entries cleanup (#1581)
## [6.1.1] ## [6.1.1]
@@ -54,16 +71,21 @@
## [6.1.0] ## [6.1.0]
- When clicking on the password reset link, a random password is no longer generated automatically. The user is now redirected to a page where they can set their own password (#2023) - When clicking on the password reset link, a random password is no longer generated automatically. The user is now
redirected to a page where they can set their own password (#2023)
- Use browser preferred language instead of English when using CommaFeed for the first time (#2018) - Use browser preferred language instead of English when using CommaFeed for the first time (#2018)
- The profile menu is now closed when scrolling the page (#2019) - The profile menu is now closed when scrolling the page (#2019)
- The "disable pull to refresh" feature is now disabled by default (#2030) - The "disable pull to refresh" feature is now disabled by default (#2030)
## [6.0.0] ## [6.0.0]
- When booting CommaFeed for the first time, the default "admin" account is no longer created automatically. A setup wizard will guide you through the creation of an admin account - When booting CommaFeed for the first time, the default "admin" account is no longer created automatically. A setup
- Default password complexity requirements have been lowered for local network deployments, where strict password rules are often unnecessary. The `commafeed.users.strict-password-policy` setting has been replaced by `commafeed.users.minimum-password-length` with a default value of `4` (#1916) wizard will guide you through the creation of an admin account
- Email addresses are no longer required when creating users and when they update their profile. The `commafeed.users.email-address-required` setting has been added to restore the previous behavior (#1914) - Default password complexity requirements have been lowered for local network deployments, where strict password rules
are often unnecessary. The `commafeed.users.strict-password-policy` setting has been replaced by
`commafeed.users.minimum-password-length` with a default value of `4` (#1916)
- Email addresses are no longer required when creating users and when they update their profile. The
`commafeed.users.email-address-required` setting has been added to restore the previous behavior (#1914)
- Java 25+ is now required to build and run CommaFeed - Java 25+ is now required to build and run CommaFeed
## [5.12.1] ## [5.12.1]
@@ -93,15 +115,18 @@
## [5.10.0] ## [5.10.0]
- Add an indicator next to each feed's unread count in the tree to show when new entries are discovered while the app is open (#1762) - Add an indicator next to each feed's unread count in the tree to show when new entries are discovered while the app is
open (#1762)
- Feeds with uppercase HTTP:// or HTTPS:// URLs are now correctly handled again - Feeds with uppercase HTTP:// or HTTPS:// URLs are now correctly handled again
- The aarch64 native executable now also works on the Raspberry Pi 5 (#1795) - The aarch64 native executable now also works on the Raspberry Pi 5 (#1795)
- Improve general performance of the UI by reducing the number of re-renders, especially when a lot of entries are displayed (#1087) - Improve general performance of the UI by reducing the number of re-renders, especially when a lot of entries are
displayed (#1087)
## [5.9.0] ## [5.9.0]
- A lot of CSS classes have been added to the elements of the application to ease custom CSS rules (#1757) - A lot of CSS classes have been added to the elements of the application to ease custom CSS rules (#1757)
- Added a link in the README to the [documentation](https://athou.github.io/commafeed/documentation/custom-css/) of the new CSS classes - Added a link in the README to the [documentation](https://athou.github.io/commafeed/documentation/custom-css/) of the
new CSS classes
- Static resources are now cached for much longer (#1782) - Static resources are now cached for much longer (#1782)
## [5.8.0] ## [5.8.0]
@@ -110,7 +135,8 @@
- A font size slider is now available to change the size of the text of feed entries (#1462) - A font size slider is now available to change the size of the text of feed entries (#1462)
- The "mark all as read" confirmation setting now also applies to the "shift+a" keyboard shortcut (#1744) - The "mark all as read" confirmation setting now also applies to the "shift+a" keyboard shortcut (#1744)
- CommaFeed wil try to match the language of the browser before defaulting to english (#1767) - CommaFeed wil try to match the language of the browser before defaulting to english (#1767)
- The default value for the number of entries to keep above the selected entry when scrolling is now 1 instead of 0 to match what other feed readers do - The default value for the number of entries to keep above the selected entry when scrolling is now 1 instead of 0 to
match what other feed readers do
## [5.7.0] ## [5.7.0]
@@ -129,14 +155,22 @@
## [5.6.0] ## [5.6.0]
- To better respect the bandwidth of feed owners, the default value of `commafeed.feed-refresh.interval-empirical` is now true. This means feeds no longer refresh exactly every 5 minutes (the default value of `commafeed.feed-refresh.interval`) but between 5 minutes and 4 hours (the default value of the new `commafeed.feed-refresh.max-interval` setting). The interval is calculated based on feed activity, so highly active feeds refresh more often (#1677) - To better respect the bandwidth of feed owners, the default value of `commafeed.feed-refresh.interval-empirical` is
now true. This means feeds no longer refresh exactly every 5 minutes (the default value of
`commafeed.feed-refresh.interval`) but between 5 minutes and 4 hours (the default value of the new
`commafeed.feed-refresh.max-interval` setting). The interval is calculated based on feed activity, so highly active
feeds refresh more often (#1677)
- Many previously hardcoded values used in feed refresh interval calculation are now exposed as settings (#1677) - Many previously hardcoded values used in feed refresh interval calculation are now exposed as settings (#1677)
- Access to local addresses is now blocked to mitigate server-side request forgery (SSRF) attacks, which could potentially expose internal resources. You might want to disable the new `commafeed.http-client.block-local-addresses` setting if you subscribe to feeds only available on your local network and you trust all your users - Access to local addresses is now blocked to mitigate server-side request forgery (SSRF) attacks, which could
- If a feed responds with a "429 - Too many requests" response, a backoff mechanism is triggered when the response does not contain a "Retry-After" header potentially expose internal resources. You might want to disable the new `commafeed.http-client.block-local-addresses`
setting if you subscribe to feeds only available on your local network and you trust all your users
- If a feed responds with a "429 - Too many requests" response, a backoff mechanism is triggered when the response does
not contain a "Retry-After" header
## [5.5.0] ## [5.5.0]
- CommaFeed now honors the Retry-After response header and will not try to refresh a feed sooner than the value of this header - CommaFeed now honors the Retry-After response header and will not try to refresh a feed sooner than the value of this
header
- Audio enclosures (e.g. podcasts) now fill available entry width - Audio enclosures (e.g. podcasts) now fill available entry width
- Fix an issue with some labels not correctly internationalized - Fix an issue with some labels not correctly internationalized
@@ -153,8 +187,10 @@
## [5.3.5] ## [5.3.5]
- Fixed an issue with the aspect ratio of images of some feeds (#1595) - Fixed an issue with the aspect ratio of images of some feeds (#1595)
- CommaFeed now honors the Cache-Control response header and will not try to refresh a feed sooner than its max-age property (#1615) - CommaFeed now honors the Cache-Control response header and will not try to refresh a feed sooner than its max-age
- Added support for compilation with JDK 23+. If you're building CommaFeed from sources with a JDK 17 or 21, you may need to update it to the most recent patch version to support `-proc:full` (#1618) property (#1615)
- Added support for compilation with JDK 23+. If you're building CommaFeed from sources with a JDK 17 or 21, you may
need to update it to the most recent patch version to support `-proc:full` (#1618)
## [5.3.4] ## [5.3.4]
@@ -181,19 +217,22 @@
- Added an option to keep a number of entries above the selected entry when scrolling - Added an option to keep a number of entries above the selected entry when scrolling
- Added a cache to the HTTP client to reduce the number of requests made to feeds when subscribing (#1431) - Added a cache to the HTTP client to reduce the number of requests made to feeds when subscribing (#1431)
- Feeds are no longer refreshed between the moment its last user unsubscribes and the moment the feed is cleaned up (every hour) - Feeds are no longer refreshed between the moment its last user unsubscribes and the moment the feed is cleaned up
(every hour)
- Fixed an issue that could cause entries to not correctly load when using keyboard navigation (#1557) - Fixed an issue that could cause entries to not correctly load when using keyboard navigation (#1557)
## [5.1.1] ## [5.1.1]
- Fixed database migration issue when upgrading from 5.0.0 to 5.1.0 on MariaDB (#1544) - Fixed database migration issue when upgrading from 5.0.0 to 5.1.0 on MariaDB (#1544)
- When feeds without unread entries are hidden from the tree, the feed is displayed in the tree until another one is selected (#1543) - When feeds without unread entries are hidden from the tree, the feed is displayed in the tree until another one is
selected (#1543)
## [5.1.0] ## [5.1.0]
- Added a setting for showing/hiding unread count in the browser's tab title/favicon (#1518) - Added a setting for showing/hiding unread count in the browser's tab title/favicon (#1518)
- Fixed an issue that could prevent the app from starting on some systems (#1532) - Fixed an issue that could prevent the app from starting on some systems (#1532)
- Added a cache busting filter for the webapp index.html and openapi documentation to make sure they are always up to date - Added a cache busting filter for the webapp index.html and openapi documentation to make sure they are always up to
date
- Reduced database cleanup log verbosity - Reduced database cleanup log verbosity
## [5.0.2] ## [5.0.2]
@@ -208,9 +247,9 @@
## [5.0.0] ## [5.0.0]
CommaFeed is now powered by Quarkus instead of Dropwizard. Read the rationale behind this change in CommaFeed is now powered by Quarkus instead of Dropwizard. Read the rationale behind this change in
the [announcement](https://github.com/Athou/commafeed/discussions/1517). the [announcement](https://github.com/Athou/commafeed/discussions/1517). The gist of it is that CommaFeed can now be
The gist of it is that CommaFeed can now be compiled to a native binary, resulting in blazing fast startup times (around compiled to a native binary, resulting in blazing fast startup times (around 0.3s) and very low memory footprint (<
0.3s) and very low memory footprint (< 50M). 50M).
- CommaFeed now has a different package for each supported database. - CommaFeed now has a different package for each supported database.
- If you are deploying CommaFeed with a precompiled package, please - If you are deploying CommaFeed with a precompiled package, please
@@ -266,8 +305,8 @@ The gist of it is that CommaFeed can now be compiled to a native binary, resulti
- add a button in the entry headers to open links in a new tab (#1333) - add a button in the entry headers to open links in a new tab (#1333)
- add two options in the settings to toggle those buttons - add two options in the settings to toggle those buttons
- accept .opml file extension when importing and export with the .opml extension - accept .opml file extension when importing and export with the .opml extension
- the "mark as read" option is no longer shown in the context menu for entries that are too old to be marked as read ( - the "mark as read" option is no longer shown in the context menu for entries that are too old to be marked as read
older than `keepStatusDays`) (#1303) (older than `keepStatusDays`) (#1303)
## [4.3.3] ## [4.3.3]
@@ -311,9 +350,8 @@ The gist of it is that CommaFeed can now be compiled to a native binary, resulti
- it is now possible to open the sidebar on mobile by swiping to the right (#1098) - it is now possible to open the sidebar on mobile by swiping to the right (#1098)
- swiping to mark entries as read/unread changed from swiping right to left because swiping right now opens the sidebar - swiping to mark entries as read/unread changed from swiping right to left because swiping right now opens the sidebar
- the full hierarchy of categories are now displayed in the category dropdown (#1045) - the full hierarchy of categories are now displayed in the category dropdown (#1045)
- added a setting `maxEntriesAgeDays` to delete old entries based on their age during database cleanup. - added a setting `maxEntriesAgeDays` to delete old entries based on their age during database cleanup. The setting is
The setting is disabled by default for existing installations, except for the docker image where it is enabled and set disabled by default for existing installations, except for the docker image where it is enabled and set to 365 days
to 365 days
- if user registrations are disabled on your instance which is the default behavior, users are redirected on the login - if user registrations are disabled on your instance which is the default behavior, users are redirected on the login
page instead of the welcome page when not logged in (#1185) page instead of the welcome page when not logged in (#1185)
- the sidebar resizer is no longer shown in the middle of the screen on mobile - the sidebar resizer is no longer shown in the middle of the screen on mobile
@@ -339,8 +377,8 @@ The gist of it is that CommaFeed can now be compiled to a native binary, resulti
request, reducing CPU usage request, reducing CPU usage
- updated UI library Mantine to 7.0, improving performance - updated UI library Mantine to 7.0, improving performance
- the h2 embedded database is now compacted on shutdown to reclaim unused space - the h2 embedded database is now compacted on shutdown to reclaim unused space
- the admin connector on port 8084 is now disabled in config.yml.example. Disabling it in your config.yml is - the admin connector on port 8084 is now disabled in config.yml.example. Disabling it in your config.yml is recommended
recommended (see https://github.com/Athou/commafeed/commit/929df60f09cce56020b0962ab111cd8349b271b0) (see https://github.com/Athou/commafeed/commit/929df60f09cce56020b0962ab111cd8349b271b0)
- migrated documentation from swagger 2 to openapi 3 - migrated documentation from swagger 2 to openapi 3
- added a GET method to the fever api to indicate that the endpoint is working correctly when accessed from a browser - added a GET method to the fever api to indicate that the endpoint is working correctly when accessed from a browser
- the websocket connection can now be disabled, the websocket ping interval and the tree reload interval can now be - the websocket connection can now be disabled, the websocket ping interval and the tree reload interval can now be
@@ -582,7 +620,6 @@ The gist of it is that CommaFeed can now be compiled to a native binary, resulti
## [2.0.0] ## [2.0.0]
- The backend has been completely rewritten using Dropwizard instead of TomEE, resulting in a lot less memory - The backend has been completely rewritten using Dropwizard instead of TomEE, resulting in a lot less memory
consumption and better overall performances. consumption and better overall performances. See the README on how to build CommaFeed from now on.
See the README on how to build CommaFeed from now on.
- CommaFeed should no longer fetch the same feed multiple times in a row - CommaFeed should no longer fetch the same feed multiple times in a row
- Users can use their username or email to log in - Users can use their username or email to log in

View File

@@ -1,5 +1,5 @@
{ {
"$schema": "https://biomejs.dev/schemas/2.5.8/schema.json", "$schema": "https://biomejs.dev/schemas/2.5.9/schema.json",
"formatter": { "formatter": {
"indentStyle": "space", "indentStyle": "space",
"indentWidth": 4, "indentWidth": 4,

View File

@@ -20,11 +20,11 @@
"@mantine/notifications": "9.5.1", "@mantine/notifications": "9.5.1",
"@mantine/spotlight": "9.5.1", "@mantine/spotlight": "9.5.1",
"@monaco-editor/react": "4.7.0", "@monaco-editor/react": "4.7.0",
"@react-querybuilder/mantine": "8.22.5", "@react-querybuilder/mantine": "8.23.0",
"@reduxjs/toolkit": "2.12.0", "@reduxjs/toolkit": "2.12.0",
"@rolldown/plugin-babel": "0.2.3", "@rolldown/plugin-babel": "0.2.3",
"axios": "1.19.0", "axios": "1.19.0",
"dayjs": "1.11.21", "dayjs": "1.11.23",
"escape-string-regexp": "5.0.0", "escape-string-regexp": "5.0.0",
"interweave": "13.1.1", "interweave": "13.1.1",
"monaco-editor": "0.56.0", "monaco-editor": "0.56.0",
@@ -36,7 +36,7 @@
"react-draggable": "4.7.1", "react-draggable": "4.7.1",
"react-icons": "5.7.0", "react-icons": "5.7.0",
"react-infinite-scroller": "1.2.6", "react-infinite-scroller": "1.2.6",
"react-querybuilder": "8.22.5", "react-querybuilder": "8.23.0",
"react-redux": "9.3.0", "react-redux": "9.3.0",
"react-router-dom": "7.18.2", "react-router-dom": "7.18.2",
"react-swipeable": "7.0.2", "react-swipeable": "7.0.2",
@@ -48,13 +48,13 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/types": "^8.0.4", "@babel/types": "^8.0.4",
"@biomejs/biome": "2.5.8", "@biomejs/biome": "2.5.9",
"@lingui/babel-plugin-lingui-macro": "6.6.0", "@lingui/babel-plugin-lingui-macro": "6.6.0",
"@lingui/cli": "6.6.0", "@lingui/cli": "6.6.0",
"@lingui/vite-plugin": "6.6.0", "@lingui/vite-plugin": "6.6.0",
"@testing-library/jest-dom": "7.0.1", "@testing-library/jest-dom": "7.0.1",
"@testing-library/react": "16.3.2", "@testing-library/react": "16.3.2",
"@testing-library/user-event": "14.6.4", "@testing-library/user-event": "14.6.5",
"@types/mousetrap": "1.6.15", "@types/mousetrap": "1.6.15",
"@types/react": "19.2.18", "@types/react": "19.2.18",
"@types/react-dom": "19.2.4", "@types/react-dom": "19.2.4",
@@ -67,7 +67,7 @@
"typescript": "7.0.2", "typescript": "7.0.2",
"vite": "8.2.1", "vite": "8.2.1",
"vite-plugin-checker": "0.14.5", "vite-plugin-checker": "0.14.5",
"vitest": "4.1.10", "vitest": "4.1.11",
"yaml": "2.9.0" "yaml": "2.9.0"
} }
}, },
@@ -592,9 +592,9 @@
} }
}, },
"node_modules/@biomejs/biome": { "node_modules/@biomejs/biome": {
"version": "2.5.8", "version": "2.5.9",
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.8.tgz", "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.9.tgz",
"integrity": "sha512-aeAeeJB9fSDc7Gq+2GqpQxA0qBj6gj1k2R6L1cYqGePKP/baIq1WX8y6B+D+nRsO5ViQL22K/8IwbqERW0q1nw==", "integrity": "sha512-KkgCvdHB4IhtpHpF564plA9jo6fDOwWGQ/3jvreLzgOtRLEDoPqr7QO9qejNA8jKwDsSkAKr77hqBHnyUbIw4g==",
"dev": true, "dev": true,
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"bin": { "bin": {
@@ -608,20 +608,20 @@
"url": "https://opencollective.com/biome" "url": "https://opencollective.com/biome"
}, },
"optionalDependencies": { "optionalDependencies": {
"@biomejs/cli-darwin-arm64": "2.5.8", "@biomejs/cli-darwin-arm64": "2.5.9",
"@biomejs/cli-darwin-x64": "2.5.8", "@biomejs/cli-darwin-x64": "2.5.9",
"@biomejs/cli-linux-arm64": "2.5.8", "@biomejs/cli-linux-arm64": "2.5.9",
"@biomejs/cli-linux-arm64-musl": "2.5.8", "@biomejs/cli-linux-arm64-musl": "2.5.9",
"@biomejs/cli-linux-x64": "2.5.8", "@biomejs/cli-linux-x64": "2.5.9",
"@biomejs/cli-linux-x64-musl": "2.5.8", "@biomejs/cli-linux-x64-musl": "2.5.9",
"@biomejs/cli-win32-arm64": "2.5.8", "@biomejs/cli-win32-arm64": "2.5.9",
"@biomejs/cli-win32-x64": "2.5.8" "@biomejs/cli-win32-x64": "2.5.9"
} }
}, },
"node_modules/@biomejs/cli-darwin-arm64": { "node_modules/@biomejs/cli-darwin-arm64": {
"version": "2.5.8", "version": "2.5.9",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.8.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.9.tgz",
"integrity": "sha512-mk1QON9PHllvvLN5gU3f4rMxeh4syK5p9OvKyWH6/W8ueh04uaC8TUXXByhGufWf/y5mQc03ZLM45zU+cmqMjA==", "integrity": "sha512-am22pX2aBqznqq1eMyIj/bZ++riF3Lk6ct7cbv+gQK0csFhr+d8O0RkOi2FF2qSgFgANbqNkIZ0/PxlnW2pLFg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -636,9 +636,9 @@
} }
}, },
"node_modules/@biomejs/cli-darwin-x64": { "node_modules/@biomejs/cli-darwin-x64": {
"version": "2.5.8", "version": "2.5.9",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.8.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.9.tgz",
"integrity": "sha512-bsGwFMBNyHPyiLSsQcZJxdoRrg1V4JL+d7wEsvUBczlP9U9lwM+7mzQHxI4o1mhBsTmdOBbAb6fHU3Z3snN45w==", "integrity": "sha512-l44KWDHLDvEnD0N/XcrVs7VXb3A18xL7QS3WB0eL93wbmk529ffIG55vleGCqaunpRUjLrdnjK05Qki1dsjylg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -653,9 +653,9 @@
} }
}, },
"node_modules/@biomejs/cli-linux-arm64": { "node_modules/@biomejs/cli-linux-arm64": {
"version": "2.5.8", "version": "2.5.9",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.8.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.9.tgz",
"integrity": "sha512-XmFiA0WPYFC+uiUDC8WRFzAIH9bo7vwQLav38Uoq4ETC+T/+uBi0TsYGJECkugY3r8USl3jc+Ae2/irAF6F2lQ==", "integrity": "sha512-ICaK+IYaVZvKbBxX2rwrPT0DdUDMnE9Vm3nQGe+mltQPmUg19pONzkPWGdY4FCsoreDETWDynvdt4ysCbF5gNQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -673,9 +673,9 @@
} }
}, },
"node_modules/@biomejs/cli-linux-arm64-musl": { "node_modules/@biomejs/cli-linux-arm64-musl": {
"version": "2.5.8", "version": "2.5.9",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.8.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.9.tgz",
"integrity": "sha512-VcJNbstduTHx83NGAdhp78/JOcP45BZHXL7yNsfI1uGzdUgegAz2s+mSoT7wK6PBNzLoqG0zDOXaz/RQYVtSiw==", "integrity": "sha512-7ImVPwBLCtkmpR5esd8RHhTqW94f0JLJQum6AneYcy94jRm18TaPPm7slaigGzFhfgt3QiD1Vj52LKmBAnKizA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -693,9 +693,9 @@
} }
}, },
"node_modules/@biomejs/cli-linux-x64": { "node_modules/@biomejs/cli-linux-x64": {
"version": "2.5.8", "version": "2.5.9",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.8.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.9.tgz",
"integrity": "sha512-S5wcm9OBDvLHodD4PUaN488hCpco9QD/9ZxuYJiw4euWtr/oQvLR72z2ixItH8Wd5BCm6FZaeb+YNvOoM1xHtQ==", "integrity": "sha512-z22Q/zFYSvbIJfW1CbfZPu4X8PddS6Qd2ORbc6h+aT6EcwAxUF3m6fA4HjNvA3TU4X0dTJRwNPB165ES3PJXzg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -713,9 +713,9 @@
} }
}, },
"node_modules/@biomejs/cli-linux-x64-musl": { "node_modules/@biomejs/cli-linux-x64-musl": {
"version": "2.5.8", "version": "2.5.9",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.8.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.9.tgz",
"integrity": "sha512-kKmiyokeISRGq2FLwvr+TzsgBusfxaZ0FZNLcOYOpCK/78tRrEjeEBLvq3xLZMpqbANgJdRPI7vZX8ZL37u9/w==", "integrity": "sha512-RXGaD0o1/pTTguYw1aeDJh9ad6Lfrui0fI7mBderTyGr7WuUJkBIttgLkR3XJyoxOkkgfBDspaUT8wXArTqLZw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -733,9 +733,9 @@
} }
}, },
"node_modules/@biomejs/cli-win32-arm64": { "node_modules/@biomejs/cli-win32-arm64": {
"version": "2.5.8", "version": "2.5.9",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.8.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.9.tgz",
"integrity": "sha512-nILH0mzm3Hi3iEdd7o7GpB8kBR/mSQwfQG/tyBqyNrY2GFtcgwfV9nV8xLmbtUpMNY/Oi0Ml1XgfR4flOdq+AA==", "integrity": "sha512-nHK+/HHC+D0ogAHUxomgoSTdjImb6fmNNVTKmf0tyu4eDL1DqPKIHc+i+UL8+b0RnAu8224qo8F2tCVnaT0A3w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -750,9 +750,9 @@
} }
}, },
"node_modules/@biomejs/cli-win32-x64": { "node_modules/@biomejs/cli-win32-x64": {
"version": "2.5.8", "version": "2.5.9",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.8.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.9.tgz",
"integrity": "sha512-I2czzXTY61f3nFJxXoMDq80t7MivxDEnCjE+8sDKoFfcKMaoQdkqhIFQ3KyY0XLzeSpUBYeNAXgD+iOV/BU0VA==", "integrity": "sha512-Yiq0H56LjXSSw/hd9YkXgSLQfzyDJzbzU2TezozxyNw+uKWAqOtqGVvBfzKRRDiaFF5avGAhHdWKx7LtDOShUw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1675,9 +1675,9 @@
} }
}, },
"node_modules/@react-querybuilder/mantine": { "node_modules/@react-querybuilder/mantine": {
"version": "8.22.5", "version": "8.23.0",
"resolved": "https://registry.npmjs.org/@react-querybuilder/mantine/-/mantine-8.22.5.tgz", "resolved": "https://registry.npmjs.org/@react-querybuilder/mantine/-/mantine-8.23.0.tgz",
"integrity": "sha512-ciLXWRh6YhFdQQwkS9x0h/z7nxe2thtq3mseTC3/KV2SQBrjBDiBoRVxQe8H2koL0FuasTmdiPU/TqDkqV9Acg==", "integrity": "sha512-gAUV9bkdMH5+ZALKYieTdOVTPMzDa/ZWw+5QdklM6u6r6o4mtgo0pIf2c9b0M008lUISmo71mcR2z1Bn2zCGnQ==",
"license": "MIT", "license": "MIT",
"peerDependencies": { "peerDependencies": {
"@mantine/core": ">=7", "@mantine/core": ">=7",
@@ -1685,7 +1685,7 @@
"@mantine/hooks": ">=7", "@mantine/hooks": ">=7",
"dayjs": ">=1", "dayjs": ">=1",
"react": ">=18", "react": ">=18",
"react-querybuilder": "8.22.5" "react-querybuilder": "8.23.0"
} }
}, },
"node_modules/@reduxjs/toolkit": { "node_modules/@reduxjs/toolkit": {
@@ -2096,9 +2096,9 @@
} }
}, },
"node_modules/@testing-library/user-event": { "node_modules/@testing-library/user-event": {
"version": "14.6.4", "version": "14.6.5",
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.4.tgz", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.5.tgz",
"integrity": "sha512-QCGwP6QrjypBLwyj5cuyfVamkaIEy/XGY+1VDehbtbQqOggYmTFpFOdWR5mPz14vX8vXLMVjDHlRNBcClyO9ew==", "integrity": "sha512-FhqjldLTpteueBaKflhNFlMT3+PM0O5fiBUivht6b9CZ1eesJyy7+g3Jr7XwJzt/Hip3ZG5hWwK1MX1FuDiE4w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -2657,16 +2657,16 @@
} }
}, },
"node_modules/@vitest/expect": { "node_modules/@vitest/expect": {
"version": "4.1.10", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.11.tgz",
"integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", "integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@standard-schema/spec": "^1.1.0", "@standard-schema/spec": "^1.1.0",
"@types/chai": "^5.2.2", "@types/chai": "^5.2.2",
"@vitest/spy": "4.1.10", "@vitest/spy": "4.1.11",
"@vitest/utils": "4.1.10", "@vitest/utils": "4.1.11",
"chai": "^6.2.2", "chai": "^6.2.2",
"tinyrainbow": "^3.1.0" "tinyrainbow": "^3.1.0"
}, },
@@ -2675,13 +2675,13 @@
} }
}, },
"node_modules/@vitest/mocker": { "node_modules/@vitest/mocker": {
"version": "4.1.10", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.11.tgz",
"integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", "integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/spy": "4.1.10", "@vitest/spy": "4.1.11",
"estree-walker": "^3.0.3", "estree-walker": "^3.0.3",
"magic-string": "^0.30.21" "magic-string": "^0.30.21"
}, },
@@ -2702,9 +2702,9 @@
} }
}, },
"node_modules/@vitest/pretty-format": { "node_modules/@vitest/pretty-format": {
"version": "4.1.10", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.11.tgz",
"integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", "integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -2715,13 +2715,13 @@
} }
}, },
"node_modules/@vitest/runner": { "node_modules/@vitest/runner": {
"version": "4.1.10", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.11.tgz",
"integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", "integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/utils": "4.1.10", "@vitest/utils": "4.1.11",
"pathe": "^2.0.3" "pathe": "^2.0.3"
}, },
"funding": { "funding": {
@@ -2729,14 +2729,14 @@
} }
}, },
"node_modules/@vitest/snapshot": { "node_modules/@vitest/snapshot": {
"version": "4.1.10", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.11.tgz",
"integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", "integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/pretty-format": "4.1.10", "@vitest/pretty-format": "4.1.11",
"@vitest/utils": "4.1.10", "@vitest/utils": "4.1.11",
"magic-string": "^0.30.21", "magic-string": "^0.30.21",
"pathe": "^2.0.3" "pathe": "^2.0.3"
}, },
@@ -2745,9 +2745,9 @@
} }
}, },
"node_modules/@vitest/spy": { "node_modules/@vitest/spy": {
"version": "4.1.10", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.11.tgz",
"integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", "integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"funding": { "funding": {
@@ -2755,13 +2755,13 @@
} }
}, },
"node_modules/@vitest/utils": { "node_modules/@vitest/utils": {
"version": "4.1.10", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.11.tgz",
"integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", "integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/pretty-format": "4.1.10", "@vitest/pretty-format": "4.1.11",
"convert-source-map": "^2.0.0", "convert-source-map": "^2.0.0",
"tinyrainbow": "^3.1.0" "tinyrainbow": "^3.1.0"
}, },
@@ -3262,9 +3262,9 @@
} }
}, },
"node_modules/dayjs": { "node_modules/dayjs": {
"version": "1.11.21", "version": "1.11.23",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.23.tgz",
"integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", "integrity": "sha512-QDTCU0M0MxR3hQfnlDJfwekQiaanm1ubOD231u73WBckQ/fsamwRLiE2GBz6D3a/xF1NgfiDLJjXBa1hYOYTtQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/debug": { "node_modules/debug": {
@@ -5080,12 +5080,12 @@
} }
}, },
"node_modules/react-querybuilder": { "node_modules/react-querybuilder": {
"version": "8.22.5", "version": "8.23.0",
"resolved": "https://registry.npmjs.org/react-querybuilder/-/react-querybuilder-8.22.5.tgz", "resolved": "https://registry.npmjs.org/react-querybuilder/-/react-querybuilder-8.23.0.tgz",
"integrity": "sha512-UyLmmxB0fp9O54pexYW/fV3skQaQT7rW1wM3LzIEbnzStvXiCj8dEQDYqwOspwDajCOScYyFBVn6tMC05OpYTg==", "integrity": "sha512-Pfa/16QVitajArvcJNgqnzqKoAj8lr0W/e7ubqCgLka1Tt9pkxSGQSjUkcKjxumpct8VsnAkKc2IFigAJCSbyg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@react-querybuilder/core": "^8.22.5", "@react-querybuilder/core": "^8.23.0",
"@reduxjs/toolkit": "^2.12.0", "@reduxjs/toolkit": "^2.12.0",
"react-redux": "^9.3.0" "react-redux": "^9.3.0"
}, },
@@ -6070,19 +6070,19 @@
} }
}, },
"node_modules/vitest": { "node_modules/vitest": {
"version": "4.1.10", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.11.tgz",
"integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", "integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/expect": "4.1.10", "@vitest/expect": "4.1.11",
"@vitest/mocker": "4.1.10", "@vitest/mocker": "4.1.11",
"@vitest/pretty-format": "4.1.10", "@vitest/pretty-format": "4.1.11",
"@vitest/runner": "4.1.10", "@vitest/runner": "4.1.11",
"@vitest/snapshot": "4.1.10", "@vitest/snapshot": "4.1.11",
"@vitest/spy": "4.1.10", "@vitest/spy": "4.1.11",
"@vitest/utils": "4.1.10", "@vitest/utils": "4.1.11",
"es-module-lexer": "^2.0.0", "es-module-lexer": "^2.0.0",
"expect-type": "^1.3.0", "expect-type": "^1.3.0",
"magic-string": "^0.30.21", "magic-string": "^0.30.21",
@@ -6110,12 +6110,12 @@
"@edge-runtime/vm": "*", "@edge-runtime/vm": "*",
"@opentelemetry/api": "^1.9.0", "@opentelemetry/api": "^1.9.0",
"@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
"@vitest/browser-playwright": "4.1.10", "@vitest/browser-playwright": "4.1.11",
"@vitest/browser-preview": "4.1.10", "@vitest/browser-preview": "4.1.11",
"@vitest/browser-webdriverio": "4.1.10", "@vitest/browser-webdriverio": "4.1.11",
"@vitest/coverage-istanbul": "4.1.10", "@vitest/coverage-istanbul": "4.1.11",
"@vitest/coverage-v8": "4.1.10", "@vitest/coverage-v8": "4.1.11",
"@vitest/ui": "4.1.10", "@vitest/ui": "4.1.11",
"happy-dom": "*", "happy-dom": "*",
"jsdom": "*", "jsdom": "*",
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0" "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"

View File

@@ -27,11 +27,11 @@
"@mantine/notifications": "9.5.1", "@mantine/notifications": "9.5.1",
"@mantine/spotlight": "9.5.1", "@mantine/spotlight": "9.5.1",
"@monaco-editor/react": "4.7.0", "@monaco-editor/react": "4.7.0",
"@react-querybuilder/mantine": "8.22.5", "@react-querybuilder/mantine": "8.23.0",
"@reduxjs/toolkit": "2.12.0", "@reduxjs/toolkit": "2.12.0",
"@rolldown/plugin-babel": "0.2.3", "@rolldown/plugin-babel": "0.2.3",
"axios": "1.19.0", "axios": "1.19.0",
"dayjs": "1.11.21", "dayjs": "1.11.23",
"escape-string-regexp": "5.0.0", "escape-string-regexp": "5.0.0",
"interweave": "13.1.1", "interweave": "13.1.1",
"monaco-editor": "0.56.0", "monaco-editor": "0.56.0",
@@ -43,7 +43,7 @@
"react-draggable": "4.7.1", "react-draggable": "4.7.1",
"react-icons": "5.7.0", "react-icons": "5.7.0",
"react-infinite-scroller": "1.2.6", "react-infinite-scroller": "1.2.6",
"react-querybuilder": "8.22.5", "react-querybuilder": "8.23.0",
"react-redux": "9.3.0", "react-redux": "9.3.0",
"react-router-dom": "7.18.2", "react-router-dom": "7.18.2",
"react-swipeable": "7.0.2", "react-swipeable": "7.0.2",
@@ -55,13 +55,13 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/types": "^8.0.4", "@babel/types": "^8.0.4",
"@biomejs/biome": "2.5.8", "@biomejs/biome": "2.5.9",
"@lingui/babel-plugin-lingui-macro": "6.6.0", "@lingui/babel-plugin-lingui-macro": "6.6.0",
"@lingui/cli": "6.6.0", "@lingui/cli": "6.6.0",
"@lingui/vite-plugin": "6.6.0", "@lingui/vite-plugin": "6.6.0",
"@testing-library/jest-dom": "7.0.1", "@testing-library/jest-dom": "7.0.1",
"@testing-library/react": "16.3.2", "@testing-library/react": "16.3.2",
"@testing-library/user-event": "14.6.4", "@testing-library/user-event": "14.6.5",
"@types/mousetrap": "1.6.15", "@types/mousetrap": "1.6.15",
"@types/react": "19.2.18", "@types/react": "19.2.18",
"@types/react-dom": "19.2.4", "@types/react-dom": "19.2.4",
@@ -74,7 +74,7 @@
"typescript": "7.0.2", "typescript": "7.0.2",
"vite": "8.2.1", "vite": "8.2.1",
"vite-plugin-checker": "0.14.5", "vite-plugin-checker": "0.14.5",
"vitest": "4.1.10", "vitest": "4.1.11",
"yaml": "2.9.0" "yaml": "2.9.0"
}, },
"overrides": { "overrides": {

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.commafeed</groupId> <groupId>com.commafeed</groupId>
<artifactId>commafeed</artifactId> <artifactId>commafeed</artifactId>
<version>7.3.1</version> <version>7.3.2</version>
</parent> </parent>
<artifactId>commafeed-client</artifactId> <artifactId>commafeed-client</artifactId>
<name>CommaFeed Client</name> <name>CommaFeed Client</name>

View File

@@ -0,0 +1,36 @@
import { i18n } from "@lingui/core"
import type { AxiosError } from "axios"
import { afterEach, describe, expect, it, vi } from "vitest"
import { errorToStrings } from "./client"
const axiosError = (status: number, data: unknown) =>
({
isAxiosError: true,
response: { status, data },
}) as AxiosError
describe("errorToStrings", () => {
afterEach(() => vi.restoreAllMocks())
it("translates known application error types", () => {
vi.spyOn(i18n, "_").mockReturnValue("Translated authentication error")
const error = axiosError(401, {
type: "WRONG_USERNAME_OR_PASSWORD",
message: "wrong username or password",
})
expect(errorToStrings(error)).toEqual(["Translated authentication error"])
})
it("preserves backend messages for unexpected errors", () => {
const error = axiosError(500, { message: "unexpected error" })
expect(errorToStrings(error)).toEqual(["unexpected error"])
})
it("preserves backend messages for unknown application error types", () => {
const error = axiosError(400, { type: "UNKNOWN_ERROR", message: "unknown error" })
expect(errorToStrings(error)).toEqual(["unknown error"])
})
})

View File

@@ -1,3 +1,5 @@
import { i18n, type MessageDescriptor } from "@lingui/core"
import { msg } from "@lingui/core/macro"
import axios, { type AxiosError } from "axios" import axios, { type AxiosError } from "axios"
import type { import type {
AddCategoryRequest, AddCategoryRequest,
@@ -6,6 +8,8 @@ import type {
Category, Category,
CategoryModificationRequest, CategoryModificationRequest,
CollapseRequest, CollapseRequest,
CommaFeedApplicationError,
CommaFeedExceptionType,
Entries, Entries,
FeedInfo, FeedInfo,
FeedInfoRequest, FeedInfoRequest,
@@ -31,6 +35,10 @@ import type {
UserModel, UserModel,
} from "./types" } from "./types"
const applicationErrorMessages = {
WRONG_USERNAME_OR_PASSWORD: msg`Wrong username or password`,
} satisfies Record<CommaFeedExceptionType, MessageDescriptor>
const axiosInstance = axios.create({ baseURL: "./rest", withCredentials: true }) const axiosInstance = axios.create({ baseURL: "./rest", withCredentials: true })
axiosInstance.interceptors.response.use( axiosInstance.interceptors.response.use(
response => response, response => response,
@@ -128,14 +136,25 @@ export const errorToStrings = (err: unknown) => {
let strings: string[] = [] let strings: string[] = []
if (axios.isAxiosError(err) && err.response) { if (axios.isAxiosError(err) && err.response) {
if (typeof err.response.data === "string") strings.push(err.response.data) if (isCommaFeedApplicationError(err)) {
if (isMessageError(err)) strings.push(err.response.data.message) strings.push(i18n._(applicationErrorMessages[err.response.data.type]))
if (isMessageArrayError(err)) strings = [...strings, ...err.response.data.errors] } else {
if (typeof err.response.data === "string") strings.push(err.response.data)
if (isMessageError(err)) strings.push(err.response.data.message)
if (isMessageArrayError(err)) strings = [...strings, ...err.response.data.errors]
}
} }
return strings return strings
} }
function isCommaFeedApplicationError(err: AxiosError): err is AxiosError<CommaFeedApplicationError> {
const data = err.response?.data
if (!data || typeof data !== "object" || !("type" in data)) return false
const type = data.type
return typeof type === "string" && Object.hasOwn(applicationErrorMessages, type)
}
function isMessageError(err: AxiosError): err is AxiosError<{ message: string }> { function isMessageError(err: AxiosError): err is AxiosError<{ message: string }> {
return !!err.response && !!err.response.data && typeof err.response.data === "object" && "message" in err.response.data return !!err.response && !!err.response.data && typeof err.response.data === "object" && "message" in err.response.data
} }

View File

@@ -166,7 +166,6 @@ export const starEntry = createAppAsyncThunk(
(arg: { entry: Entry; starred: boolean }) => { (arg: { entry: Entry; starred: boolean }) => {
client.entry.star({ client.entry.star({
id: arg.entry.id, id: arg.entry.id,
feedId: +arg.entry.feedId,
starred: arg.starred, starred: arg.starred,
}) })
}, },

View File

@@ -297,7 +297,6 @@ export interface LocalSettings {
export interface StarRequest { export interface StarRequest {
id: string id: string
feedId: number
starred: boolean starred: boolean
} }
@@ -338,3 +337,10 @@ export interface AuthenticationError {
message: string message: string
allowRegistrations: boolean allowRegistrations: boolean
} }
export type CommaFeedExceptionType = "WRONG_USERNAME_OR_PASSWORD"
export interface CommaFeedApplicationError {
type: CommaFeedExceptionType
message: string
}

View File

@@ -1150,6 +1150,10 @@ msgstr "موقع الكتروني"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "مرحباً! يبدو أن هذه هي المرة الأولى التي تقوم فيها بتشغيل CommaFeed. يرجى إنشاء حساب مسؤول للبدء." msgstr "مرحباً! يبدو أن هذه هي المرة الأولى التي تقوم فيها بتشغيل CommaFeed. يرجى إنشاء حساب مسؤول للبدء."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "أصفر" msgstr "أصفر"

View File

@@ -1150,6 +1150,10 @@ msgstr "Lloc web"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Benvingut! Sembla que aquesta és la primera vegada que executeu CommaFeed. Creeu un compte d'administrador per començar." msgstr "Benvingut! Sembla que aquesta és la primera vegada que executeu CommaFeed. Creeu un compte d'administrador per començar."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Groc" msgstr "Groc"

View File

@@ -1150,6 +1150,10 @@ msgstr "Webová stránka"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Vítejte! Zdá se, že je to poprvé, co spouštíte CommaFeed. Chcete-li začít, vytvořte si účet správce." msgstr "Vítejte! Zdá se, že je to poprvé, co spouštíte CommaFeed. Chcete-li začít, vytvořte si účet správce."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Žlutá" msgstr "Žlutá"

View File

@@ -1150,6 +1150,10 @@ msgstr "Gwefan"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Croeso! Ymddengys mai dyma'r tro cyntaf i chi redeg CommaFeed. Creuwch gyfrif gweinyddwr i ddechrau." msgstr "Croeso! Ymddengys mai dyma'r tro cyntaf i chi redeg CommaFeed. Creuwch gyfrif gweinyddwr i ddechrau."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Melyn" msgstr "Melyn"

View File

@@ -1150,6 +1150,10 @@ msgstr "Hjemmeside"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Velkommen! Det ser ud til at være første gang, du kører CommaFeed. Opret venligst en administratorkonto for at komme i gang." msgstr "Velkommen! Det ser ud til at være første gang, du kører CommaFeed. Opret venligst en administratorkonto for at komme i gang."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Gul" msgstr "Gul"

View File

@@ -1150,6 +1150,10 @@ msgstr "Webseite"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Willkommen! Dies scheint das erste Mal zu sein, dass Sie CommaFeed ausführen. Bitte erstellen Sie ein Administrator-Konto, um zu beginnen." msgstr "Willkommen! Dies scheint das erste Mal zu sein, dass Sie CommaFeed ausführen. Bitte erstellen Sie ein Administrator-Konto, um zu beginnen."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Gelb" msgstr "Gelb"

View File

@@ -1150,6 +1150,10 @@ msgstr "Website"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgstr "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr "Wrong username or password"
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Yellow" msgstr "Yellow"

View File

@@ -1151,6 +1151,10 @@ msgstr "Sitio web"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "¡Bienvenido! Parece que esta es la primera vez que ejecutas CommaFeed. Por favor, crea una cuenta de administrador para empezar." msgstr "¡Bienvenido! Parece que esta es la primera vez que ejecutas CommaFeed. Por favor, crea una cuenta de administrador para empezar."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Amarillo" msgstr "Amarillo"

View File

@@ -1150,6 +1150,10 @@ msgstr "وب سایت"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "خوش آمدید! به نظر می‌رسد این اولین بار است که CommaFeed را اجرا می‌کنید. لطفاً برای شروع یک حساب مدیر ایجاد کنید." msgstr "خوش آمدید! به نظر می‌رسد این اولین بار است که CommaFeed را اجرا می‌کنید. لطفاً برای شروع یک حساب مدیر ایجاد کنید."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "زرد" msgstr "زرد"

View File

@@ -1150,6 +1150,10 @@ msgstr "Verkkosivusto"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Tervetuloa! Näyttää siltä, että suoritat CommaFeediä ensimmäistä kertaa. Luo ylläpitäjän tili aloittaaksesi." msgstr "Tervetuloa! Näyttää siltä, että suoritat CommaFeediä ensimmäistä kertaa. Luo ylläpitäjän tili aloittaaksesi."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Keltainen" msgstr "Keltainen"

View File

@@ -460,11 +460,11 @@ msgstr "Extensions"
#: src/components/settings/ProfileSettings.tsx #: src/components/settings/ProfileSettings.tsx
msgid "Google Reader API" msgid "Google Reader API"
msgstr "" msgstr "API Google Reader"
#: src/components/settings/ProfileSettings.tsx #: src/components/settings/ProfileSettings.tsx
msgid "Google Reader API URL" msgid "Google Reader API URL"
msgstr "" msgstr "URL de l'API Google Reader"
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Grape" msgid "Grape"
@@ -1150,6 +1150,10 @@ msgstr "Site web"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Bienvenue ! Il semble que ce soit le premier démarrage de Commafeed. Avant tout, vous devez créer un compte administrateur." msgstr "Bienvenue ! Il semble que ce soit le premier démarrage de Commafeed. Avant tout, vous devez créer un compte administrateur."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr "Utilisateur ou mot de passe incorrect"
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Jaune" msgstr "Jaune"

View File

@@ -1151,6 +1151,10 @@ msgstr "Páxina web"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Benvida! Semella que é a primeira vez que executas CommaFeed. Para comezar, crea unha conta de administración." msgstr "Benvida! Semella que é a primeira vez que executas CommaFeed. Para comezar, crea unha conta de administración."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Amarelo" msgstr "Amarelo"

View File

@@ -1150,6 +1150,10 @@ msgstr "Webhely"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Üdvözöljük! Úgy tűnik, ez az első alkalom, hogy a CommaFeedet futtatja. Kérjük, hozzon létre egy rendszergazdai fiókot a kezdéshez." msgstr "Üdvözöljük! Úgy tűnik, ez az első alkalom, hogy a CommaFeedet futtatja. Kérjük, hozzon létre egy rendszergazdai fiókot a kezdéshez."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Sárga" msgstr "Sárga"

View File

@@ -1150,6 +1150,10 @@ msgstr "Situs Web"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Selamat datang! Ini sepertinya pertama kalinya Anda menjalankan CommaFeed. Silakan buat akun administrator untuk memulai." msgstr "Selamat datang! Ini sepertinya pertama kalinya Anda menjalankan CommaFeed. Silakan buat akun administrator untuk memulai."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Kuning" msgstr "Kuning"

View File

@@ -1150,6 +1150,10 @@ msgstr "Sito web"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Benvenuto! Sembra che sia la prima volta che esegui CommaFeed. Crea un account amministratore per iniziare." msgstr "Benvenuto! Sembra che sia la prima volta che esegui CommaFeed. Crea un account amministratore per iniziare."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Giallo" msgstr "Giallo"

View File

@@ -1150,6 +1150,10 @@ msgstr "ウェブサイト"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "ようこそ!CommaFeedを初めて実行するようです。開始するには管理者アカウントを作成してください。" msgstr "ようこそ!CommaFeedを初めて実行するようです。開始するには管理者アカウントを作成してください。"
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "イエロー" msgstr "イエロー"

View File

@@ -1150,6 +1150,10 @@ msgstr "웹사이트"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "환영합니다! CommaFeed를 처음 실행하는 것 같습니다. 시작하려면 관리자 계정을 만드십시오." msgstr "환영합니다! CommaFeed를 처음 실행하는 것 같습니다. 시작하려면 관리자 계정을 만드십시오."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "옐로우" msgstr "옐로우"

View File

@@ -1150,6 +1150,10 @@ msgstr "Laman web"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Selamat datang! Ini nampaknya kali pertama anda menjalankan CommaFeed. Sila cipta akaun pentadbir untuk bermula." msgstr "Selamat datang! Ini nampaknya kali pertama anda menjalankan CommaFeed. Sila cipta akaun pentadbir untuk bermula."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Kuning" msgstr "Kuning"

View File

@@ -1150,6 +1150,10 @@ msgstr "Nettsted"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Velkommen! Det ser ut til å være første gang du kjører CommaFeed. Vennligst opprett en administratorkonto for å komme i gang." msgstr "Velkommen! Det ser ut til å være første gang du kjører CommaFeed. Vennligst opprett en administratorkonto for å komme i gang."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Gul" msgstr "Gul"

View File

@@ -1150,6 +1150,10 @@ msgstr "Website"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Welkom! Dit lijkt de eerste keer te zijn dat je CommaFeed draait. Maak een beheerdersaccount aan om aan de slag te gaan." msgstr "Welkom! Dit lijkt de eerste keer te zijn dat je CommaFeed draait. Maak een beheerdersaccount aan om aan de slag te gaan."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Geel" msgstr "Geel"

View File

@@ -1150,6 +1150,10 @@ msgstr "Nettstad"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Velkomen! Det ser ut til å vera fyrste gongen du køyrer CommaFeed. Ver venleg og opprett ein administratorkonto for å koma i gang." msgstr "Velkomen! Det ser ut til å vera fyrste gongen du køyrer CommaFeed. Ver venleg og opprett ein administratorkonto for å koma i gang."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Gul" msgstr "Gul"

View File

@@ -1150,6 +1150,10 @@ msgstr "Strona internetowa"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Witaj! Wygląda na to, że uruchamiasz CommaFeed po raz pierwszy. Aby rozpocząć, utwórz konto administratora." msgstr "Witaj! Wygląda na to, że uruchamiasz CommaFeed po raz pierwszy. Aby rozpocząć, utwórz konto administratora."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Żółty" msgstr "Żółty"

View File

@@ -1150,6 +1150,10 @@ msgstr "Site"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Bem-vindo! Esta parece ser a primeira vez que você está executando o CommaFeed. Crie uma conta de administrador para começar." msgstr "Bem-vindo! Esta parece ser a primeira vez que você está executando o CommaFeed. Crie uma conta de administrador para começar."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Amarelo" msgstr "Amarelo"

View File

@@ -1150,6 +1150,10 @@ msgstr "Веб-сайт"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Добро пожаловать! Похоже, вы запускаете CommaFeed в первый раз. Пожалуйста, создайте учетную запись администратора, чтобы начать работу." msgstr "Добро пожаловать! Похоже, вы запускаете CommaFeed в первый раз. Пожалуйста, создайте учетную запись администратора, чтобы начать работу."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Желтый" msgstr "Желтый"

View File

@@ -1150,6 +1150,10 @@ msgstr "Webová stránka"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Vitajte! Zdá sa, že CommaFeed spúšťate prvýkrát. Ak chcete začať, vytvorte si účet správcu." msgstr "Vitajte! Zdá sa, že CommaFeed spúšťate prvýkrát. Ak chcete začať, vytvorte si účet správcu."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Žltá" msgstr "Žltá"

View File

@@ -1150,6 +1150,10 @@ msgstr "Webbplats"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Välkommen! Det verkar vara första gången du kör CommaFeed. Skapa ett administratörskonto för att komma igång." msgstr "Välkommen! Det verkar vara första gången du kör CommaFeed. Skapa ett administratörskonto för att komma igång."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Gul" msgstr "Gul"

View File

@@ -1150,6 +1150,10 @@ msgstr "Web sitesi"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "Hoş geldiniz! Görünüşe göre CommaFeed'i ilk kez çalıştırıyorsunuz. Başlamak için lütfen bir yönetici hesabı oluşturun." msgstr "Hoş geldiniz! Görünüşe göre CommaFeed'i ilk kez çalıştırıyorsunuz. Başlamak için lütfen bir yönetici hesabı oluşturun."
#: src/app/client.ts
msgid "Wrong username or password"
msgstr ""
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "Sarı" msgstr "Sarı"

View File

@@ -1150,6 +1150,10 @@ msgstr "网站"
msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started." msgid "Welcome! This appears to be the first time you're running CommaFeed. Please create an administrator account to get started."
msgstr "欢迎!当前页仅当您第一次使用CommaFeed时出现,请创建一个管理员帐号以开始使用。" msgstr "欢迎!当前页仅当您第一次使用CommaFeed时出现,请创建一个管理员帐号以开始使用。"
#: src/app/client.ts
msgid "Wrong username or password"
msgstr "用户名或密码错误"
#: src/components/settings/DisplaySettings.tsx #: src/components/settings/DisplaySettings.tsx
msgid "Yellow" msgid "Yellow"
msgstr "黄" msgstr "黄"

View File

@@ -6,15 +6,15 @@
<parent> <parent>
<groupId>com.commafeed</groupId> <groupId>com.commafeed</groupId>
<artifactId>commafeed</artifactId> <artifactId>commafeed</artifactId>
<version>7.3.1</version> <version>7.3.2</version>
</parent> </parent>
<artifactId>commafeed-server</artifactId> <artifactId>commafeed-server</artifactId>
<name>CommaFeed Server</name> <name>CommaFeed Server</name>
<packaging>quarkus</packaging> <packaging>quarkus</packaging>
<properties> <properties>
<quarkus.version>3.38.2</quarkus.version> <quarkus.version>3.38.3</quarkus.version>
<querydsl.version>7.5</querydsl.version> <querydsl.version>7.6</querydsl.version>
<rome.version>2.1.0</rome.version> <rome.version>2.1.0</rome.version>
<!-- renovate: depName=com.google.googlejavaformat:google-java-format --> <!-- renovate: depName=com.google.googlejavaformat:google-java-format -->
<google-java-format.version>1.36.1</google-java-format.version> <google-java-format.version>1.36.1</google-java-format.version>
@@ -35,7 +35,7 @@
<dependency> <dependency>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId> <artifactId>protobuf-java</artifactId>
<version>4.35.1</version> <version>4.36.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
@@ -245,7 +245,7 @@
<dependency> <dependency>
<groupId>com.puppycrawl.tools</groupId> <groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId> <artifactId>checkstyle</artifactId>
<version>13.11.0</version> <version>14.0.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
<executions> <executions>
@@ -302,7 +302,7 @@
<dependency> <dependency>
<groupId>com.commafeed</groupId> <groupId>com.commafeed</groupId>
<artifactId>commafeed-client</artifactId> <artifactId>commafeed-client</artifactId>
<version>7.3.1</version> <version>7.3.2</version>
</dependency> </dependency>
<!-- compile-time processors --> <!-- compile-time processors -->
@@ -399,7 +399,7 @@
<dependency> <dependency>
<groupId>dev.cel</groupId> <groupId>dev.cel</groupId>
<artifactId>cel</artifactId> <artifactId>cel</artifactId>
<version>0.13.1</version> <version>0.14.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.passay</groupId> <groupId>org.passay</groupId>
@@ -482,7 +482,7 @@
<dependency> <dependency>
<groupId>org.mock-server</groupId> <groupId>org.mock-server</groupId>
<artifactId>mockserver-junit-jupiter</artifactId> <artifactId>mockserver-junit-jupiter</artifactId>
<version>7.5.0</version> <version>7.6.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@@ -1,4 +1,4 @@
FROM ibm-semeru-runtimes:open-jdk-25.0.4.0-jre@sha256:02888a2306c2cb8af22a05b2c41be90fdc9df5f4611861ddf6ea90c874de65e6 FROM ibm-semeru-runtimes:open-jdk-25.0.4.0-jre@sha256:524f0d04723aff42ed4142ab2621fa55f22cb691763cd75b59eee86749e2e872
EXPOSE 8082 EXPOSE 8082
RUN mkdir -p /commafeed/data RUN mkdir -p /commafeed/data

View File

@@ -1,5 +1,7 @@
package com.commafeed; package com.commafeed;
import com.commafeed.frontend.exception.CommaFeedApplicationException;
import com.commafeed.frontend.exception.CommaFeedExceptionType;
import com.commafeed.security.CookieService; import com.commafeed.security.CookieService;
import io.quarkus.runtime.annotations.RegisterForReflection; import io.quarkus.runtime.annotations.RegisterForReflection;
@@ -26,6 +28,18 @@ public class ExceptionMappers {
private final CookieService cookieService; private final CookieService cookieService;
private final CommaFeedConfiguration config; private final CommaFeedConfiguration config;
@ServerExceptionMapper(CommaFeedApplicationException.class)
public RestResponse<CommaFeedApplicationError> applicationError(
CommaFeedApplicationException e) {
ResponseBuilder<CommaFeedApplicationError> response =
ResponseBuilder.create(
e.type().status(), new CommaFeedApplicationError(e.type(), e.getMessage()));
if (e.type().status() == Status.UNAUTHORIZED) {
response.cookie(cookieService.buildLogoutCookie());
}
return response.build();
}
@ServerExceptionMapper(UnauthorizedException.class) @ServerExceptionMapper(UnauthorizedException.class)
public RestResponse<UnauthorizedResponse> unauthorized(UnauthorizedException e) { public RestResponse<UnauthorizedResponse> unauthorized(UnauthorizedException e) {
return RestResponse.status( return RestResponse.status(
@@ -55,4 +69,7 @@ public class ExceptionMappers {
@RegisterForReflection @RegisterForReflection
public record ValidationFailed(String message) {} public record ValidationFailed(String message) {}
@RegisterForReflection
public record CommaFeedApplicationError(CommaFeedExceptionType type, String message) {}
} }

View File

@@ -98,15 +98,14 @@ public class FeedEntryService {
} }
} }
public void starEntry(User user, Long entryId, Long subscriptionId, boolean starred) { public void starEntry(User user, Long entryId, boolean starred) {
FeedEntry entry = feedEntryDAO.findById(entryId);
FeedSubscription sub = feedSubscriptionDAO.findById(user, subscriptionId); if (entry == null) {
if (sub == null) {
return; return;
} }
FeedEntry entry = feedEntryDAO.findById(entryId); FeedSubscription sub = feedSubscriptionDAO.findByFeed(user, entry.getFeed());
if (entry == null) { if (sub == null) {
return; return;
} }

View File

@@ -2,8 +2,10 @@ package com.commafeed.backend.service;
import com.commafeed.backend.dao.FeedEntryDAO; import com.commafeed.backend.dao.FeedEntryDAO;
import com.commafeed.backend.dao.FeedEntryTagDAO; import com.commafeed.backend.dao.FeedEntryTagDAO;
import com.commafeed.backend.dao.FeedSubscriptionDAO;
import com.commafeed.backend.model.FeedEntry; import com.commafeed.backend.model.FeedEntry;
import com.commafeed.backend.model.FeedEntryTag; import com.commafeed.backend.model.FeedEntryTag;
import com.commafeed.backend.model.FeedSubscription;
import com.commafeed.backend.model.User; import com.commafeed.backend.model.User;
import jakarta.inject.Singleton; import jakarta.inject.Singleton;
@@ -20,6 +22,7 @@ public class FeedEntryTagService {
private final FeedEntryDAO feedEntryDAO; private final FeedEntryDAO feedEntryDAO;
private final FeedEntryTagDAO feedEntryTagDAO; private final FeedEntryTagDAO feedEntryTagDAO;
private final FeedSubscriptionDAO feedSubscriptionDAO;
public void updateTags(User user, Long entryId, List<String> tagNames) { public void updateTags(User user, Long entryId, List<String> tagNames) {
FeedEntry entry = feedEntryDAO.findById(entryId); FeedEntry entry = feedEntryDAO.findById(entryId);
@@ -27,6 +30,11 @@ public class FeedEntryTagService {
return; return;
} }
FeedSubscription sub = feedSubscriptionDAO.findByFeed(user, entry.getFeed());
if (sub == null) {
return;
}
List<FeedEntryTag> existingTags = feedEntryTagDAO.findByEntry(user, entry); List<FeedEntryTag> existingTags = feedEntryTagDAO.findByEntry(user, entry);
Set<String> existingTagNames = Set<String> existingTagNames =
existingTags.stream().map(FeedEntryTag::getName).collect(Collectors.toSet()); existingTags.stream().map(FeedEntryTag::getName).collect(Collectors.toSet());

View File

@@ -0,0 +1,20 @@
package com.commafeed.frontend.exception;
import java.io.Serial;
import java.util.Objects;
public class CommaFeedApplicationException extends RuntimeException {
@Serial private static final long serialVersionUID = 1L;
private final CommaFeedExceptionType type;
public CommaFeedApplicationException(CommaFeedExceptionType type) {
super(Objects.requireNonNull(type).message());
this.type = type;
}
public CommaFeedExceptionType type() {
return type;
}
}

View File

@@ -0,0 +1,23 @@
package com.commafeed.frontend.exception;
import org.jboss.resteasy.reactive.RestResponse.Status;
public enum CommaFeedExceptionType {
WRONG_USERNAME_OR_PASSWORD(Status.UNAUTHORIZED, "wrong username or password");
private final Status status;
private final String message;
CommaFeedExceptionType(Status status, String message) {
this.status = status;
this.message = message;
}
public Status status() {
return status;
}
public String message() {
return message;
}
}

View File

@@ -19,9 +19,6 @@ public class StarRequest implements Serializable {
@Size(max = 128) @Size(max = 128)
private String id; private String id;
@Schema(description = "feed id", required = true)
private Long feedId;
@Schema(description = "starred or not", required = true) @Schema(description = "starred or not", required = true)
private boolean starred; private boolean starred;
} }

View File

@@ -89,11 +89,9 @@ public class EntryREST {
@Valid @Parameter(description = "Star Request", required = true) StarRequest req) { @Valid @Parameter(description = "Star Request", required = true) StarRequest req) {
Preconditions.checkNotNull(req); Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId()); Preconditions.checkNotNull(req.getId());
Preconditions.checkNotNull(req.getFeedId());
User user = authenticationContext.getCurrentUser(); User user = authenticationContext.getCurrentUser();
feedEntryService.starEntry( feedEntryService.starEntry(user, Long.valueOf(req.getId()), req.isStarred());
user, Long.valueOf(req.getId()), req.getFeedId(), req.isStarred());
return Response.ok().build(); return Response.ok().build();
} }

View File

@@ -388,9 +388,7 @@ public class FeverREST {
if ("read".equals(action) || "unread".equals(action)) { if ("read".equals(action) || "unread".equals(action)) {
feedEntryService.markEntry(user, id, "read".equals(action)); feedEntryService.markEntry(user, id, "read".equals(action));
} else if ("saved".equals(action) || "unsaved".equals(action)) { } else if ("saved".equals(action) || "unsaved".equals(action)) {
FeedEntry entry = feedEntryDAO.findById(id); feedEntryService.starEntry(user, id, "saved".equals(action));
FeedSubscription sub = feedSubscriptionDAO.findByFeed(user, entry.getFeed());
feedEntryService.starEntry(user, id, sub.getId(), "saved".equals(action));
} }
} else if ("feed".equals(source)) { } else if ("feed".equals(source)) {
FeedSubscription subscription = feedSubscriptionDAO.findById(user, id); FeedSubscription subscription = feedSubscriptionDAO.findById(user, id);

View File

@@ -402,16 +402,11 @@ public class GoogleReaderREST {
if (markUnread) { if (markUnread) {
feedEntryService.markEntry(user, entryId, false); feedEntryService.markEntry(user, entryId, false);
} }
if (star || unstar) { if (star) {
FeedSubscription sub = feedSubscriptionDAO.findByFeed(user, entry.getFeed()); feedEntryService.starEntry(user, entryId, true);
if (sub != null) { }
if (star) { if (unstar) {
feedEntryService.starEntry(user, entryId, sub.getId(), true); feedEntryService.starEntry(user, entryId, false);
}
if (unstar) {
feedEntryService.starEntry(user, entryId, sub.getId(), false);
}
}
} }
} }

View File

@@ -4,8 +4,9 @@ import com.commafeed.backend.dao.UnitOfWork;
import com.commafeed.backend.model.User; import com.commafeed.backend.model.User;
import com.commafeed.backend.model.UserRole.Role; import com.commafeed.backend.model.UserRole.Role;
import com.commafeed.backend.service.UserService; import com.commafeed.backend.service.UserService;
import com.commafeed.frontend.exception.CommaFeedApplicationException;
import com.commafeed.frontend.exception.CommaFeedExceptionType;
import io.quarkus.security.AuthenticationFailedException;
import io.quarkus.security.identity.AuthenticationRequestContext; import io.quarkus.security.identity.AuthenticationRequestContext;
import io.quarkus.security.identity.IdentityProvider; import io.quarkus.security.identity.IdentityProvider;
import io.quarkus.security.identity.SecurityIdentity; import io.quarkus.security.identity.SecurityIdentity;
@@ -48,7 +49,8 @@ public class DatabaseUsernamePasswordIdentityProvider
new String( new String(
request.getPassword().getPassword()))); request.getPassword().getPassword())));
if (user.isEmpty()) { if (user.isEmpty()) {
throw new AuthenticationFailedException("wrong username or password"); throw new CommaFeedApplicationException(
CommaFeedExceptionType.WRONG_USERNAME_OR_PASSWORD);
} }
Set<Role> roles = unitOfWork.call(() -> userService.getRoles(user.get())); Set<Role> roles = unitOfWork.call(() -> userService.getRoles(user.get()));

View File

@@ -36,7 +36,7 @@ class AuthentificationIT {
page.navigate(getLoginPageUrl()); page.navigate(getLoginPageUrl());
PlaywrightTestUtils.login(page, TestConstants.ADMIN_USERNAME, "wrong_password"); PlaywrightTestUtils.login(page, TestConstants.ADMIN_USERNAME, "wrong_password");
PlaywrightAssertions.assertThat(page.getByRole(AriaRole.ALERT)) PlaywrightAssertions.assertThat(page.getByRole(AriaRole.ALERT))
.containsText("wrong username or password"); .containsText("Wrong username or password");
} }
@Test @Test

View File

@@ -1,7 +1,9 @@
package com.commafeed.integration; package com.commafeed.integration;
import com.commafeed.ExceptionMappers.CommaFeedApplicationError;
import com.commafeed.ExceptionMappers.UnauthorizedResponse; import com.commafeed.ExceptionMappers.UnauthorizedResponse;
import com.commafeed.TestConstants; import com.commafeed.TestConstants;
import com.commafeed.frontend.exception.CommaFeedExceptionType;
import com.commafeed.frontend.model.Entries; import com.commafeed.frontend.model.Entries;
import com.commafeed.frontend.model.UserModel; import com.commafeed.frontend.model.UserModel;
import com.commafeed.frontend.model.request.MarkRequest; import com.commafeed.frontend.model.request.MarkRequest;
@@ -57,6 +59,27 @@ class SecurityIT extends BaseIT {
.statusCode(HttpStatus.SC_OK); .statusCode(HttpStatus.SC_OK);
} }
@Test
void formLoginWrongPassword() {
CommaFeedApplicationError error =
RestAssured.given()
.auth()
.none()
.formParams(
"j_username",
TestConstants.ADMIN_USERNAME,
"j_password",
"wrong-password")
.post("j_security_check")
.then()
.statusCode(HttpStatus.SC_UNAUTHORIZED)
.extract()
.as(CommaFeedApplicationError.class);
Assertions.assertEquals(CommaFeedExceptionType.WRONG_USERNAME_OR_PASSWORD, error.type());
Assertions.assertEquals("wrong username or password", error.message());
}
@Test @Test
void basicAuthLogin() { void basicAuthLogin() {
RestAssured.given() RestAssured.given()

View File

@@ -45,7 +45,6 @@ class DatabaseCleaningIT extends BaseIT {
private void starEntry(String entryId, Long subscriptionId) { private void starEntry(String entryId, Long subscriptionId) {
StarRequest starRequest = new StarRequest(); StarRequest starRequest = new StarRequest();
starRequest.setId(entryId); starRequest.setId(entryId);
starRequest.setFeedId(subscriptionId);
starRequest.setStarred(true); starRequest.setStarred(true);
RestAssured.given() RestAssured.given()
.body(starRequest) .body(starRequest)
@@ -58,7 +57,6 @@ class DatabaseCleaningIT extends BaseIT {
private void unstarEntry(String entryId, Long subscriptionId) { private void unstarEntry(String entryId, Long subscriptionId) {
StarRequest starRequest = new StarRequest(); StarRequest starRequest = new StarRequest();
starRequest.setId(entryId); starRequest.setId(entryId);
starRequest.setFeedId(subscriptionId);
starRequest.setStarred(false); starRequest.setStarred(false);
RestAssured.given() RestAssured.given()
.body(starRequest) .body(starRequest)

View File

@@ -240,7 +240,6 @@ class CategoryIT extends BaseIT {
StarRequest starRequest = new StarRequest(); StarRequest starRequest = new StarRequest();
starRequest.setId(entry.getId()); starRequest.setId(entry.getId());
starRequest.setFeedId(subscriptionId);
starRequest.setStarred(true); starRequest.setStarred(true);
RestAssured.given() RestAssured.given()
.body(starRequest) .body(starRequest)

View File

@@ -121,7 +121,6 @@ class FeverIT extends BaseIT {
StarRequest starRequest = new StarRequest(); StarRequest starRequest = new StarRequest();
starRequest.setId(entry.getId()); starRequest.setId(entry.getId());
starRequest.setFeedId(subscriptionId);
starRequest.setStarred(true); starRequest.setStarred(true);
RestAssured.given().body(starRequest).contentType(ContentType.JSON).post("rest/entry/star"); RestAssured.given().body(starRequest).contentType(ContentType.JSON).post("rest/entry/star");

View File

@@ -5,7 +5,7 @@
<groupId>com.commafeed</groupId> <groupId>com.commafeed</groupId>
<artifactId>commafeed</artifactId> <artifactId>commafeed</artifactId>
<version>7.3.1</version> <version>7.3.2</version>
<name>CommaFeed</name> <name>CommaFeed</name>
<packaging>pom</packaging> <packaging>pom</packaging>