auth.e2e-spec.ts 7.4 KB

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