role.e2e-spec.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. import { omit } from '@vendure/common/lib/omit';
  2. import {
  3. CUSTOMER_ROLE_CODE,
  4. DEFAULT_CHANNEL_CODE,
  5. SUPER_ADMIN_ROLE_CODE,
  6. } from '@vendure/common/lib/shared-constants';
  7. import { createTestEnvironment } from '@vendure/testing';
  8. import gql from 'graphql-tag';
  9. import path from 'path';
  10. import { initialData } from '../../../e2e-common/e2e-initial-data';
  11. import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
  12. import { ROLE_FRAGMENT } from './graphql/fragments';
  13. import {
  14. ChannelFragment,
  15. CreateChannel,
  16. CreateRole,
  17. CurrencyCode,
  18. DeleteRole,
  19. DeletionResult,
  20. GetRole,
  21. GetRoles,
  22. LanguageCode,
  23. Permission,
  24. Role,
  25. UpdateRole,
  26. } from './graphql/generated-e2e-admin-types';
  27. import { CREATE_CHANNEL, CREATE_ROLE, UPDATE_ROLE } from './graphql/shared-definitions';
  28. import { assertThrowsWithMessage } from './utils/assert-throws-with-message';
  29. import { sortById } from './utils/test-order-utils';
  30. describe('Role resolver', () => {
  31. const { server, adminClient } = createTestEnvironment(testConfig());
  32. let createdRole: Role.Fragment;
  33. let defaultRoles: Role.Fragment[];
  34. beforeAll(async () => {
  35. await server.init({
  36. initialData,
  37. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
  38. customerCount: 1,
  39. });
  40. await adminClient.asSuperAdmin();
  41. }, TEST_SETUP_TIMEOUT_MS);
  42. afterAll(async () => {
  43. await server.destroy();
  44. });
  45. it('roles', async () => {
  46. const result = await adminClient.query<GetRoles.Query, GetRoles.Variables>(GET_ROLES);
  47. defaultRoles = result.roles.items;
  48. expect(result.roles.items.length).toBe(2);
  49. expect(result.roles.totalItems).toBe(2);
  50. });
  51. it('createRole with invalid permission', async () => {
  52. try {
  53. await adminClient.query<CreateRole.Mutation, CreateRole.Variables>(CREATE_ROLE, {
  54. input: {
  55. code: 'test',
  56. description: 'test role',
  57. permissions: ['ReadCatalogx' as any],
  58. },
  59. });
  60. fail('Should have thrown');
  61. } catch (e) {
  62. expect(e.response.errors[0]?.extensions.code).toBe('BAD_USER_INPUT');
  63. }
  64. });
  65. it('createRole with no permissions includes Authenticated', async () => {
  66. const { createRole } = await adminClient.query<CreateRole.Mutation, CreateRole.Variables>(
  67. CREATE_ROLE,
  68. {
  69. input: {
  70. code: 'test',
  71. description: 'test role',
  72. permissions: [],
  73. },
  74. },
  75. );
  76. expect(omit(createRole, ['channels'])).toEqual({
  77. code: 'test',
  78. description: 'test role',
  79. id: 'T_3',
  80. permissions: [Permission.Authenticated],
  81. });
  82. });
  83. it('createRole deduplicates permissions', async () => {
  84. const { createRole } = await adminClient.query<CreateRole.Mutation, CreateRole.Variables>(
  85. CREATE_ROLE,
  86. {
  87. input: {
  88. code: 'test2',
  89. description: 'test role2',
  90. permissions: [Permission.ReadSettings, Permission.ReadSettings],
  91. },
  92. },
  93. );
  94. expect(omit(createRole, ['channels'])).toEqual({
  95. code: 'test2',
  96. description: 'test role2',
  97. id: 'T_4',
  98. permissions: [Permission.Authenticated, Permission.ReadSettings],
  99. });
  100. });
  101. it('createRole with permissions', async () => {
  102. const result = await adminClient.query<CreateRole.Mutation, CreateRole.Variables>(CREATE_ROLE, {
  103. input: {
  104. code: 'test',
  105. description: 'test role',
  106. permissions: [Permission.ReadCustomer, Permission.UpdateCustomer],
  107. },
  108. });
  109. createdRole = result.createRole;
  110. expect(createdRole).toEqual({
  111. code: 'test',
  112. description: 'test role',
  113. id: 'T_5',
  114. permissions: [Permission.Authenticated, Permission.ReadCustomer, Permission.UpdateCustomer],
  115. channels: [
  116. {
  117. code: DEFAULT_CHANNEL_CODE,
  118. id: 'T_1',
  119. token: 'e2e-default-channel',
  120. },
  121. ],
  122. });
  123. });
  124. it('role', async () => {
  125. const result = await adminClient.query<GetRole.Query, GetRole.Variables>(GET_ROLE, {
  126. id: createdRole.id,
  127. });
  128. expect(result.role).toEqual(createdRole);
  129. });
  130. describe('updateRole', () => {
  131. it('updates role', async () => {
  132. const result = await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
  133. input: {
  134. id: createdRole.id,
  135. code: 'test-modified',
  136. description: 'test role modified',
  137. permissions: [
  138. Permission.ReadCustomer,
  139. Permission.UpdateCustomer,
  140. Permission.DeleteCustomer,
  141. ],
  142. },
  143. });
  144. expect(omit(result.updateRole, ['channels'])).toEqual({
  145. code: 'test-modified',
  146. description: 'test role modified',
  147. id: 'T_5',
  148. permissions: [
  149. Permission.Authenticated,
  150. Permission.ReadCustomer,
  151. Permission.UpdateCustomer,
  152. Permission.DeleteCustomer,
  153. ],
  154. });
  155. });
  156. it('works with partial input', async () => {
  157. const result = await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
  158. input: {
  159. id: createdRole.id,
  160. code: 'test-modified-again',
  161. },
  162. });
  163. expect(result.updateRole.code).toBe('test-modified-again');
  164. expect(result.updateRole.description).toBe('test role modified');
  165. expect(result.updateRole.permissions).toEqual([
  166. Permission.Authenticated,
  167. Permission.ReadCustomer,
  168. Permission.UpdateCustomer,
  169. Permission.DeleteCustomer,
  170. ]);
  171. });
  172. it('deduplicates permissions', async () => {
  173. const result = await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
  174. input: {
  175. id: createdRole.id,
  176. permissions: [
  177. Permission.Authenticated,
  178. Permission.Authenticated,
  179. Permission.ReadCustomer,
  180. Permission.ReadCustomer,
  181. ],
  182. },
  183. });
  184. expect(result.updateRole.permissions).toEqual([
  185. Permission.Authenticated,
  186. Permission.ReadCustomer,
  187. ]);
  188. });
  189. it(
  190. 'does not allow setting non-assignable permissions - Owner',
  191. assertThrowsWithMessage(async () => {
  192. await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
  193. input: {
  194. id: createdRole.id,
  195. permissions: [Permission.Owner],
  196. },
  197. });
  198. }, 'The permission "Owner" may not be assigned'),
  199. );
  200. it(
  201. 'does not allow setting non-assignable permissions - Public',
  202. assertThrowsWithMessage(async () => {
  203. await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
  204. input: {
  205. id: createdRole.id,
  206. permissions: [Permission.Public],
  207. },
  208. });
  209. }, 'The permission "Public" may not be assigned'),
  210. );
  211. it(
  212. 'does not allow setting SuperAdmin permission',
  213. assertThrowsWithMessage(async () => {
  214. await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
  215. input: {
  216. id: createdRole.id,
  217. permissions: [Permission.SuperAdmin],
  218. },
  219. });
  220. }, 'The permission "SuperAdmin" may not be assigned'),
  221. );
  222. it(
  223. 'is not allowed for SuperAdmin role',
  224. assertThrowsWithMessage(async () => {
  225. const superAdminRole = defaultRoles.find(r => r.code === SUPER_ADMIN_ROLE_CODE);
  226. if (!superAdminRole) {
  227. fail(`Could not find SuperAdmin role`);
  228. return;
  229. }
  230. return adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
  231. input: {
  232. id: superAdminRole.id,
  233. code: 'superadmin-modified',
  234. description: 'superadmin modified',
  235. permissions: [Permission.Authenticated],
  236. },
  237. });
  238. }, `The role '${SUPER_ADMIN_ROLE_CODE}' cannot be modified`),
  239. );
  240. it(
  241. 'is not allowed for Customer role',
  242. assertThrowsWithMessage(async () => {
  243. const customerRole = defaultRoles.find(r => r.code === CUSTOMER_ROLE_CODE);
  244. if (!customerRole) {
  245. fail(`Could not find Customer role`);
  246. return;
  247. }
  248. return adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
  249. input: {
  250. id: customerRole.id,
  251. code: 'customer-modified',
  252. description: 'customer modified',
  253. permissions: [Permission.Authenticated, Permission.DeleteAdministrator],
  254. },
  255. });
  256. }, `The role '${CUSTOMER_ROLE_CODE}' cannot be modified`),
  257. );
  258. });
  259. it(
  260. 'deleteRole is not allowed for Customer role',
  261. assertThrowsWithMessage(async () => {
  262. const customerRole = defaultRoles.find(r => r.code === CUSTOMER_ROLE_CODE);
  263. if (!customerRole) {
  264. fail(`Could not find Customer role`);
  265. return;
  266. }
  267. return adminClient.query<DeleteRole.Mutation, DeleteRole.Variables>(DELETE_ROLE, {
  268. id: customerRole.id,
  269. });
  270. }, `The role '${CUSTOMER_ROLE_CODE}' cannot be deleted`),
  271. );
  272. it(
  273. 'deleteRole is not allowed for SuperAdmin role',
  274. assertThrowsWithMessage(async () => {
  275. const superAdminRole = defaultRoles.find(r => r.code === SUPER_ADMIN_ROLE_CODE);
  276. if (!superAdminRole) {
  277. fail(`Could not find Customer role`);
  278. return;
  279. }
  280. return adminClient.query<DeleteRole.Mutation, DeleteRole.Variables>(DELETE_ROLE, {
  281. id: superAdminRole.id,
  282. });
  283. }, `The role '${SUPER_ADMIN_ROLE_CODE}' cannot be deleted`),
  284. );
  285. it('deleteRole deletes a role', async () => {
  286. const { deleteRole } = await adminClient.query<DeleteRole.Mutation, DeleteRole.Variables>(
  287. DELETE_ROLE,
  288. {
  289. id: createdRole.id,
  290. },
  291. );
  292. expect(deleteRole.result).toBe(DeletionResult.DELETED);
  293. const { role } = await adminClient.query<GetRole.Query, GetRole.Variables>(GET_ROLE, {
  294. id: createdRole.id,
  295. });
  296. expect(role).toBeNull();
  297. });
  298. describe('multi-channel', () => {
  299. let secondChannel: ChannelFragment;
  300. let multiChannelRole: CreateRole.CreateRole;
  301. beforeAll(async () => {
  302. const { createChannel } = await adminClient.query<
  303. CreateChannel.Mutation,
  304. CreateChannel.Variables
  305. >(CREATE_CHANNEL, {
  306. input: {
  307. code: 'second-channel',
  308. token: 'second-channel-token',
  309. defaultLanguageCode: LanguageCode.en,
  310. currencyCode: CurrencyCode.GBP,
  311. pricesIncludeTax: true,
  312. defaultShippingZoneId: 'T_1',
  313. defaultTaxZoneId: 'T_1',
  314. },
  315. });
  316. secondChannel = createChannel as any;
  317. });
  318. it('createRole with specified channel', async () => {
  319. const result = await adminClient.query<CreateRole.Mutation, CreateRole.Variables>(CREATE_ROLE, {
  320. input: {
  321. code: 'multi-test',
  322. description: 'multi channel test role',
  323. permissions: [Permission.ReadCustomer],
  324. channelIds: [secondChannel.id],
  325. },
  326. });
  327. multiChannelRole = result.createRole;
  328. expect(multiChannelRole).toEqual({
  329. code: 'multi-test',
  330. description: 'multi channel test role',
  331. id: 'T_6',
  332. permissions: [Permission.Authenticated, Permission.ReadCustomer],
  333. channels: [
  334. {
  335. code: 'second-channel',
  336. id: 'T_2',
  337. token: 'second-channel-token',
  338. },
  339. ],
  340. });
  341. });
  342. it('updateRole with specified channel', async () => {
  343. const { updateRole } = await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(
  344. UPDATE_ROLE,
  345. {
  346. input: {
  347. id: multiChannelRole.id,
  348. channelIds: ['T_1', 'T_2'],
  349. },
  350. },
  351. );
  352. expect(updateRole.channels.sort(sortById)).toEqual([
  353. {
  354. code: DEFAULT_CHANNEL_CODE,
  355. id: 'T_1',
  356. token: 'e2e-default-channel',
  357. },
  358. {
  359. code: 'second-channel',
  360. id: 'T_2',
  361. token: 'second-channel-token',
  362. },
  363. ]);
  364. });
  365. });
  366. });
  367. export const GET_ROLES = gql`
  368. query GetRoles($options: RoleListOptions) {
  369. roles(options: $options) {
  370. items {
  371. ...Role
  372. }
  373. totalItems
  374. }
  375. }
  376. ${ROLE_FRAGMENT}
  377. `;
  378. export const GET_ROLE = gql`
  379. query GetRole($id: ID!) {
  380. role(id: $id) {
  381. ...Role
  382. }
  383. }
  384. ${ROLE_FRAGMENT}
  385. `;
  386. export const DELETE_ROLE = gql`
  387. mutation DeleteRole($id: ID!) {
  388. deleteRole(id: $id) {
  389. result
  390. message
  391. }
  392. }
  393. `;