Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix(site): add defensive access to entitlement features#21381

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
mtojek merged 9 commits intomainfromfix/defensive-feature-access
Dec 23, 2025

Conversation

@mtojek
Copy link
Member

@mtojekmtojek commentedDec 23, 2025
edited
Loading

Fixes#14784

Summary

This PR fixes a runtime crash on the License Settings page when the entitlements response doesn't contain theuser_limit feature, and removes unused code from TemplateInsightsPage.

Changes

1. Fix: Defensive access to entitlement features (LicensesSettingsPage.tsx)

When the entitlements response doesn't contain certain feature keys (likeuser_limit), the License Settings page crashes with a runtime error because the code assumesfeatures.user_limit always exists.

Solution: Use optional chaining (?.) to safely access feature properties:

- userLimitActual={entitlementsQuery.data?.features.user_limit.actual}- userLimitLimit={entitlementsQuery.data?.features.user_limit.limit}+ userLimitActual={entitlementsQuery.data?.features.user_limit?.actual}+ userLimitLimit={entitlementsQuery.data?.features.user_limit?.limit}

The View component already handlesundefined values gracefully through its optional prop types.

2. Test: Storybook story for the fix

AddedLicensesSettingsPage.stories.tsx withWithoutUserLimitFeature story that tests the page renders correctly when entitlements don't includeuser_limit.

3. Refactor: Remove unused code from TemplateInsightsPage

TheuserLimit prop inActiveUsersPanel was passed through but never actually used in the render. This removes:

  • entitlements query fromTemplateInsightsPage
  • entitlements prop fromTemplateInsightsPageView
  • userLimit prop fromActiveUsersPanel
  • Associated unused imports (entitlements,Entitlements,useEmbeddedMetadata)

When entitlement features like user_limit might not exist in theresponse, using optional chaining prevents runtime errors.This fixes the License page crash when user_limit feature is notpresent in the entitlements response.Fixes#14784
Verifies that LicensesSettingsPageView renders correctly whenuserLimit feature values are undefined.
Verifies that the page renders correctly when the entitlementsresponse does not include user_limit feature.
@mtojekmtojekforce-pushed thefix/defensive-feature-access branch from60baf2e tod634893CompareDecember 23, 2025 11:40
@mtojekmtojekforce-pushed thefix/defensive-feature-access branch fromdbf5a3e to45a8253CompareDecember 23, 2025 11:52
@mtojekmtojek changed the titlefix(site): defensive access to entitlement featuresfix(site): add defensive access to entitlement featuresDec 23, 2025
@mtojekmtojek marked this pull request as ready for reviewDecember 23, 2025 12:19
@DanielleMaywood
Copy link
Contributor

Is there a reason for using jest over storybook?

@mtojek
Copy link
MemberAuthor

Yes, there is. The culprit isLicensesSettingsPage.tsx, which is before going into PageView. Storybooks operate on PageView components.

@DanielleMaywood
Copy link
Contributor

DanielleMaywood commentedDec 23, 2025
edited
Loading

We have a couple of options then:

mtojek reacted with thumbs up emoji

@mtojekmtojek marked this pull request as draftDecember 23, 2025 13:04
Comment on lines +80 to +81
userLimitActual={entitlementsQuery.data?.features.user_limit?.actual}
userLimitLimit={entitlementsQuery.data?.features.user_limit?.limit}
Copy link
Contributor

@EhabYEhabYDec 23, 2025
edited
Loading

Choose a reason for hiding this comment

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

features: Record<FeatureName, Feature>;, technically any index access should use the?. notation (no guarantees on the existence). There's even atsconfig.json config for this:https://www.typescriptlang.org/tsconfig/#noUncheckedIndexedAccess

This issue is that if this is enabled it might require a humongous amount of changes

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

TIL!

I understand that it is something we definitely don't want to enable without wider refactor 😅 ?

Copy link
Contributor

Choose a reason for hiding this comment

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

So I do not have a workingsite rn but if you add the option:

"compilerOptions": {"noUncheckedIndexedAccess":true  }

How many failures are there when compiling? This is def beyond the scope of this PR though 😓

Copy link
MemberAuthor

@mtojekmtojekDec 23, 2025
edited
Loading

Choose a reason for hiding this comment

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

I involved Claude & mux in this exercise. Here are the results:

Total: 257 errors, 89 files

TS253286Object is possibly 'undefined'
TS234562Argument of type 'X | undefined' is not assignable to...
TS232256Type 'X | undefined' is not assignable to type...
TS1804846'X' is possibly 'undefined'
Others7(TS2538, TS2339, TS2769, TS2488)

I asked to create a draft for better picture (clauding now), but we would need more eyes on this anyway 😅

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Here is the first draft:#21383

Copy link
Contributor

Choose a reason for hiding this comment

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

Hahahaha I love how the way it solves this is by asserting (and thus breaking at run time anyway). 145 lines is not bad though, I'm guessing in some cases we can assert and in others we just "handle" the undefined

… user_limitAdded LicensesSettingsPage.stories.tsx with WithoutUserLimitFeature storythat tests the page component renders correctly when entitlements.featuresdoes not include user_limit.
@mtojekmtojekforce-pushed thefix/defensive-feature-access branch from2181a02 to5e0c9f4CompareDecember 23, 2025 13:13
mtojekand others added3 commitsDecember 23, 2025 13:30
- LicensesSettingsPage.stories.tsx: WithoutUserLimitFeature story- TemplateInsightsPage.stories.tsx: Added entitlements with user_limit  to Loaded story, and WithoutUserLimitFeature story with undefined  entitlements
The userLimit prop in ActiveUsersPanel was never used - it was passedthrough but not rendered. This removes:- entitlements query from TemplateInsightsPage- entitlements prop from TemplateInsightsPageView- userLimit prop from ActiveUsersPanel- Associated unused imports
Copy link
MemberAuthor

@mtojekmtojek left a comment

Choose a reason for hiding this comment

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

@DanielleMaywood Thanks for challenging. I switched to Storybook and actually discovered unused code in template insights (we don't draw the limit line anymore).

Comment on lines +80 to +81
userLimitActual={entitlementsQuery.data?.features.user_limit?.actual}
userLimitLimit={entitlementsQuery.data?.features.user_limit?.limit}
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

TIL!

I understand that it is something we definitely don't want to enable without wider refactor 😅 ?

@mtojekmtojek requested a review fromEhabYDecember 23, 2025 13:52
@mtojekmtojek marked this pull request as ready for reviewDecember 23, 2025 13:52
Copy link
Contributor

@EhabYEhabY left a comment
edited
Loading

Choose a reason for hiding this comment

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

LGTM, I'm not too familiar with Storybook though 😅

Comment on lines -254 to -258
userLimit={
entitlements?.features.user_limit.enabled
?entitlements?.features.user_limit.limit
:undefined
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Was this just passed tonothing?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Passed andunused 👍

Comment on lines +80 to +81
userLimitActual={entitlementsQuery.data?.features.user_limit?.actual}
userLimitLimit={entitlementsQuery.data?.features.user_limit?.limit}
Copy link
Contributor

Choose a reason for hiding this comment

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

So I do not have a workingsite rn but if you add the option:

"compilerOptions": {"noUncheckedIndexedAccess":true  }

How many failures are there when compiling? This is def beyond the scope of this PR though 😓

@mtojekmtojek merged commit923c04e intomainDec 23, 2025
31 of 33 checks passed
@mtojekmtojek deleted the fix/defensive-feature-access branchDecember 23, 2025 15:00
@github-actionsgithub-actionsbot locked and limited conversation to collaboratorsDec 23, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.

Reviewers

@EhabYEhabYEhabY approved these changes

@DanielleMaywoodDanielleMaywoodDanielleMaywood approved these changes

Assignees

@mtojekmtojek

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

License withoutuser_limit crashes license UI page

4 participants

@mtojek@DanielleMaywood@EhabY

[8]ページ先頭

©2009-2025 Movatter.jp