Skip to content

feat: pages_enabled admin controls with subscription-only search#4674

Open
NorkzYT wants to merge 39 commits intoiv-org:masterfrom
NorkzYT:optional-disable-api-features
Open

feat: pages_enabled admin controls with subscription-only search#4674
NorkzYT wants to merge 39 commits intoiv-org:masterfrom
NorkzYT:optional-disable-api-features

Conversation

@NorkzYT
Copy link
Copy Markdown

@NorkzYT NorkzYT commented May 1, 2024

Summary

Adds pages_enabled admin controls for Popular, Trending, and Search. When YouTube search is disabled, users can still search within their subscriptions and saved playlists. Also prevents duplicate videos in playlists.

Motivation

Invidious admins who run family instances need control over what users can access. A parent subscribes to approved channels on a child's account, disables search/trending/popular, and the child can only browse and search within those channels. No exposure to the wider YouTube catalog.

Config

pages_enabled:
  popular: false
  trending: false
  search: false

Changes

Admin Preferences Fix

  • Checkboxes for Popular, Trending, and Search now persist when unchecked. The fallback defaulted to "on" because HTML checkboxes send no value when unchecked. Fixed to "off" to match the existing pattern for captcha_enabled and login_enabled.

Route Blocking

  • /feed/popular, /feed/trending, /hashtag/* return 403 when disabled.

  • /api/v1/search, /api/v1/search/suggestions, /api/v1/hashtag/* return 403 JSON when disabled.

Subscription-Only Search

  • When pages_enabled.search is false and the user is logged in, /search queries the subscription materialized view and playlist_videos table instead of YouTube.
  • Results merge, deduplicate by video ID, and sort by publish date.
  • Anonymous users see a 403 with a login prompt.
  • Search bar placeholder changes to "Search subscriptions & playlists..."
  • YouTube search filters (date, type, duration) are hidden.
  • Results page shows a lock icon with "Searching within your subscriptions and playlists only."

Playlist Duplicate Prevention

  • Adding a video that already exists in a playlist is now a no-op on the web UI and returns 409 via the API.
  • Applied to the web route (/playlist_ajax) and the API route (POST /api/v1/auth/playlists/:plid/videos).

UI

  • Search bar is always visible (subscription search needs it).
  • Search homepage shows a hint when YouTube search is disabled.
  • Feed menu hides disabled pages.

Files Changed

  • src/invidious/routes/preferences.cr — checkbox persistence fix
  • src/invidious/routes/before_all.cr — route blocking logic
  • src/invidious/routes/search.cr — subscription-only search mode
  • src/invidious/search/processors.crsubscriptions_and_playlists search method
  • src/invidious/routes/playlists.cr — playlist duplicate check (web)
  • src/invidious/routes/api/v1/authenticated.cr — playlist duplicate check (API)
  • src/invidious/views/template.ecr — navbar search bar
  • src/invidious/views/search_homepage.ecr — subscription hint
  • src/invidious/views/search.ecr — conditional filters and empty state
  • src/invidious/views/components/search_box.ecr — dynamic placeholder
  • locales/en-US.json — 6 new locale strings

Screenshots

image image image image image image image image

@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented May 3, 2024

Code formatting issues will be fixed soon.

@unixfox
Copy link
Copy Markdown
Member

unixfox commented May 18, 2024

If we are going to allow every specific pages to be disabled, we might as well use an array for that like:

pages_enabled:
  trending: true
  popular: true
  search: true

@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented May 18, 2024

@unixfox

Great suggestion. Do you recommend I implement it in this GitHub Pull Request or in a separate one?

@unixfox
Copy link
Copy Markdown
Member

unixfox commented May 18, 2024

Would prefer in this one but we would need to keep compatibility with existing popular_enabled parameter.

@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented May 18, 2024

Understood, that works.

@unixfox
Copy link
Copy Markdown
Member

unixfox commented May 18, 2024

@SamantazFox advice on my comment please: #4674 (comment)

@SamantazFox
Copy link
Copy Markdown
Member

If we are going to allow every specific pages to be disabled, we might as well use an array for that like:

pages_enabled:
  trending: true
  popular: true
  search: true

Yes, I second that! However, it will be a breaking change (will go with the next major version release).

@NorkzYT Though, why do you want to disable search? For the trending feed, I can understand that you may not want random crap in your home page, but why search?

@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented May 20, 2024

@SamantazFox

My plan is to enable Invidious admins to control which features are accessible to users. This is particularly important for families/my family with young children who prefer YouTube over YouTube Kids. I found that existing tools lacked the ability to give admins such granular control over user features, thus I decided to contribute to Invidious by developing these admin control features.

For instance, in my case, I want to restrict access for some users that only very young children use to only allow certain YouTube channels that are pre-approved and subscribed to their user account. By disabling features like search, trending, and popular, I can ensure that children only interact with videos from these subscribed channels and playlists, thereby preventing exposure to unsuitable and overage content.

Additionally, I propose adding a search bar specifically for subscriptions and playlists. This would allow users to quickly find videos within these predefined categories without the need to navigate through entire channels or playlists, thus saving time and ensuring a safer viewing experience.

I know that a tool called TubeArchivist has a search feature for videos that have already been downloaded. However, I am switching from TubeArchivist to Invidious because I no longer want to host 5TB of downloaded YouTube videos, especially as the library keeps growing.

@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented Jun 12, 2024

I will start working on this to complete as soon as I can.

@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented Jun 30, 2024

Complete. Someone please test as the only issue I know is the Invidious docker container becoming unhealthy if I specify pages_enabled in the environmental variables under INVIDIOUS_CONFIG: as shown below even though it works without issues in Invidious itself.

services:
  invidious:
    container_name: invidious
    hostname: invidious
    build:
      context: .
      dockerfile: docker/Dockerfile.arm64
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      # Please read the following file for a comprehensive list of all available
      # configuration options and their associated syntax:
      # https://github.com/iv-org/invidious/blob/master/config/config.example.yml
      INVIDIOUS_CONFIG: |
        db:
          dbname: invidious
          user: kemal
          password: kemal
          host: invidious-db
          port: 5432
        check_tables: true
        # external_port:
        # domain:
        # https_only: false
        # statistics_enabled: false
        hmac_key: "xxx"
        player_style: youtube
        save_player_pos: true
        registration_enabled: true
        pages_enabled:
          popular: false
          trending: false
          search: false
        captcha_enabled: false
        feed_menu: ["Subscriptions", "Playlists"]
        default_home: <none>
        related_videos: false
        admins: ["norkz"] # set your user name
    healthcheck:
      test: wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/trending || exit 1
      interval: 30s
      timeout: 5s
      retries: 2
    networks:
      - proxy

@iBicha
Copy link
Copy Markdown
Contributor

iBicha commented Jul 1, 2024

Complete. Someone please test as the only issue I know is the Invidious docker container becoming unhealthy if I specify pages_enabled in the environmental variables under INVIDIOUS_CONFIG: as shown below even though it works without issues in Invidious itself.

The health check is hitting the trending endpoint

    healthcheck:
      test: wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/trending || exit 1

Which you have disabled, so it is natural for it to appear unhealthy

@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented Jul 1, 2024

@iBicha

Ah, thank you for the explanation. Much appreciated. I went right by it and did not notice.

NorkzYT and others added 3 commits July 1, 2024 19:32
Co-authored-by: Samantaz Fox <coding@samantaz.fr>
Co-authored-by: Samantaz Fox <coding@samantaz.fr>
@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented Jul 1, 2024

@SamantazFox

Thank you for the info. Suggestions have been added and completed.

@syeopite
Copy link
Copy Markdown
Member

syeopite commented Sep 8, 2025

Hi sorry about the slow response.

I had to push a couple extra commits to this branch for a few changes that were a bit hard to explain. This is the first deprecation within the Invidious config in a long-while so I wanted to make it as smooth as possible but tackling on warnings and tests to something very much not designed for it (the deprecated annotation will not cause a message to be printed to the user in this case) involves some less than ideal code imo.

Other than that everything looks good and is ready to be merged in the next batch!

Pinging @unixfox @Fijxu @SamantazFox for any last-minute objections to the new config and deprecation before merging in the next batch.

@syeopite syeopite added the ready label Sep 8, 2025
@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented Sep 8, 2025

@syeopite

Understood, no problem. Thank you for your time and work.

@unixfox
Copy link
Copy Markdown
Member

unixfox commented Sep 8, 2025

I was wondering since the breakage of trending (#5397). Shouldn't trending be disabled by default in this PR?

Or we will come up with a new page for trending?

@NorkzYT NorkzYT force-pushed the optional-disable-api-features branch 2 times, most recently from c2d5465 to 8c922d0 Compare November 16, 2025 14:33
@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented Nov 16, 2025

The following config is not working at the moment. Will continue working on this.

pages_enabled:
  trending: true
  popular: true
  search: true

@Fijxu
Copy link
Copy Markdown
Member

Fijxu commented Nov 18, 2025

@NorkzYT Hi, I just wanted to inform you that the trending page may be removed from Invidious in #5537, so trending_enabled may be not necessary anymore. Wait until that PR concludes before making any changes to this PR ;)

@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented Nov 18, 2025

@Fijxu

Understood, I appreciate the heads-up. I will hold off on any changes until that PR concludes.

@Fijxu
Copy link
Copy Markdown
Member

Fijxu commented Dec 6, 2025

You can keep working on it since #5555 was merged and the Trending page is still available.

…debug config route

- Fix kemal_static_file_handler directory_listing to use Path types (Crystal API compat)
- Add missing search_page_disabled translation key to en-US.json
- Filter preferences default_home options based on pages_enabled config
- Add admin-only /debug_config route for verifying configuration state
@NorkzYT NorkzYT force-pushed the optional-disable-api-features branch from 6602695 to bd6dd9c Compare March 1, 2026 00:01
NorkzYT added 3 commits March 22, 2026 21:10
…ectly

HTML checkboxes send no value when unchecked, so the fallback
"|| \"on\"" always re-enabled popular/trending/search on save.
Changed default to "off" to match the pattern used by captcha_enabled,
login_enabled, and other checkbox toggles in the same handler.
…isabled

- Hide navbar search box when CONFIG.page_enabled?("search") is false
- Keep Invidious logo visible with proper width when search bar is hidden
- Hide search widget on search_homepage when search is disabled
- Block /results, /api/v1/search/suggestions in before_all guard
- Block /hashtag/* and /api/v1/hashtag/* when search is disabled
…sabled

When pages_enabled.search is false, instead of blocking search entirely,
the search bar now searches within the user's subscriptions and saved
playlists only. YouTube's search API is never called.

Changes:
- routes/search.cr: detect search_disabled, force subscription+playlist
  search for logged-in users, 403 for anonymous users
- search/processors.cr: new subscriptions_and_playlists() method that
  queries both the subscription materialized view and playlist_videos
  table, merges and deduplicates results
- before_all.cr: let /search through to the route handler (APIs still
  blocked), keep /hashtag/* blocked
- search_box.ecr: dynamic placeholder ("Search subscriptions & playlists")
- search_homepage.ecr: hint text when in subscription-only mode
- search.ecr: hide YouTube filters, show lock icon + notice, custom
  empty-results message
- template.ecr: always show search bar (subscription search needs it)
- en-US.json: 6 new locale strings for subscription-only search UX
@NorkzYT NorkzYT changed the title feat: trending_enabled and search_enabled params added feat: pages_enabled admin controls with subscription-only search Mar 22, 2026
NorkzYT added 3 commits March 23, 2026 00:11
Check if the video already exists in the playlist before inserting.
Uses the existing select_index() query. Returns 409 via the API and
silently redirects back on the web UI.

Applied to both the web route (playlist_ajax) and the API v1 route
(POST /api/v1/auth/playlists/:plid/videos).
The return from before_all did not stop the route handler from
executing. The trending/popular/hashtag routes still ran and
overwrote the 403 response. Now set a halted flag and use Kemal
halt in the before_all block to prevent route handler execution.

Error page now renders with the full Invidious theme (dark mode,
navbar, CSS) matching the rest of the UI.
@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented Mar 23, 2026

GitHub PR Complete.

Title and Description updated to explain the changes in this PR.

@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented Mar 30, 2026

@unixfox @Fjuro @syeopite

Bumping this^.

@Fjuro
Copy link
Copy Markdown
Contributor

Fjuro commented Mar 30, 2026

I think you meant @Fijxu ?

@NorkzYT
Copy link
Copy Markdown
Author

NorkzYT commented Mar 31, 2026

You are correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking This PR contains a breaking change and requires a major release need-testing This feature needs to be deployed and tested to see if it's working, and doesn't break something ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants