auth.e2e-spec.ts 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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 { dataDir, TEST_SETUP_TIMEOUT_MS, testConfig } from './config/test-config';
  8. import { initialData } from './fixtures/e2e-initial-data';
  9. import { CURRENT_USER_FRAGMENT } from './graphql/fragments';
  10. import {
  11. CreateAdministrator,
  12. CreateRole,
  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_PRODUCT_LIST,
  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. const token = await server.init({
  32. dataDir,
  33. initialData,
  34. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
  35. customerCount: 1,
  36. });
  37. await adminClient.init();
  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('ReadCatalog permission', () => {
  63. beforeAll(async () => {
  64. await adminClient.asSuperAdmin();
  65. const { identifier, password } = await createAdministratorWithPermissions('ReadCatalog', [
  66. Permission.ReadCatalog,
  67. ]);
  68. await adminClient.asUserWithCredentials(identifier, password);
  69. });
  70. it('me returns correct permissions', async () => {
  71. const { me } = await adminClient.query<Me.Query>(ME);
  72. expect(me!.channels[0].permissions).toEqual([
  73. Permission.Authenticated,
  74. Permission.ReadCatalog,
  75. ]);
  76. });
  77. it('can read', async () => {
  78. await assertRequestAllowed(GET_PRODUCT_LIST);
  79. });
  80. it('cannot uppdate', async () => {
  81. await assertRequestForbidden<MutationUpdateProductArgs>(UPDATE_PRODUCT, {
  82. input: {
  83. id: '1',
  84. translations: [],
  85. },
  86. });
  87. });
  88. it('cannot create', async () => {
  89. await assertRequestForbidden<MutationCreateProductArgs>(CREATE_PRODUCT, {
  90. input: {
  91. translations: [],
  92. },
  93. });
  94. });
  95. });
  96. describe('CRUD on Customers permissions', () => {
  97. beforeAll(async () => {
  98. await adminClient.asSuperAdmin();
  99. const { identifier, password } = await createAdministratorWithPermissions('CRUDCustomer', [
  100. Permission.CreateCustomer,
  101. Permission.ReadCustomer,
  102. Permission.UpdateCustomer,
  103. Permission.DeleteCustomer,
  104. ]);
  105. await adminClient.asUserWithCredentials(identifier, password);
  106. });
  107. it('me returns correct permissions', async () => {
  108. const { me } = await adminClient.query<Me.Query>(ME);
  109. expect(me!.channels[0].permissions).toEqual([
  110. Permission.Authenticated,
  111. Permission.CreateCustomer,
  112. Permission.ReadCustomer,
  113. Permission.UpdateCustomer,
  114. Permission.DeleteCustomer,
  115. ]);
  116. });
  117. it('can create', async () => {
  118. await assertRequestAllowed(
  119. gql`
  120. mutation CanCreateCustomer($input: CreateCustomerInput!) {
  121. createCustomer(input: $input) {
  122. id
  123. }
  124. }
  125. `,
  126. { input: { emailAddress: '', firstName: '', lastName: '' } },
  127. );
  128. });
  129. it('can read', async () => {
  130. await assertRequestAllowed(gql`
  131. query GetCustomerCount {
  132. customers {
  133. totalItems
  134. }
  135. }
  136. `);
  137. });
  138. });
  139. });
  140. async function assertRequestAllowed<V>(operation: DocumentNode, variables?: V) {
  141. try {
  142. const status = await adminClient.queryStatus(operation, variables);
  143. expect(status).toBe(200);
  144. } catch (e) {
  145. const errorCode = getErrorCode(e);
  146. if (!errorCode) {
  147. fail(`Unexpected failure: ${e}`);
  148. } else {
  149. fail(`Operation should be allowed, got status ${getErrorCode(e)}`);
  150. }
  151. }
  152. }
  153. async function assertRequestForbidden<V>(operation: DocumentNode, variables: V) {
  154. try {
  155. const status = await adminClient.query(operation, variables);
  156. fail(`Should have thrown`);
  157. } catch (e) {
  158. expect(getErrorCode(e)).toBe('FORBIDDEN');
  159. }
  160. }
  161. function getErrorCode(err: any): string {
  162. return err.response.errors[0].extensions.code;
  163. }
  164. async function createAdministratorWithPermissions(
  165. code: string,
  166. permissions: Permission[],
  167. ): Promise<{ identifier: string; password: string }> {
  168. const roleResult = await adminClient.query<CreateRole.Mutation, CreateRole.Variables>(CREATE_ROLE, {
  169. input: {
  170. code,
  171. description: '',
  172. permissions,
  173. },
  174. });
  175. const role = roleResult.createRole;
  176. const identifier = `${code}@${Math.random()
  177. .toString(16)
  178. .substr(2, 8)}`;
  179. const password = `test`;
  180. const adminResult = await adminClient.query<
  181. CreateAdministrator.Mutation,
  182. CreateAdministrator.Variables
  183. >(CREATE_ADMINISTRATOR, {
  184. input: {
  185. emailAddress: identifier,
  186. firstName: code,
  187. lastName: 'Admin',
  188. password,
  189. roleIds: [role.id],
  190. },
  191. });
  192. const admin = adminResult.createAdministrator;
  193. return {
  194. identifier,
  195. password,
  196. };
  197. }
  198. });
  199. export const ME = gql`
  200. query Me {
  201. me {
  202. ...CurrentUser
  203. }
  204. }
  205. ${CURRENT_USER_FRAGMENT}
  206. `;