Skip to content

Commit

Permalink
fix(authenticator): fix user attribute parsing for amplify >= v6.0.6 (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
calebpollman authored Dec 19, 2023
1 parent 977b7c5 commit 190bf28
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 77 deletions.
5 changes: 5 additions & 0 deletions .changeset/swift-mirrors-cheat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@aws-amplify/ui": patch
---

fix(authenticator): fix user attribute parsing for amplify >= v6.0.6
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"@mdx-js/loader": "^2.1.0",
"@mdx-js/mdx": "^2.1.0",
"@mdx-js/react": "^2.1.0",
"aws-amplify": "^6.0.2",
"aws-amplify": "^6.0.6",
"countries-list": "^2.6.1",
"dotenv": "^16.0.0",
"gray-matter": "^4.0.3",
Expand Down
2 changes: 1 addition & 1 deletion examples/angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"@angular/platform-browser-dynamic": "^14.3.0",
"@angular/router": "^14.3.0",
"@aws-amplify/ui-angular": "^5.0.5",
"aws-amplify": "^6.0.2",
"aws-amplify": "^6.0.6",
"rxjs": "~6.6.0",
"tslib": "^2.0.0",
"zone.js": "~0.11.4"
Expand Down
2 changes: 1 addition & 1 deletion examples/next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"@aws-amplify/ui-react-notifications": "^2.0.6",
"@aws-amplify/ui-react-storage": "^3.0.7",
"@aws-sdk/credential-providers": "^3.370.0",
"aws-amplify": "^6.0.2",
"aws-amplify": "^6.0.6",
"next": "^13.5.5",
"next-global-css": "^1.1.1",
"react": "18.2.0",
Expand Down
2 changes: 1 addition & 1 deletion examples/react-native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"@react-native-async-storage/async-storage": "^1.17.5",
"@react-native-community/netinfo": "^8.3.0",
"@xstate/react": "^3.2.2",
"aws-amplify": "^6.0.2",
"aws-amplify": "^6.0.6",
"react": "18.2.0",
"react-native": "0.71.14",
"react-native-get-random-values": "^1.9.0",
Expand Down
2 changes: 1 addition & 1 deletion examples/vue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"dependencies": {
"@aws-amplify/ui-vue": "^4.0.5",
"aws-amplify": "^6.0.2",
"aws-amplify": "^6.0.6",
"vue": "^3.0.5",
"vue-router": "4"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Amplify } from 'aws-amplify';
import { Amplify, ResourcesConfig } from 'aws-amplify';

import { PasswordSettings } from '../../../types';
import { defaultServices } from '../defaultServices';
import { ALLOWED_SPECIAL_CHARACTERS } from '../../../helpers/authenticator/constants';

jest.mock('aws-amplify');
const getConfigSpy = jest.spyOn(Amplify, 'getConfig');

const {
getAmplifyConfig,
Expand Down Expand Up @@ -245,15 +245,81 @@ describe('validateConfirmPassword', () => {
});

describe('getAmplifyConfig', () => {
// @todo-migration
// think we need to mock result here:
// TypeError: Cannot read properties of undefined (reading 'Auth')
// > 21 | const cliConfig = result.Cognito;
it.skip('should call Amplify.configure', async () => {
it('should call Amplify.getConfig', async () => {
await getAmplifyConfig();

expect(Amplify.getConfig).toHaveBeenCalledTimes(1);
});

it('correctly handles invalid user attributes returned from Amplify.getConfig', async () => {
// previous to [email protected], `Amplify.getConfig` returns the wrong shape for `userAttributes`
const invalidConfig: ResourcesConfig = {
Auth: {
Cognito: {
identityPoolId: 'xxxxxx',
allowGuestAccess: true,
// @ts-expect-error
userAttributes: [{ email: { required: true } }],
userPoolClientId: 'xxxxxx',
userPoolId: 'xxxxxx',
mfa: { status: 'off', totpEnabled: false, smsEnabled: true },
passwordFormat: {
minLength: 8,
requireLowercase: false,
requireUppercase: false,
requireNumbers: false,
requireSpecialCharacters: false,
},
loginWith: { username: true, email: false, phone: false },
},
},
};

getConfigSpy.mockReturnValueOnce(invalidConfig);

const output = await getAmplifyConfig();

expect(output).toStrictEqual({
...invalidConfig.Auth.Cognito,
loginMechanisms: ['username'],
socialProviders: undefined,
signUpAttributes: ['email'],
});
});

it('correctly handles user attributes returned from Amplify.getConfig', async () => {
const validConfig: ResourcesConfig = {
Auth: {
Cognito: {
identityPoolId: 'xxxxxx',
allowGuestAccess: true,
userAttributes: { email: { required: true } },
userPoolClientId: 'xxxxxx',
userPoolId: 'xxxxxx',
mfa: { status: 'off', totpEnabled: false, smsEnabled: true },
passwordFormat: {
minLength: 8,
requireLowercase: false,
requireUppercase: false,
requireNumbers: false,
requireSpecialCharacters: false,
},
loginWith: { username: true, email: false, phone: false },
},
},
};

getConfigSpy.mockReturnValueOnce(validConfig);

const output = await getAmplifyConfig();

expect(output).toStrictEqual({
...validConfig.Auth.Cognito,
loginMechanisms: ['username'],
socialProviders: undefined,
signUpAttributes: ['email'],
});
});
});

describe('validateFormPassword', () => {
Expand Down
35 changes: 28 additions & 7 deletions packages/ui/src/machines/authenticator/defaultServices.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Amplify } from 'aws-amplify';
import { Amplify, ResourcesConfig } from 'aws-amplify';
import { UserAttributeKey } from 'aws-amplify/auth';

import {
confirmResetPassword,
Expand All @@ -16,14 +17,38 @@ import {
AuthTouchData,
LoginMechanism,
PasswordSettings,
SignUpAttribute,
SocialProvider,
ValidatorResult,
} from '../../types';

// Cognito does not allow a password length less then 8 characters
const DEFAULT_COGNITO_PASSWORD_MIN_LENGTH = 8;

type UserAttributes = ResourcesConfig['Auth']['Cognito']['userAttributes'];
type InvalidUserAttributes =
ResourcesConfig['Auth']['Cognito']['userAttributes'][];

const isInvalidUserAtributes = (
userAttributes: UserAttributes | InvalidUserAttributes
): userAttributes is InvalidUserAttributes => Array.isArray(userAttributes);

const parseUserAttributes = (
userAttributes: UserAttributes | InvalidUserAttributes
): UserAttributeKey[] => {
if (!userAttributes) {
return undefined;
}

// `aws-amplify` versions <= 6.0.5 return an array of `userAttributes` rather than an object
if (isInvalidUserAtributes(userAttributes)) {
return Object.entries(userAttributes).map(
([_, value]) => Object.keys(value)[0]
);
}

return Object.keys(userAttributes);
};

export const defaultServices = {
async getAmplifyConfig() {
const result = Amplify.getConfig();
Expand All @@ -42,11 +67,7 @@ export const defaultServices = {
}) as LoginMechanism[])
: undefined;

const parsedSignupAttributes = userAttributes
? (Object.entries(userAttributes).map(
([_key, value]) => Object.keys(value)[0]
) as SignUpAttribute[])
: undefined;
const parsedSignupAttributes = parseUserAttributes(userAttributes);

const parsedSocialProviders = loginWith?.oauth?.providers
? (loginWith.oauth.providers?.map((provider) =>
Expand Down
116 changes: 58 additions & 58 deletions yarn.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 190bf28

Please sign in to comment.