Skip to content

Commit

Permalink
feat(core): Expose User.authenticationMethod in GraphQL APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbromley committed Jun 24, 2020
1 parent 5504044 commit 96f923a
Show file tree
Hide file tree
Showing 16 changed files with 278 additions and 30 deletions.
19 changes: 14 additions & 5 deletions packages/admin-ui/src/lib/core/src/common/generated-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ export type AuthenticationInput = {
native?: Maybe<NativeAuthInput>;
};

export type AuthenticationMethod = Node & {
__typename?: 'AuthenticationMethod';
id: Scalars['ID'];
createdAt: Scalars['DateTime'];
updatedAt: Scalars['DateTime'];
strategy: Scalars['String'];
};

export type BooleanCustomFieldConfig = CustomField & {
__typename?: 'BooleanCustomFieldConfig';
name: Scalars['String'];
Expand Down Expand Up @@ -598,7 +606,7 @@ export type CreateZoneInput = {
/**
* @description
* ISO 4217 currency code
*
*
* @docsCategory common
*/
export enum CurrencyCode {
Expand Down Expand Up @@ -1393,7 +1401,7 @@ export type JobSortParameter = {
/**
* @description
* The state of a Job in the JobQueue
*
*
* @docsCategory common
*/
export enum JobState {
Expand All @@ -1411,7 +1419,7 @@ export enum JobState {
* region or script modifier (e.g. de_AT). The selection available is based
* on the [Unicode CLDR summary list](https://unicode-org.github.io/cldr-staging/charts/37/summary/root.html)
* and includes the major spoken languages of the world and any widely-used variants.
*
*
* @docsCategory common
*/
export enum LanguageCode {
Expand Down Expand Up @@ -2605,7 +2613,7 @@ export type PaymentMethodSortParameter = {
* @description
* Permissions for administrators and customers. Used to control access to
* GraphQL resolvers via the {@link Allow} decorator.
*
*
* @docsCategory common
*/
export enum Permission {
Expand Down Expand Up @@ -3775,7 +3783,8 @@ export type User = Node & {
identifier: Scalars['String'];
verified: Scalars['Boolean'];
roles: Array<Role>;
lastLogin?: Maybe<Scalars['String']>;
lastLogin?: Maybe<Scalars['DateTime']>;
authenticationMethods: Array<AuthenticationMethod>;
customFields?: Maybe<Scalars['JSON']>;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ const result: IntrospectionResultData = {
{
name: 'Role',
},
{
name: 'AuthenticationMethod',
},
{
name: 'Asset',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ export type AuthenticationInput = {
native?: Maybe<NativeAuthInput>;
};

export type AuthenticationMethod = Node & {
__typename?: 'AuthenticationMethod';
id: Scalars['ID'];
createdAt: Scalars['DateTime'];
updatedAt: Scalars['DateTime'];
strategy: Scalars['String'];
};

export type BooleanCustomFieldConfig = CustomField & {
__typename?: 'BooleanCustomFieldConfig';
name: Scalars['String'];
Expand Down Expand Up @@ -3605,7 +3613,8 @@ export type User = Node & {
identifier: Scalars['String'];
verified: Scalars['Boolean'];
roles: Array<Role>;
lastLogin?: Maybe<Scalars['String']>;
lastLogin?: Maybe<Scalars['DateTime']>;
authenticationMethods: Array<AuthenticationMethod>;
customFields?: Maybe<Scalars['JSON']>;
};

Expand Down
16 changes: 15 additions & 1 deletion packages/common/src/generated-shop-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,15 @@ export enum AssetType {

export type AuthenticationInput = {
native?: Maybe<NativeAuthInput>;
google?: Maybe<GoogleAuthInput>;
};

export type AuthenticationMethod = Node & {
__typename?: 'AuthenticationMethod';
id: Scalars['ID'];
createdAt: Scalars['DateTime'];
updatedAt: Scalars['DateTime'];
strategy: Scalars['String'];
};

export type BooleanCustomFieldConfig = CustomField & {
Expand Down Expand Up @@ -887,6 +896,10 @@ export type GlobalSettings = {
customFields?: Maybe<Scalars['JSON']>;
};

export type GoogleAuthInput = {
token: Scalars['String'];
};

export type HistoryEntry = Node & {
__typename?: 'HistoryEntry';
id: Scalars['ID'];
Expand Down Expand Up @@ -2267,7 +2280,8 @@ export type User = Node & {
identifier: Scalars['String'];
verified: Scalars['Boolean'];
roles: Array<Role>;
lastLogin?: Maybe<Scalars['String']>;
lastLogin?: Maybe<Scalars['DateTime']>;
authenticationMethods: Array<AuthenticationMethod>;
customFields?: Maybe<Scalars['JSON']>;
};

Expand Down
19 changes: 14 additions & 5 deletions packages/common/src/generated-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ export type AuthenticationInput = {
native?: Maybe<NativeAuthInput>;
};

export type AuthenticationMethod = Node & {
__typename?: 'AuthenticationMethod';
id: Scalars['ID'];
createdAt: Scalars['DateTime'];
updatedAt: Scalars['DateTime'];
strategy: Scalars['String'];
};

export type BooleanCustomFieldConfig = CustomField & {
__typename?: 'BooleanCustomFieldConfig';
name: Scalars['String'];
Expand Down Expand Up @@ -597,7 +605,7 @@ export type CreateZoneInput = {
/**
* @description
* ISO 4217 currency code
*
*
* @docsCategory common
*/
export enum CurrencyCode {
Expand Down Expand Up @@ -1385,7 +1393,7 @@ export type JobSortParameter = {
/**
* @description
* The state of a Job in the JobQueue
*
*
* @docsCategory common
*/
export enum JobState {
Expand All @@ -1403,7 +1411,7 @@ export enum JobState {
* region or script modifier (e.g. de_AT). The selection available is based
* on the [Unicode CLDR summary list](https://unicode-org.github.io/cldr-staging/charts/37/summary/root.html)
* and includes the major spoken languages of the world and any widely-used variants.
*
*
* @docsCategory common
*/
export enum LanguageCode {
Expand Down Expand Up @@ -2565,7 +2573,7 @@ export type PaymentMethodSortParameter = {
* @description
* Permissions for administrators and customers. Used to control access to
* GraphQL resolvers via the {@link Allow} decorator.
*
*
* @docsCategory common
*/
export enum Permission {
Expand Down Expand Up @@ -3727,7 +3735,8 @@ export type User = Node & {
identifier: Scalars['String'];
verified: Scalars['Boolean'];
roles: Array<Role>;
lastLogin?: Maybe<Scalars['String']>;
lastLogin?: Maybe<Scalars['DateTime']>;
authenticationMethods: Array<AuthenticationMethod>;
customFields?: Maybe<Scalars['JSON']>;
};

Expand Down
78 changes: 77 additions & 1 deletion packages/core/e2e/authentication-strategy.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,30 @@ import path from 'path';

import { initialData } from '../../../e2e-common/e2e-initial-data';
import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
import { NativeAuthenticationStrategy } from '../src/config/auth/native-authentication-strategy';

import { TestAuthenticationStrategy, VALID_AUTH_TOKEN } from './fixtures/test-authentication-strategies';
import {
Authenticate,
GetCustomerHistory,
GetCustomers,
GetCustomerUserAuth,
HistoryEntryType,
Me,
} from './graphql/generated-e2e-admin-types';
import { Register } from './graphql/generated-e2e-shop-types';
import { GET_CUSTOMER_HISTORY, ME } from './graphql/shared-definitions';
import { REGISTER_ACCOUNT } from './graphql/shop-definitions';
import { assertThrowsWithMessage } from './utils/assert-throws-with-message';

describe('AuthenticationStrategy', () => {
const { server, adminClient, shopClient } = createTestEnvironment(
mergeConfig(testConfig, {
authOptions: {
shopAuthenticationStrategy: [new TestAuthenticationStrategy()],
shopAuthenticationStrategy: [
new NativeAuthenticationStrategy(),
new TestAuthenticationStrategy(),
],
},
}),
);
Expand Down Expand Up @@ -108,6 +115,18 @@ describe('AuthenticationStrategy', () => {
]);
});

it('user authenticationMethod populated', async () => {
const { customer } = await adminClient.query<
GetCustomerUserAuth.Query,
GetCustomerUserAuth.Variables
>(GET_CUSTOMER_USER_AUTH, {
id: newCustomerId,
});

expect(customer?.user?.authenticationMethods.length).toBe(1);
expect(customer?.user?.authenticationMethods[0].strategy).toBe('test_strategy');
});

it('creates authenticated session', async () => {
const { me } = await shopClient.query<Me.Query>(ME);

Expand Down Expand Up @@ -136,6 +155,47 @@ describe('AuthenticationStrategy', () => {
userData.email,
]);
});

it('registerCustomerAccount with external email', async () => {
const { registerCustomerAccount } = await shopClient.query<Register.Mutation, Register.Variables>(
REGISTER_ACCOUNT,
{
input: {
emailAddress: userData.email,
},
},
);

expect(registerCustomerAccount).toBe(true);
const { customer } = await adminClient.query<
GetCustomerUserAuth.Query,
GetCustomerUserAuth.Variables
>(GET_CUSTOMER_USER_AUTH, {
id: newCustomerId,
});

expect(customer?.user?.authenticationMethods.length).toBe(2);
expect(customer?.user?.authenticationMethods[1].strategy).toBe('native');

const { customer: customer2 } = await adminClient.query<
GetCustomerHistory.Query,
GetCustomerHistory.Variables
>(GET_CUSTOMER_HISTORY, {
id: newCustomerId,
options: {
skip: 2,
},
});

expect(customer2?.history.items.map(pick(['type', 'data']))).toEqual([
{
type: HistoryEntryType.CUSTOMER_REGISTERED,
data: {
strategy: 'native',
},
},
]);
});
});
});

Expand All @@ -161,3 +221,19 @@ const GET_CUSTOMERS = gql`
}
}
`;

const GET_CUSTOMER_USER_AUTH = gql`
query GetCustomerUserAuth($id: ID!) {
customer(id: $id) {
id
user {
id
verified
authenticationMethods {
id
strategy
}
}
}
}
`;
42 changes: 41 additions & 1 deletion packages/core/e2e/graphql/generated-e2e-admin-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ export type AuthenticationInput = {
native?: Maybe<NativeAuthInput>;
};

export type AuthenticationMethod = Node & {
__typename?: 'AuthenticationMethod';
id: Scalars['ID'];
createdAt: Scalars['DateTime'];
updatedAt: Scalars['DateTime'];
strategy: Scalars['String'];
};

export type BooleanCustomFieldConfig = CustomField & {
__typename?: 'BooleanCustomFieldConfig';
name: Scalars['String'];
Expand Down Expand Up @@ -3605,7 +3613,8 @@ export type User = Node & {
identifier: Scalars['String'];
verified: Scalars['Boolean'];
roles: Array<Role>;
lastLogin?: Maybe<Scalars['String']>;
lastLogin?: Maybe<Scalars['DateTime']>;
authenticationMethods: Array<AuthenticationMethod>;
customFields?: Maybe<Scalars['JSON']>;
};

Expand Down Expand Up @@ -3708,6 +3717,27 @@ export type GetCustomersQuery = { __typename?: 'Query' } & {
};
};

export type GetCustomerUserAuthQueryVariables = {
id: Scalars['ID'];
};

export type GetCustomerUserAuthQuery = { __typename?: 'Query' } & {
customer?: Maybe<
{ __typename?: 'Customer' } & Pick<Customer, 'id'> & {
user?: Maybe<
{ __typename?: 'User' } & Pick<User, 'id' | 'verified'> & {
authenticationMethods: Array<
{ __typename?: 'AuthenticationMethod' } & Pick<
AuthenticationMethod,
'id' | 'strategy'
>
>;
}
>;
}
>;
};

export type GetChannelsQueryVariables = {};

export type GetChannelsQuery = { __typename?: 'Query' } & {
Expand Down Expand Up @@ -5786,6 +5816,16 @@ export namespace GetCustomers {
export type Items = NonNullable<GetCustomersQuery['customers']['items'][0]>;
}

export namespace GetCustomerUserAuth {
export type Variables = GetCustomerUserAuthQueryVariables;
export type Query = GetCustomerUserAuthQuery;
export type Customer = NonNullable<GetCustomerUserAuthQuery['customer']>;
export type User = NonNullable<NonNullable<GetCustomerUserAuthQuery['customer']>['user']>;
export type AuthenticationMethods = NonNullable<
NonNullable<NonNullable<GetCustomerUserAuthQuery['customer']>['user']>['authenticationMethods'][0]
>;
}

export namespace GetChannels {
export type Variables = GetChannelsQueryVariables;
export type Query = GetChannelsQuery;
Expand Down
Loading

0 comments on commit 96f923a

Please sign in to comment.