-
-
Notifications
You must be signed in to change notification settings - Fork 354
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[core] [docs] Add warnings, docs and gating for paid features #3156
Conversation
bharatkashyap
commented
Feb 1, 2024
•
edited
Loading
edited
- I've read and followed the contributing guide on how to create great pull requests.
- https://deploy-preview-3156--mui-toolpad-docs.netlify.app/toolpad/getting-started/roadmap/#paid-plan
- Closes Implement pro features flag with license key #3113
Scenario | Warning |
---|---|
Using paid features on a free plan | ![]() |
Using paid features on a paid plan | ![]() |
Adding roles while on a free plan | ![]() |
'role permissions'?: boolean; | ||
} | ||
|
||
export function detectPaidFeatures(application: Application): PaidFeaturesConfig | null { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These don't seem to be used outside of this module, why export them?
export function detectPaidFeatures(application: Application): PaidFeaturesConfig | null { | |
function detectPaidFeatures(application: Application): PaidFeaturesConfig | null { |
} | ||
|
||
const { authorization } = application.spec; | ||
const hasRoles = authorization.roles && authorization.roles.length > 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't have the roles property at all IMO.
const hasRoles = authorization.roles && authorization.roles.length > 0; | |
const hasRoles = !!application?.spec?.authorization?.roles |
packages/toolpad-core/src/appDom.ts
Outdated
@@ -1184,3 +1187,8 @@ export function getPageTitle(node: PageNode): string { | |||
export function isCodePage(node: PageNode): boolean { | |||
return !!node.attributes.codeFile; | |||
} | |||
|
|||
export function getPlan(dom: AppDom): ToolpadPlan | undefined { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not make this apply the default?
export function getPlan(dom: AppDom): ToolpadPlan | undefined { | |
export function getPlan(dom: AppDom): ToolpadPlan { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few remarks, otherwise this is good 👍
|
||
- ### Authorization | ||
|
||
Features allowing you to grant conditional access to pages based on user roles are part of this proposed paid plan. Read more about this feature on [authorisation](/toolpad/concepts/rbac/). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Features allowing you to grant conditional access to pages based on user roles are part of this proposed paid plan. Read more about this feature on [authorisation](/toolpad/concepts/rbac/). | |
Features allowing you to grant conditional access to pages based on user roles are part of this proposed paid plan. Read more about this feature on [authorization](/toolpad/concepts/rbac/). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks Bharat! Added some feedback but should all be simple to address!
|
||
const { authorization } = application.spec; | ||
const hasRoles = authorization.roles && authorization.roles.length > 0; | ||
const hasPaidFeatures = hasRoles; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my docs PR (#3067) I got the understanding that the whole Azure AD provider, even if only used for authentication, would also be a paid feature. Should it not be?
If it is we would need to check application.authentication.providers
for if azure-ad
is there.
If not I can adjust my docs PR.
@@ -964,6 +966,22 @@ export function getRequiredEnvVars(dom: appDom.AppDom): Set<string> { | |||
return new Set(allVars); | |||
} | |||
|
|||
export interface PaidFeaturesConfig { | |||
roles?: boolean; | |||
'role permissions'?: boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this property needed, I guess just roles
should cover it? Also if it's needed I guess it could have a camel-case name.
const paidFeatures = detectPaidFeatures(application); | ||
if (paidFeatures) { | ||
throw new Error( | ||
`You are using ${chalk.bgBlue(Object.keys(paidFeatures))} which ${Object.keys(paidFeatures).length > 1 ? 'are paid features' : 'is a paid feature'}. To continue using Toolpad, upgrade your plan or remove this feature.`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a big deal, but it might be worth it to use some object in the properties so that the object keys aren't necessarily the name of the feature we want to display.
)} | ||
</TabPanel> | ||
<TabPanel disableGutters value="roleMappings"> | ||
{isPaidPlan ? ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The role mappings tab only shows if at least one authentication provider that supports roles is selected. If we end up not letting users use even just authentication in any provider that supports roles, we wouldn't need the check in the role mappings tab. Anyway it's not very important probably, just mentioning it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense! I've added a disabling paid authentication types from the Authentication selection section, but I feel we can keep as a way to keep the knowledge that role mappings is a paid feature in the codebase.
<TextField {...params} label="Allowed roles" placeholder="Roles" /> | ||
)} | ||
/> | ||
{isPaidPlan ? ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would the upgrade message always appear to anyone who is using the free plan?
If so I guess it's better to just hide the controls here as this panel is always open?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed with the fact that it could be a little disruptive and annoying. To me its okay to advertise the fact that there is an upgrade possible as much as we can to enable feature discovery - so we can potentially keep it for now
) | ||
} | ||
> | ||
{`${feature ?? 'This feature'} is only available on paid plans.`} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh another nit, the error message right now says "Roles is only available on paid plans." instead of "Roles are". Also not sure if worth correcting though, just thought I'd mention it for completeness.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed! For now this is using singular nouns everywhere but we can enhance this to detect pluralization
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great Bharat, thanks for the changes!
const paidFeatures = [ | ||
hasRoles ? { id: 'roles', label: 'Role based access control' } : undefined, | ||
hasAzureActiveDirectory | ||
? { id: 'azure-ad', label: 'Azure Active Directory authentication' } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
? { id: 'azure-ad', label: 'Azure Active Directory authentication' } | |
? { id: 'azure-ad', label: 'Azure Active Directory authentication provider' } |
I would add the word provider
, maybe "Azure AD authentication provider" not to be too long.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe it's fine, whatever you prefer :D
@@ -177,6 +182,20 @@ export function AppAuthenticationEditor() { | |||
placeholder="example.com" | |||
/> | |||
))} | |||
{!isPaidPlan ? ( | |||
<UpgradeAlert |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this alert for authentication providers would look better just below the provider input (below the blue alert)? Anyway I'll approve it already, not a big deal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did try that, to me it made more sense at the end of the dialog (so that it would be non-obstructive)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that's fine then!