Skip to content
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

Upgrading node-auth0 from v3 to v4 #887

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Draft

Conversation

willvedd
Copy link
Contributor

@willvedd willvedd commented Feb 2, 2024

🔧 Changes

Upgrading node-auth0 from v3 to v4. This is a necessary upgrade because all new Auth0 features and dependency patches are getting released on v4 now.

This was originally attempted in #852 but had a few tricky changes that need to be reviewed. This should not require a major version bump for Deploy CLI despite the breaking changes in v4. There will however be a few awkward situations that will need to be smoothed-over.

📚 References

🔬 Testing

📝 Checklist

  • All new/changed/fixed functionality is covered by tests (or N/A)
  • I have added documentation for all new/changed functionality (or N/A)

const allResourceServers = await context.mgmtClient.resourceServers.getAll({
paginate: true,
// TODO: Bring back paginate: true
const { data: { resource_servers: allResourceServers } } = await context.mgmtClient.resourceServers.getAll({
Copy link
Contributor Author

@willvedd willvedd Feb 7, 2024

Choose a reason for hiding this comment

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

Yes, this is important to include. Before Node v4, Auth0 Node SDK didn't natively support pagination and I don't believe that v4 added it either but this needs to be confirmed. The getAll function is mutated by the Deploy CLI to support the paginate property.

Update: Yes, we need to bring this back and account for the pagination monkey-patch. Perhaps we should extract as a function instead?

audience: config.AUTH0_AUDIENCE
? config.AUTH0_AUDIENCE
: `https://${config.AUTH0_DOMAIN}/api/v2/`,
});
return clientCredentials.access_token;
return clientCredentials.data?.access_token;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should introduce some checks to prevent an undefined access_token from being persisted through the rest of the process.

@@ -167,7 +167,7 @@ export default function pagedClient(client: BaseAuth0APIClient): Auth0APIClient
frequencyLimit: API_FREQUENCY_PER_SECOND,
frequencyWindow: 1000, // 1 sec
}),
};
} as unknown as Auth0APIClient;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks very weird. Can the unknown be removed or this type cast otherwise cleaned up?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Update: Looking at this with Frederik again, we should probably find a way to exclude the pool property or facilitate pagination some other way that can retain the Auth0APIClient type.

Comment on lines +114 to +116
// TODO: Should we keep this?
delete (addAction as any).deployed;
delete (addAction as any).status;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes because when you create an action you cannot specify the deploy or status in the payload. However, this should be accomplished with the stripCreateFields: ['deployed', 'status'], in the handler definition above.

Comment on lines +121 to +122
// TODO: Should we keep this?
(action as any).id = createdAction.id;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Probably keep this so we can have reference of the ID. Should double check through testing though.

@@ -202,7 +208,9 @@ export default class ActionHandler extends DefaultAPIHandler {
// Actions API does not support include_totals param like the other paginate API's.
// So we set it to false otherwise it will fail with "Additional properties not allowed: include_totals"
try {
const actions = await this.client.actions.getAll({ paginate: true });
// TODO: bring back paginate: true
const { data } = await this.client.actions.getAll();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggested change
const { data } = await this.client.actions.getAll();
const { data: {actions} } = await this.client.actions.getAll();

if (Object.keys(emailProvider).length === 0) {
if (this.config('AUTH0_ALLOW_DELETE') === true) {
await this.client.emailProvider.delete();
// await this.client.emails.delete();
Copy link
Contributor Author

@willvedd willvedd Feb 7, 2024

Choose a reason for hiding this comment

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

This could technically be a breaking change but it also seems like this never worked to begin with. We may be able to replicate a delete-like functionality to the best of our ability.

This function was removed because the endpoint wasn't officially supported, so it wasn't included in the SDK. We still might be able to smooth this over by removing email provider configurations.

this.updated += 1;
this.didUpdate(updated);
} else {
const provider = { name: emailProvider.name, enabled: emailProvider.enabled };
const created = await this.client.emailProvider.configure(provider, emailProvider);
const created = await this.client.emails.configure(emailProvider as PostProviderRequest);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can this type be applied to the construction of the emailProvider value above rather than smoothing-over as a type cast?

Comment on lines +56 to +57
// TODO: Should we revisit this?
delete (updated as any ).body;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@frederikprijck What is there to revisit?

Comment on lines +64 to +65
// TODO: Should we revisit this?
delete (created as any).body;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Similarly, @frederikprijck what is there to revisit?

Comment on lines +44 to +53
// TODO: This is quite a change, needs to be validated for sure.
if (m.name === 'phone' && m.provider === 'twilio') {
provider = await this.client.guardian.getPhoneFactorProviderTwilio();
} else if (m.name === 'sms' && m.provider === 'twilio') {
provider = await this.client.guardian.getSmsFactorProviderTwilio();
} else if (m.name === 'push-notification' && m.provider === 'apns') {
provider = await this.client.guardian.getPushNotificationProviderAPNS();
} else if (m.name === 'push-notification' && m.provider === 'sns') {
provider = await this.client.guardian.getPushNotificationProviderSNS();
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Verify if there are any other providers

getTriggerBindings: () => Promise<Asset>;
};
}; // TODO: replace with a more accurate representation of the Auth0APIClient type
export type BaseAuth0APIClient = ManagementClient;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should remove the BaseAuth0APIClient type altogether.

@@ -16,7 +17,8 @@ export default class EmailProviderHandler extends DefaultHandler {

async getType(): Promise<Asset> {
try {
return await this.client.emailProvider.get({ include_fields: true, fields: defaultFields });
const { data } = await this.client.emails.get({ include_fields: true, fields: defaultFields.join(',') });
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This looks like a breaking change but the SDK types fields as a string so this doesn't precludes the need to type cast.

@@ -20,7 +20,6 @@ import * as guardianPhoneFactorMessageTypes from './guardianPhoneFactorMessageTy
import * as roles from './roles';
import * as branding from './branding';
import * as prompts from './prompts';
import * as migrations from './migrations';
Copy link
Contributor Author

@willvedd willvedd Feb 9, 2024

Choose a reason for hiding this comment

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

Migrations not part of the public spec. Need to understand if this was an intentional deprecation or if it is even necessary.

Removing this would be a breaking change so we should consider adding-in back in unless we create a new major for Deploy CLI.

import log from '../../../logger';

export const schema = {
type: 'object',
};

export type Tenant = Asset & { enabled_locales?: Language[]; flags: { [key: string]: boolean } };
export type Tenant = TenantSettings;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would rather we just get rid of the Tenant type altogether in favor of the TenantSettings.

@@ -2,7 +2,7 @@
{
"scope": "https://deploy-cli-dev.eu.auth0.com:443",
"method": "GET",
"path": "/api/v2/rules?include_totals=true&page=0&per_page=100",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These recordings should probably be reverted once the pagination functionality is added back in.

import fetch from 'node-fetch';

// Use node.http for recording library
global.fetch = fetch;

const shouldUseRecordings = process.env['AUTH0_HTTP_RECORDINGS'] === 'lockdown';
const AUTH0_DOMAIN = shouldUseRecordings
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Basically everthing below this line is an innocuous testing change 🙌

Copy link
Contributor Author

@willvedd willvedd left a comment

Choose a reason for hiding this comment

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

Outstanding items with this PR:

  • DELETE email provider SDK function – Review the impact of this. Can this be smoothed-over? Should this be re-added to the SDK?
  • Migrations removal – Review the impact of this. Do we actually need or want migrations? However, it is a large enough breaking change where if this was removed from the Deploy CLI, you would need to create a new major version
  • Pagination – Bring back and probably favor a method of implementation that doesn't monkey-patch the SDK. Also look into relocating the pool construct.
  • Types – Node SDK v4 introduces comprehensive types, which should take precedence over the types defined in this repo. Lots of weird type casting going on, should review and used canonical types from SDK wherever possible.
  • Node Compatibility – The Node SDK v4 drops support for v16 w/ introduction of fetch. We've dropped node version support in the past without much noise but need to review the usage decide the gravity if this change and if it warrants a new major release or not.

There are some other minor things to review in this PR but otherwise the above are the major chunks of work. IMO, we should attempt to not introduce a new major to facilitate this new SDK because there are many improvements that can be made with a new major that should be provided to developers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants