role.e2e-spec.ts 13 KB

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