api-token.integ.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import { faker } from '@faker-js/faker';
  2. import { serializeUserSecurely } from '@growi/core/dist/models/serializers';
  3. import type { Response } from 'express';
  4. import { mock } from 'vitest-mock-extended';
  5. import type Crowi from '~/server/crowi';
  6. import type UserEvent from '~/server/events/user';
  7. import { parserForApiToken } from './api-token';
  8. import type { AccessTokenParserReq } from './interfaces';
  9. vi.mock('@growi/core/dist/models/serializers', { spy: true });
  10. describe('access-token-parser middleware', () => {
  11. let User;
  12. beforeAll(async() => {
  13. const crowiMock = mock<Crowi>({
  14. event: vi.fn().mockImplementation((eventName) => {
  15. if (eventName === 'user') {
  16. return mock<UserEvent>({
  17. on: vi.fn(),
  18. });
  19. }
  20. }),
  21. });
  22. const userModelFactory = (await import('../../models/user')).default;
  23. User = userModelFactory(crowiMock);
  24. });
  25. it('should call next if no access token is provided', async() => {
  26. // arrange
  27. const reqMock = mock<AccessTokenParserReq>({
  28. user: undefined,
  29. });
  30. const resMock = mock<Response>();
  31. const nextMock = vi.fn();
  32. expect(reqMock.user).toBeUndefined();
  33. // act
  34. await parserForApiToken(reqMock, resMock, nextMock);
  35. // assert
  36. expect(reqMock.user).toBeUndefined();
  37. expect(serializeUserSecurely).not.toHaveBeenCalled();
  38. });
  39. it('should call next if the given access token is invalid', async() => {
  40. // arrange
  41. const reqMock = mock<AccessTokenParserReq>({
  42. user: undefined,
  43. });
  44. const resMock = mock<Response>();
  45. const nextMock = vi.fn();
  46. expect(reqMock.user).toBeUndefined();
  47. // act
  48. reqMock.query.access_token = 'invalidToken';
  49. await parserForApiToken(reqMock, resMock, nextMock);
  50. // assert
  51. expect(reqMock.user).toBeUndefined();
  52. expect(serializeUserSecurely).not.toHaveBeenCalled();
  53. });
  54. it('should set req.user with a valid api token in query', async() => {
  55. // arrange
  56. const reqMock = mock<AccessTokenParserReq>({
  57. user: undefined,
  58. });
  59. const resMock = mock<Response>();
  60. const nextMock = vi.fn();
  61. expect(reqMock.user).toBeUndefined();
  62. // prepare a user with an access token
  63. const targetUser = await User.create({
  64. name: faker.person.fullName(),
  65. username: faker.string.uuid(),
  66. password: faker.internet.password(),
  67. lang: 'en_US',
  68. apiToken: faker.internet.password(),
  69. });
  70. // act
  71. reqMock.query.access_token = targetUser.apiToken;
  72. await parserForApiToken(reqMock, resMock, nextMock);
  73. // assert
  74. expect(reqMock.user).toBeDefined();
  75. expect(reqMock.user?._id).toStrictEqual(targetUser._id);
  76. expect(serializeUserSecurely).toHaveBeenCalledOnce();
  77. });
  78. it('should set req.user with a valid api token in body', async() => {
  79. // arrange
  80. const reqMock = mock<AccessTokenParserReq>({
  81. user: undefined,
  82. });
  83. const resMock = mock<Response>();
  84. const nextMock = vi.fn();
  85. expect(reqMock.user).toBeUndefined();
  86. // prepare a user with an access token
  87. const targetUser = await User.create({
  88. name: faker.person.fullName(),
  89. username: faker.string.uuid(),
  90. password: faker.internet.password(),
  91. lang: 'en_US',
  92. apiToken: faker.internet.password(),
  93. });
  94. // act
  95. reqMock.body.access_token = targetUser.apiToken;
  96. await parserForApiToken(reqMock, resMock, nextMock);
  97. // assert
  98. expect(reqMock.user).toBeDefined();
  99. expect(reqMock.user?._id).toStrictEqual(targetUser._id);
  100. expect(serializeUserSecurely).toHaveBeenCalledOnce();
  101. });
  102. });