auth.e2e-spec.ts 7.4 KB

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