auth.e2e-spec.ts 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /* tslint:disable:no-non-null-assertion */
  2. import { SUPER_ADMIN_USER_IDENTIFIER, SUPER_ADMIN_USER_PASSWORD } from '@vendure/common/lib/shared-constants';
  3. import { createTestEnvironment } from '@vendure/testing';
  4. import { DocumentNode } from 'graphql';
  5. import gql from 'graphql-tag';
  6. import path from 'path';
  7. import { initialData } from '../../../e2e-common/e2e-initial-data';
  8. import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
  9. import {
  10. CreateAdministrator,
  11. CreateRole,
  12. ErrorCode,
  13. GetCustomerList,
  14. Me,
  15. MutationCreateProductArgs,
  16. MutationLoginArgs,
  17. MutationUpdateProductArgs,
  18. Permission,
  19. } from './graphql/generated-e2e-admin-types';
  20. import {
  21. ATTEMPT_LOGIN,
  22. CREATE_ADMINISTRATOR,
  23. CREATE_PRODUCT,
  24. CREATE_ROLE,
  25. GET_CUSTOMER_LIST,
  26. GET_PRODUCT_LIST,
  27. ME,
  28. UPDATE_PRODUCT,
  29. } from './graphql/shared-definitions';
  30. import { assertThrowsWithMessage } from './utils/assert-throws-with-message';
  31. describe('Authorization & permissions', () => {
  32. const { server, adminClient } = createTestEnvironment(testConfig);
  33. beforeAll(async () => {
  34. await server.init({
  35. initialData,
  36. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
  37. customerCount: 1,
  38. });
  39. await adminClient.asSuperAdmin();
  40. }, TEST_SETUP_TIMEOUT_MS);
  41. afterAll(async () => {
  42. await server.destroy();
  43. });
  44. describe('admin permissions', () => {
  45. describe('Anonymous user', () => {
  46. beforeAll(async () => {
  47. await adminClient.asAnonymousUser();
  48. });
  49. it(
  50. 'me is not permitted',
  51. assertThrowsWithMessage(async () => {
  52. await adminClient.query<Me.Query>(ME);
  53. }, 'You are not currently authorized to perform this action'),
  54. );
  55. it('can attempt login', async () => {
  56. await assertRequestAllowed<MutationLoginArgs>(ATTEMPT_LOGIN, {
  57. username: SUPER_ADMIN_USER_IDENTIFIER,
  58. password: SUPER_ADMIN_USER_PASSWORD,
  59. rememberMe: false,
  60. });
  61. });
  62. });
  63. describe('Customer user', () => {
  64. let customerEmailAddress: string;
  65. beforeAll(async () => {
  66. await adminClient.asSuperAdmin();
  67. const { customers } = await adminClient.query<GetCustomerList.Query>(GET_CUSTOMER_LIST);
  68. customerEmailAddress = customers.items[0].emailAddress;
  69. });
  70. it('cannot login', async () => {
  71. const result = await adminClient.asUserWithCredentials(customerEmailAddress, 'test');
  72. expect(result.errorCode).toBe(ErrorCode.INVALID_CREDENTIALS_ERROR);
  73. });
  74. });
  75. describe('ReadCatalog permission', () => {
  76. beforeAll(async () => {
  77. await adminClient.asSuperAdmin();
  78. const { identifier, password } = await createAdministratorWithPermissions('ReadCatalog', [
  79. Permission.ReadCatalog,
  80. ]);
  81. await adminClient.asUserWithCredentials(identifier, password);
  82. });
  83. it('me returns correct permissions', async () => {
  84. const { me } = await adminClient.query<Me.Query>(ME);
  85. expect(me!.channels[0].permissions).toEqual([
  86. Permission.Authenticated,
  87. Permission.ReadCatalog,
  88. ]);
  89. });
  90. it('can read', async () => {
  91. await assertRequestAllowed(GET_PRODUCT_LIST);
  92. });
  93. it('cannot uppdate', async () => {
  94. await assertRequestForbidden<MutationUpdateProductArgs>(UPDATE_PRODUCT, {
  95. input: {
  96. id: '1',
  97. translations: [],
  98. },
  99. });
  100. });
  101. it('cannot create', async () => {
  102. await assertRequestForbidden<MutationCreateProductArgs>(CREATE_PRODUCT, {
  103. input: {
  104. translations: [],
  105. },
  106. });
  107. });
  108. });
  109. describe('CRUD on Customers permissions', () => {
  110. beforeAll(async () => {
  111. await adminClient.asSuperAdmin();
  112. const { identifier, password } = await createAdministratorWithPermissions('CRUDCustomer', [
  113. Permission.CreateCustomer,
  114. Permission.ReadCustomer,
  115. Permission.UpdateCustomer,
  116. Permission.DeleteCustomer,
  117. ]);
  118. await adminClient.asUserWithCredentials(identifier, password);
  119. });
  120. it('me returns correct permissions', async () => {
  121. const { me } = await adminClient.query<Me.Query>(ME);
  122. expect(me!.channels[0].permissions).toEqual([
  123. Permission.Authenticated,
  124. Permission.CreateCustomer,
  125. Permission.ReadCustomer,
  126. Permission.UpdateCustomer,
  127. Permission.DeleteCustomer,
  128. ]);
  129. });
  130. it('can create', async () => {
  131. await assertRequestAllowed(
  132. gql`
  133. mutation CanCreateCustomer($input: CreateCustomerInput!) {
  134. createCustomer(input: $input) {
  135. ... on Customer {
  136. id
  137. }
  138. }
  139. }
  140. `,
  141. { input: { emailAddress: '', firstName: '', lastName: '' } },
  142. );
  143. });
  144. it('can read', async () => {
  145. await assertRequestAllowed(gql`
  146. query GetCustomerCount {
  147. customers {
  148. totalItems
  149. }
  150. }
  151. `);
  152. });
  153. });
  154. });
  155. async function assertRequestAllowed<V>(operation: DocumentNode, variables?: V) {
  156. try {
  157. const status = await adminClient.queryStatus(operation, variables);
  158. expect(status).toBe(200);
  159. } catch (e) {
  160. const errorCode = getErrorCode(e);
  161. if (!errorCode) {
  162. fail(`Unexpected failure: ${e}`);
  163. } else {
  164. fail(`Operation should be allowed, got status ${getErrorCode(e)}`);
  165. }
  166. }
  167. }
  168. async function assertRequestForbidden<V>(operation: DocumentNode, variables: V) {
  169. try {
  170. const status = await adminClient.query(operation, variables);
  171. fail(`Should have thrown`);
  172. } catch (e) {
  173. expect(getErrorCode(e)).toBe('FORBIDDEN');
  174. }
  175. }
  176. function getErrorCode(err: any): string {
  177. return err.response.errors[0].extensions.code;
  178. }
  179. async function createAdministratorWithPermissions(
  180. code: string,
  181. permissions: Permission[],
  182. ): Promise<{ identifier: string; password: string }> {
  183. const roleResult = await adminClient.query<CreateRole.Mutation, CreateRole.Variables>(CREATE_ROLE, {
  184. input: {
  185. code,
  186. description: '',
  187. permissions,
  188. },
  189. });
  190. const role = roleResult.createRole;
  191. const identifier = `${code}@${Math.random().toString(16).substr(2, 8)}`;
  192. const password = `test`;
  193. const adminResult = await adminClient.query<
  194. CreateAdministrator.Mutation,
  195. CreateAdministrator.Variables
  196. >(CREATE_ADMINISTRATOR, {
  197. input: {
  198. emailAddress: identifier,
  199. firstName: code,
  200. lastName: 'Admin',
  201. password,
  202. roleIds: [role.id],
  203. },
  204. });
  205. const admin = adminResult.createAdministrator;
  206. return {
  207. identifier,
  208. password,
  209. };
  210. }
  211. });