Skip to content

Say why a sign in was refused when the account can't be used right now - #312

Merged
RadicalMuffinMan merged 1 commit into
Moonfin-Client:masterfrom
benklop:feat/times-up-signin
Oct 19, 2026
Merged

RadicalMuffinMan merged 1 commit into
Moonfin-Client:masterfrom
benklop:feat/times-up-signin

Conversation

@benklop

@benklop benklop commented Oct 19, 2026

Copy link
Copy Markdown

Pull Request

Summary

When Jellyfin refuses a sign in because the account can't be used right now, for instance because the user's access schedule doesn't allow the current time, the sign in screen says "Username or password is incorrect, or access is denied." That sends people to retype a password that was right. This says the account can't sign in right now and why that might be. It is the Roku half of Moonfin-Core#1918 and Smart-TV#544.

Related Issues

Type of Change

  • Bug fix
  • New feature
  • Refactor
  • Performance improvement
  • UI/UX update
  • Documentation update
  • Build/CI change
  • Other (describe):

Changes Made

  • signInRefusedMessage() in source/api/userauth.bs: a 403 from a Jellyfin password sign in now shows "This account can't sign in right now. It may be outside its allowed hours, locked or disabled. Try again later or ask an administrator." A 401 (wrong password), a 5xx and the timeout and 404 cases keep their messages, and Emby keeps its own message. Jellyfin only puts the reason in the response body when it runs in development, and answers "Error processing request." otherwise, so the status is all the client has. I checked this against the server source and a live server log. The message therefore names the possibilities instead of claiming one.
  • Quick Connect swallowed the same refusal: once the code was approved, the exchange failing left the screen polling until it timed out. AuthenticateViaQuickConnect now keeps the HTTP status (it sends the request the way the password sign in does) and reports {ok, refused}. A refusal stops the polling and shows the same message.
  • The red error box on the sign in screen was a fixed 60 px tall and its text 10 px wider than the box, which was fine for one-line messages. The new message wraps to several lines, so the box now takes its height from the text and the text is 580 px wide.
  • One new English string in locale/en_US/translations.ts.
  • Tests in test/sign-in-refused.bs, run from npm test: the message for 403, 401 and 500, and the refused and server-error cases of the Quick Connect exchange.

Testing

  • Tested on physical Roku device
  • Tested via sideload
  • Manual testing completed
  • Not tested (explain why):

Tested on a TCL 43S405 Roku TV (Roku OS 15.3), sideloaded from npm run build, against a Jellyfin server, signing in as a non-admin user whose access schedule excludes the current time: the sign in screen shows the new message inside the error box. A wrong password for a user without a schedule still shows the old message, and a user whose schedule includes the current time signs in normally.

Not tested: Quick Connect for such a user (approving a code means signing in to the web client as them, which the server refuses outside their hours), so that path is covered by the unit test only. Other Roku models.

Jellyfin checks the account's status before it applies the password result, so for such an account a wrong password gets the same 403 and shows this message too. That is the server's order of checks.

npm run lint is clean and npm test passes (it needs Node 22 or newer for fs.glob).

Test Steps

  1. On a Jellyfin server, create a non-admin user and give them an access schedule that doesn't include the current time.
  2. Try to sign in as that user.
  3. The sign in screen shows the new message instead of "Username or password is incorrect, or access is denied."

Screenshots (if applicable)

A photo of the TV will follow in a comment.

Checklist

  • Code builds successfully
  • Code follows project style and conventions
  • No unnecessary commented-out code
  • No new warnings introduced

AI assistance

An AI assistant (Claude) helped write and test this change, as the contributing guide asks me to say. I tested it on the Roku above and can walk through any of it.

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 19, 2026 02:48

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: Moonfin-Client/Roku/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2f71d756-8fe7-42df-82d6-4be89d4b22e6
📥 Commits

Reviewing files that changed from the base of the PR and between 84d5a29 and 1937a1e.

📒 Files selected for processing: 8
  • components/config/SigninScene.bs
  • components/config/SigninScene.xml
  • components/quickConnect/QuickConnect.bs
  • locale/en_US/translations.ts
  • source/api/userauth.bs
  • test/server-compatibility.bs
  • test/server-compatibility.mjs
  • test/sign-in-refused.bs

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • Quick Connect sign-in now shows a clear message when access is refused and stops retrying.
    • Improved error-message sizing so alerts are less likely to be cut off.
    • Sign-in errors now provide more specific guidance for accounts that are unavailable or outside allowed hours.

Quick Connect authentication now distinguishes HTTP 403 refusals from other failures. The sign-in scene displays a translated refusal message, hides Quick Connect, and adjusts the error container to fit the message.

Changes: Quick Connect sign-in refusal

Layer / File(s) Summary
Authentication result and refusal message
source/api/userauth.bs, locale/en_US/translations.ts, test/sign-in-refused.bs, test/server-compatibility.*
Quick Connect authentication returns success and refusal fields, and password-login errors use a specific message for non-Emby HTTP 403 responses. The compatibility harness runs tests for refusal messages and Quick Connect results.
Quick Connect refusal display
components/quickConnect/QuickConnect.bs, components/config/SigninScene.bs, components/config/SigninScene.xml
The Quick Connect monitor passes a refusal status to the sign-in scene. The scene displays the refusal message, hides Quick Connect, and sizes the error container using the message height and a minimum height.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant QuickConnectMonitor
  participant AuthenticateViaQuickConnect
  participant QuickConnectEndpoint
  participant SigninScene
  QuickConnectMonitor->>AuthenticateViaQuickConnect: Submit secret
  AuthenticateViaQuickConnect->>QuickConnectEndpoint: POST secret and authorization headers
  QuickConnectEndpoint-->>AuthenticateViaQuickConnect: Return HTTP response
  AuthenticateViaQuickConnect-->>QuickConnectMonitor: Return ok and refused result
  QuickConnectMonitor->>SigninScene: Set authenticated status to -2
  SigninScene->>SigninScene: Display refusal message and hide Quick Connect
Loading

Suggested reviewers: radicalmuffinman

Merge Risk: ⚪ Minimal · up to 1937a

The refusal message and Quick Connect flow appear ready to merge after normal checks.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title clearly states the primary change: explaining sign-in refusal when an account cannot be used. It is specific and concise.
Description check Passed The description follows the required template and covers the purpose, related issues, change details, testing, test steps, checklist, and UI impact. It also clearly identifies the untested Quick Conne…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description follows the required template and covers the purpose, related issues, change details, testing, test steps, checklist, and UI impact. It also clearly identifies the untested Quick Connect device path.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

🔧 ast-grep (0.45.3)
locale/en_US/translations.ts

ast-grep timed out on this file

🔧 Biome (2.5.14)
locale/en_US/translations.ts

File contains syntax errors that prevent linting: Line 1: Expected a type but instead found '?'.; Line 1: expected : but instead found version; Line 1: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 1: Expected an expression for the left hand side of the > operator.; Line 2: Expected a type but instead found '!'.; Line 2: expected : but instead found TS; Line 3: expected > but instead found version; Line 2: Invalid assignment to TS> <TS version; Line 3: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 3: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 4: unterminated regex literal; Line 6: Expected an expression but instead found 'default'.; Line 8: Expected a type but instead found '/'.; Line 8: unterminated regex literal; Line 9: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 9: Expected a semicolon or an implicit sem

... [truncated 1252824 characters] ...

cted a semicolon or an implicit semicolon after a statement, but found none; Line 7126: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 7126: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 7126: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 7126: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 7126: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 7126: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 6466: Multiple default clauses inside of a switch statement are not allowed; Line 7126: unterminated string literal; Line 7130: expected } but instead the file ends

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@benklop

benklop commented Oct 19, 2026

Copy link
Copy Markdown
Author
PXL_20261019_024848605 RAW-01

@github-actions

Copy link
Copy Markdown

Build Successful

The channel compiled and packaged. The sideload zip is on the run below.

Property Value
Build Passed
Commit 1937a1e
Workflow run Build #219

@RadicalMuffinMan
RadicalMuffinMan merged commit 0d0ff27 into Moonfin-Client:master Oct 19, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants