enterprise-auth.integration.test.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. import { describe, it, expect, beforeEach } from 'vitest';
  2. import { testClient } from 'hono/testing';
  3. import {
  4. IntegrationTestDatabase,
  5. setupIntegrationDatabaseHooksWithEntities,
  6. } from '@d8d/shared-test-util';
  7. import { Role, UserEntity, UserService } from '@d8d/core-module/user-module';
  8. import { File } from '@d8d/core-module/file-module';
  9. import { Company } from '@d8d/allin-company-module/entities';
  10. import { Platform } from '@d8d/allin-platform-module/entities';
  11. import { enterpriseAuthRoutes } from '../../src/routes/index';
  12. import { AuthService } from '../../src/services/index';
  13. import { DisabledStatus } from '@d8d/shared-types';
  14. import { TestDataFactory } from '../utils/test-data-factory';
  15. // 设置集成测试钩子,包含公司实体
  16. setupIntegrationDatabaseHooksWithEntities([UserEntity, Role, File, Company, Platform])
  17. describe('企业用户认证API集成测试', () => {
  18. let client: ReturnType<typeof testClient<typeof enterpriseAuthRoutes>>;
  19. let authService: AuthService;
  20. let userService: UserService;
  21. let testToken: string;
  22. let testUser: any;
  23. let testCompany: any;
  24. beforeEach(async () => {
  25. // 创建测试客户端
  26. client = testClient(enterpriseAuthRoutes);
  27. // 获取数据源
  28. const dataSource = await IntegrationTestDatabase.getDataSource();
  29. // 确保数据源已初始化
  30. if (!dataSource.isInitialized) {
  31. await dataSource.initialize();
  32. }
  33. // 初始化服务
  34. userService = new UserService(dataSource);
  35. authService = new AuthService(userService);
  36. // 创建测试平台
  37. const platformRepository = dataSource.getRepository(Platform);
  38. await platformRepository.delete({ platformName: '测试平台' });
  39. const testPlatform = platformRepository.create({
  40. platformName: '测试平台',
  41. contactPerson: '测试联系人',
  42. contactPhone: '13800138000',
  43. contactEmail: 'platform@example.com',
  44. status: 1
  45. });
  46. const savedPlatform = await platformRepository.save(testPlatform);
  47. // 创建测试公司
  48. const companyRepository = dataSource.getRepository(Company);
  49. await companyRepository.delete({ companyName: '测试企业有限公司' });
  50. testCompany = companyRepository.create({
  51. companyName: '测试企业有限公司',
  52. contactPerson: '张经理',
  53. contactPhone: '13800138000',
  54. contactEmail: 'contact@example.com',
  55. address: '北京市朝阳区',
  56. status: 1,
  57. platformId: savedPlatform.id
  58. });
  59. testCompany = await companyRepository.save(testCompany);
  60. // 创建测试企业用户前先删除可能存在的重复用户
  61. const userRepository = dataSource.getRepository(UserEntity);
  62. await userRepository.delete({ username: 'enterprise_user' });
  63. await userRepository.delete({ phone: '13800138001' });
  64. testUser = await TestDataFactory.createTestUser(dataSource, {
  65. username: 'enterprise_user',
  66. password: 'EnterprisePass123!',
  67. email: 'enterprise@example.com',
  68. phone: '13800138001',
  69. companyId: testCompany.id
  70. });
  71. // 生成测试用户的token
  72. testToken = authService.generateToken(testUser);
  73. });
  74. describe('企业用户登录端点测试 (POST /api/v1/yongren/auth/login)', () => {
  75. it('应该使用正确手机号和密码成功登录', async () => {
  76. const loginData = {
  77. phone: '13800138001',
  78. password: 'EnterprisePass123!'
  79. };
  80. const response = await client.login.$post({
  81. json: loginData
  82. });
  83. expect(response.status).toBe(200);
  84. if (response.status === 200) {
  85. const responseData = await response.json();
  86. expect(responseData).toHaveProperty('token');
  87. expect(responseData).toHaveProperty('user');
  88. expect(responseData.user.username).toBe('enterprise_user');
  89. expect(responseData.user.phone).toBe('13800138001');
  90. expect(responseData.user.companyId).toBe(testCompany.id);
  91. expect(responseData.user.company).toBeDefined();
  92. expect(responseData.user.company.companyName).toBe('测试企业有限公司');
  93. expect(typeof responseData.token).toBe('string');
  94. expect(responseData.token.length).toBeGreaterThan(0);
  95. }
  96. });
  97. it('应该拒绝错误密码的登录', async () => {
  98. const loginData = {
  99. phone: '13800138001',
  100. password: 'WrongPassword123!'
  101. };
  102. const response = await client.login.$post({
  103. json: loginData
  104. });
  105. expect(response.status).toBe(401);
  106. if (response.status === 401) {
  107. const responseData = await response.json();
  108. expect(responseData.message).toContain('手机号或密码错误');
  109. }
  110. });
  111. it('应该拒绝不存在的手机号登录', async () => {
  112. const loginData = {
  113. phone: '13999999999',
  114. password: 'EnterprisePass123!'
  115. };
  116. const response = await client.login.$post({
  117. json: loginData
  118. });
  119. expect(response.status).toBe(401);
  120. if (response.status === 401) {
  121. const responseData = await response.json();
  122. expect(responseData.message).toContain('手机号或密码错误');
  123. }
  124. });
  125. it('应该拒绝非企业用户登录(company_id为NULL)', async () => {
  126. // 创建非企业用户
  127. const dataSource = await IntegrationTestDatabase.getDataSource();
  128. const nonEnterpriseUser = await TestDataFactory.createTestUser(dataSource, {
  129. username: 'non_enterprise_user',
  130. password: 'Password123!',
  131. email: 'non_enterprise@example.com',
  132. phone: '13800138002',
  133. companyId: null
  134. });
  135. const loginData = {
  136. phone: '13800138002',
  137. password: 'Password123!'
  138. };
  139. const response = await client.login.$post({
  140. json: loginData
  141. });
  142. expect(response.status).toBe(401);
  143. if (response.status === 401) {
  144. const responseData = await response.json();
  145. expect(responseData.message).toContain('用户不是企业用户');
  146. }
  147. });
  148. it('应该拒绝禁用账户的登录', async () => {
  149. // 禁用测试用户
  150. const dataSource = await IntegrationTestDatabase.getDataSource();
  151. const userRepository = dataSource.getRepository(UserEntity);
  152. await userRepository.update(testUser.id, { isDisabled: DisabledStatus.DISABLED });
  153. const loginData = {
  154. phone: '13800138001',
  155. password: 'EnterprisePass123!'
  156. };
  157. const response = await client.login.$post({
  158. json: loginData
  159. });
  160. expect(response.status).toBe(401);
  161. if (response.status === 401) {
  162. const responseData = await response.json();
  163. expect(responseData.message).toContain('账户已禁用');
  164. }
  165. });
  166. });
  167. describe('企业用户信息端点测试 (GET /api/v1/yongren/auth/me)', () => {
  168. it('应该成功获取企业用户信息,包含企业详情', async () => {
  169. const response = await client.me.$get({
  170. header: {
  171. Authorization: `Bearer ${testToken}`
  172. }
  173. });
  174. expect(response.status).toBe(200);
  175. if (response.status === 200) {
  176. const responseData = await response.json();
  177. expect(responseData.username).toBe('enterprise_user');
  178. expect(responseData.phone).toBe('13800138001');
  179. expect(responseData.companyId).toBe(testCompany.id);
  180. expect(responseData.company).toBeDefined();
  181. expect(responseData.company.companyName).toBe('测试企业有限公司');
  182. expect(responseData.company.contactPerson).toBe('张经理');
  183. expect(responseData.company.contactPhone).toBe('13800138000');
  184. }
  185. });
  186. it('应该拒绝非企业用户访问企业信息接口', async () => {
  187. // 创建非企业用户token
  188. const dataSource = await IntegrationTestDatabase.getDataSource();
  189. const nonEnterpriseUser = await TestDataFactory.createTestUser(dataSource, {
  190. username: 'non_enterprise_user2',
  191. password: 'Password123!',
  192. email: 'non_enterprise2@example.com',
  193. phone: '13800138003',
  194. companyId: null
  195. });
  196. const nonEnterpriseToken = authService.generateToken(nonEnterpriseUser);
  197. const response = await client.me.$get({
  198. header: {
  199. Authorization: `Bearer ${nonEnterpriseToken}`
  200. }
  201. });
  202. expect(response.status).toBe(403);
  203. if (response.status === 403) {
  204. const responseData = await response.json();
  205. expect(responseData.message).toContain('非企业用户');
  206. }
  207. });
  208. it('应该拒绝无效令牌的访问', async () => {
  209. const response = await client.me.$get({
  210. header: {
  211. Authorization: 'Bearer invalid_token'
  212. }
  213. });
  214. expect(response.status).toBe(401);
  215. });
  216. it('应该拒绝缺少令牌的访问', async () => {
  217. const response = await client.me.$get();
  218. expect(response.status).toBe(401);
  219. });
  220. });
  221. describe('企业用户退出登录端点测试 (POST /api/v1/yongren/auth/logout)', () => {
  222. it('应该成功退出登录', async () => {
  223. const response = await client.logout.$post({
  224. header: {
  225. Authorization: `Bearer ${testToken}`
  226. }
  227. });
  228. expect(response.status).toBe(200);
  229. if (response.status === 200) {
  230. const responseData = await response.json();
  231. expect(responseData.message).toBe('登出成功');
  232. }
  233. });
  234. it('应该拒绝无效令牌的退出登录', async () => {
  235. const response = await client.logout.$post({
  236. header: {
  237. Authorization: 'Bearer invalid_token'
  238. }
  239. });
  240. expect(response.status).toBe(401);
  241. });
  242. });
  243. describe('企业用户权限验证', () => {
  244. it('verifyEnterpriseUser方法应该正确识别企业用户', async () => {
  245. const dataSource = await IntegrationTestDatabase.getDataSource();
  246. const userService = new UserService(dataSource);
  247. const authService = new AuthService(userService);
  248. const isEnterpriseUser = await authService.verifyEnterpriseUser(testUser.id);
  249. expect(isEnterpriseUser).toBe(true);
  250. // 创建非企业用户测试
  251. const nonEnterpriseUser = await TestDataFactory.createTestUser(dataSource, {
  252. username: 'non_enterprise_user3',
  253. password: 'Password123!',
  254. email: 'non_enterprise3@example.com',
  255. phone: '13800138004',
  256. companyId: null
  257. });
  258. const isNonEnterpriseUser = await authService.verifyEnterpriseUser(nonEnterpriseUser.id);
  259. expect(isNonEnterpriseUser).toBe(false);
  260. });
  261. });
  262. });