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