role.e2e-spec.ts 15 KB

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