refactor: 迁移后台身份权限与平台配置
This commit is contained in:
parent
c5f42251bc
commit
51f05acf55
@ -754,6 +754,11 @@ git -C D:\MyFiles\KT commit -m "docs: 记录第三期基础层迁移"
|
||||
|
||||
## Batch 2: Admin/Auth/Platform Config
|
||||
|
||||
Reusable guardrail for later module batches: route contract tests must prove both
|
||||
decorator route compatibility and module graph reachability. If a route remains
|
||||
available through an imported legacy module, assert the importing module metadata
|
||||
and assert that the imported controller is not also registered directly.
|
||||
|
||||
### Task 2.1: Build new Admin module boundary
|
||||
|
||||
**Files:**
|
||||
@ -763,19 +768,21 @@ git -C D:\MyFiles\KT commit -m "docs: 记录第三期基础层迁移"
|
||||
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\src\app.module.ts`
|
||||
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\admin\admin-contract.spec.ts`
|
||||
|
||||
- [ ] **Step 1: Write RED route compatibility test**
|
||||
- [x] **Step 1: Write RED route compatibility test**
|
||||
|
||||
Create assertions for login, menu, user, role, dept, dict, notice controller paths using `test/helpers/controller-route.helper.ts`.
|
||||
|
||||
- [ ] **Step 2: Create module shell**
|
||||
- [x] **Step 2: Create module shell**
|
||||
|
||||
Create `src/modules/admin/admin.module.ts` with controllers and providers grouped by `identity` and `platform-config`.
|
||||
|
||||
- [ ] **Step 3: Move one domain at a time**
|
||||
- [x] **Step 3: Move one domain at a time**
|
||||
|
||||
Move identity first, then menu/permission, then dict/component/notice. After each move, run the related Jest file.
|
||||
|
||||
- [ ] **Step 4: Verify**
|
||||
Actual: Batch 2 kept legacy `src/admin/**` files in place and created the new shell boundary by grouping identity and platform-config controllers/providers. Dict and notice remain reachable through imported legacy modules to avoid duplicate controller registration.
|
||||
|
||||
- [x] **Step 4: Verify**
|
||||
|
||||
Run:
|
||||
|
||||
@ -794,15 +801,19 @@ Expected: PASS.
|
||||
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\system\*.ts`
|
||||
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\system\**`
|
||||
|
||||
- [ ] **Step 1: Update API types to string IDs**
|
||||
- [x] **Step 1: Update API types to string IDs**
|
||||
|
||||
All ID fields crossing the API boundary use `string`.
|
||||
|
||||
- [ ] **Step 2: Ensure route page roots are stable**
|
||||
Actual: no Admin frontend edit was needed. The targeted `core` and `system` API wrappers already use string IDs for user, role, menu, dept, dict, and notice contracts; the only `id: number` scan hit is the local `SystemKtTableDemo` demo row type, not a backend contract.
|
||||
|
||||
- [x] **Step 2: Ensure route page roots are stable**
|
||||
|
||||
Every changed route page has a single stable root element.
|
||||
|
||||
- [ ] **Step 3: Verify Admin typecheck**
|
||||
Actual: targeted system pages already use a single `Page` root, with modal/drawer children inside the page root.
|
||||
|
||||
- [x] **Step 3: Verify Admin typecheck**
|
||||
|
||||
Run:
|
||||
|
||||
@ -812,10 +823,12 @@ pnpm --dir D:\MyFiles\KT\Vue\kt-template-admin -F @vben/web-antdv-next run typec
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 4: Run local login/menu smoke**
|
||||
- [x] **Step 4: Run local login/menu smoke**
|
||||
|
||||
Start API and Admin only for this smoke. Save evidence under `.kt-workspace/test-artifacts/admin-system/<date>/`.
|
||||
|
||||
Actual: because Admin frontend had no code diff in this batch, full dev-server login was not started. The interface smoke used a local Nest TestingModule HTTP server with real Admin boundary controllers from `ADMIN_IDENTITY_CONTROLLERS` and `ADMIN_PLATFORM_CONFIG_CONTROLLERS`, then called `GET /auth/password-public-key`, `GET /menu/all`, `GET /dict/codes`, and `GET /system/notice/list` successfully.
|
||||
|
||||
### Task 2.3: Commit Batch 2
|
||||
|
||||
Run:
|
||||
@ -829,6 +842,8 @@ git -C D:\MyFiles\KT add TASKS.md
|
||||
git -C D:\MyFiles\KT commit -m "docs: 记录第三期系统管理迁移"
|
||||
```
|
||||
|
||||
Actual: Admin repo remained clean after Task 2.2 verification, so Batch 2 creates no Admin commit.
|
||||
|
||||
## Batch 3: Blog/WordPress/Asset
|
||||
|
||||
### Task 3.1: Build Blog, WordPress, and Asset modules
|
||||
|
||||
@ -14,7 +14,7 @@ import {
|
||||
createPinoLoggerParams,
|
||||
SaveBodyInterceptor,
|
||||
} from './common';
|
||||
import { AdminModule } from './admin/admin.module';
|
||||
import { AdminModule } from './modules/admin/admin.module';
|
||||
import { BlogModule } from './blog/blog.module';
|
||||
import { WordpressModule } from './wordpress/wordpress.module';
|
||||
import { QqbotModule } from './qqbot/qqbot.module';
|
||||
|
||||
8
src/modules/admin/admin.module.ts
Normal file
8
src/modules/admin/admin.module.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AdminIdentityModule } from './identity/admin-identity.module';
|
||||
import { AdminPlatformConfigModule } from './platform-config/admin-platform-config.module';
|
||||
|
||||
@Module({
|
||||
imports: [AdminIdentityModule, AdminPlatformConfigModule],
|
||||
})
|
||||
export class AdminModule {}
|
||||
45
src/modules/admin/identity/admin-identity.module.ts
Normal file
45
src/modules/admin/identity/admin-identity.module.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { AdminAuthGuardModule } from '@/admin/auth/admin-auth-guard.module';
|
||||
import { AdminAuthController } from '@/admin/auth/admin-auth.controller';
|
||||
import { AdminDeptController } from '@/admin/dept/admin-dept.controller';
|
||||
import { AdminDept } from '@/admin/dept/admin-dept.entity';
|
||||
import { AdminDeptService } from '@/admin/dept/admin-dept.service';
|
||||
import { AdminMenuController } from '@/admin/menu/admin-menu.controller';
|
||||
import { AdminMenu } from '@/admin/menu/admin-menu.entity';
|
||||
import { AdminMenuService } from '@/admin/menu/admin-menu.service';
|
||||
import { AdminRoleController } from '@/admin/role/admin-role.controller';
|
||||
import { AdminRole } from '@/admin/role/admin-role.entity';
|
||||
import { AdminRoleService } from '@/admin/role/admin-role.service';
|
||||
import { AdminUserManageController } from '@/admin/user/admin-user-manage.controller';
|
||||
import { AdminUserController } from '@/admin/user/admin-user.controller';
|
||||
import { AdminUser } from '@/admin/user/admin-user.entity';
|
||||
import { AdminUserService } from '@/admin/user/admin-user.service';
|
||||
import { WordpressModule } from '@/wordpress/wordpress.module';
|
||||
|
||||
export const ADMIN_IDENTITY_CONTROLLERS = [
|
||||
AdminAuthController,
|
||||
AdminUserController,
|
||||
AdminUserManageController,
|
||||
AdminMenuController,
|
||||
AdminRoleController,
|
||||
AdminDeptController,
|
||||
];
|
||||
|
||||
export const ADMIN_IDENTITY_PROVIDERS = [
|
||||
AdminUserService,
|
||||
AdminMenuService,
|
||||
AdminRoleService,
|
||||
AdminDeptService,
|
||||
];
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([AdminUser, AdminRole, AdminMenu, AdminDept]),
|
||||
AdminAuthGuardModule,
|
||||
WordpressModule,
|
||||
],
|
||||
controllers: ADMIN_IDENTITY_CONTROLLERS,
|
||||
providers: ADMIN_IDENTITY_PROVIDERS,
|
||||
})
|
||||
export class AdminIdentityModule {}
|
||||
@ -0,0 +1,53 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { AdminAuthGuardModule } from '@/admin/auth/admin-auth-guard.module';
|
||||
import { ComponentController } from '@/admin/component/component.controller';
|
||||
import { Component } from '@/admin/component/component.entity';
|
||||
import { ComponentService } from '@/admin/component/component.service';
|
||||
import { DictController } from '@/admin/dict/dict.controller';
|
||||
import { DictModule } from '@/admin/dict/dict.module';
|
||||
import { AdminNoticeController } from '@/admin/notice/admin-notice.controller';
|
||||
import { NoticeModule } from '@/admin/notice/notice.module';
|
||||
import { SystemLogController } from '@/admin/system-log/system-log.controller';
|
||||
import { SystemLogService } from '@/admin/system-log/system-log.service';
|
||||
import { AdminTimezoneController } from '@/admin/timezone/admin-timezone.controller';
|
||||
import { AdminTimezoneService } from '@/admin/timezone/admin-timezone.service';
|
||||
import { AdminUser } from '@/admin/user/admin-user.entity';
|
||||
import { AdminExampleController } from '@/admin/example/admin-example.controller';
|
||||
import { MinioClientModule } from '@/minio/minio.module';
|
||||
|
||||
export const ADMIN_PLATFORM_CONFIG_DIRECT_CONTROLLERS = [
|
||||
ComponentController,
|
||||
SystemLogController,
|
||||
AdminTimezoneController,
|
||||
AdminExampleController,
|
||||
];
|
||||
|
||||
export const ADMIN_PLATFORM_CONFIG_IMPORTED_CONTROLLERS = [
|
||||
DictController,
|
||||
AdminNoticeController,
|
||||
];
|
||||
|
||||
export const ADMIN_PLATFORM_CONFIG_CONTROLLERS = [
|
||||
...ADMIN_PLATFORM_CONFIG_DIRECT_CONTROLLERS,
|
||||
...ADMIN_PLATFORM_CONFIG_IMPORTED_CONTROLLERS,
|
||||
];
|
||||
|
||||
export const ADMIN_PLATFORM_CONFIG_PROVIDERS = [
|
||||
ComponentService,
|
||||
SystemLogService,
|
||||
AdminTimezoneService,
|
||||
];
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Component, AdminUser]),
|
||||
AdminAuthGuardModule,
|
||||
DictModule,
|
||||
NoticeModule,
|
||||
MinioClientModule,
|
||||
],
|
||||
controllers: ADMIN_PLATFORM_CONFIG_DIRECT_CONTROLLERS,
|
||||
providers: ADMIN_PLATFORM_CONFIG_PROVIDERS,
|
||||
})
|
||||
export class AdminPlatformConfigModule {}
|
||||
104
test/modules/admin/admin-contract.spec.ts
Normal file
104
test/modules/admin/admin-contract.spec.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import { MODULE_METADATA } from '@nestjs/common/constants';
|
||||
import { DictController } from '../../../src/admin/dict/dict.controller';
|
||||
import { DictModule } from '../../../src/admin/dict/dict.module';
|
||||
import { AdminNoticeController } from '../../../src/admin/notice/admin-notice.controller';
|
||||
import { NoticeModule } from '../../../src/admin/notice/notice.module';
|
||||
import { AdminModule } from '../../../src/modules/admin/admin.module';
|
||||
import {
|
||||
ADMIN_IDENTITY_CONTROLLERS,
|
||||
AdminIdentityModule,
|
||||
} from '../../../src/modules/admin/identity/admin-identity.module';
|
||||
import {
|
||||
ADMIN_PLATFORM_CONFIG_DIRECT_CONTROLLERS,
|
||||
ADMIN_PLATFORM_CONFIG_CONTROLLERS,
|
||||
ADMIN_PLATFORM_CONFIG_IMPORTED_CONTROLLERS,
|
||||
AdminPlatformConfigModule,
|
||||
} from '../../../src/modules/admin/platform-config/admin-platform-config.module';
|
||||
import {
|
||||
collectControllerRoutes,
|
||||
routeKey,
|
||||
} from '../../helpers/controller-route.helper';
|
||||
|
||||
const getModuleMetadata = <T>(moduleClass: unknown, key: string): T[] => {
|
||||
return Reflect.getMetadata(key, moduleClass) || [];
|
||||
};
|
||||
|
||||
describe('Admin module route contract', () => {
|
||||
it('keeps legacy Admin route paths available from the new module boundary', () => {
|
||||
const routes = collectControllerRoutes([
|
||||
...ADMIN_IDENTITY_CONTROLLERS,
|
||||
...ADMIN_PLATFORM_CONFIG_CONTROLLERS,
|
||||
]);
|
||||
|
||||
expect(routes.map(routeKey)).toEqual(
|
||||
expect.arrayContaining([
|
||||
'GET /auth/password-public-key',
|
||||
'POST /auth/login',
|
||||
'POST /auth/refresh',
|
||||
'POST /auth/logout',
|
||||
'GET /auth/codes',
|
||||
'GET /menu/all',
|
||||
'GET /user/info',
|
||||
'PUT /user/profile',
|
||||
'GET /system/user/list',
|
||||
'POST /system/user',
|
||||
'PUT /system/user/:id',
|
||||
'DELETE /system/user/:id',
|
||||
'GET /system/menu/list',
|
||||
'GET /system/menu/name-exists',
|
||||
'GET /system/menu/path-exists',
|
||||
'POST /system/menu',
|
||||
'PUT /system/menu/:id',
|
||||
'DELETE /system/menu/:id',
|
||||
'GET /system/role/list',
|
||||
'POST /system/role',
|
||||
'PUT /system/role/:id',
|
||||
'DELETE /system/role/:id',
|
||||
'GET /system/dept/list',
|
||||
'POST /system/dept',
|
||||
'PUT /system/dept/:id',
|
||||
'DELETE /system/dept/:id',
|
||||
'GET /dict/list',
|
||||
'GET /dict/tree',
|
||||
'GET /dict/groups',
|
||||
'GET /dict/codes',
|
||||
'GET /dict/getDictByKey',
|
||||
'GET /dict/getComponentDictByType',
|
||||
'POST /dict/save',
|
||||
'POST /dict/update',
|
||||
'DELETE /dict/:id',
|
||||
'POST /dict/toggle',
|
||||
'GET /system/notice/list',
|
||||
'GET /system/notice/detail/:id',
|
||||
'DELETE /system/notice/:id',
|
||||
'POST /system/notice/toggle',
|
||||
'POST /system/notice/top',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps dict and notice reachable through platform-config module imports', () => {
|
||||
expect(getModuleMetadata(AdminModule, MODULE_METADATA.IMPORTS)).toEqual(
|
||||
expect.arrayContaining([AdminIdentityModule, AdminPlatformConfigModule]),
|
||||
);
|
||||
|
||||
expect(
|
||||
getModuleMetadata(AdminPlatformConfigModule, MODULE_METADATA.IMPORTS),
|
||||
).toEqual(expect.arrayContaining([DictModule, NoticeModule]));
|
||||
|
||||
const directControllers = getModuleMetadata(
|
||||
AdminPlatformConfigModule,
|
||||
MODULE_METADATA.CONTROLLERS,
|
||||
);
|
||||
|
||||
expect(directControllers).toEqual(
|
||||
expect.arrayContaining(ADMIN_PLATFORM_CONFIG_DIRECT_CONTROLLERS),
|
||||
);
|
||||
expect(directControllers).not.toEqual(
|
||||
expect.arrayContaining([DictController, AdminNoticeController]),
|
||||
);
|
||||
expect(ADMIN_PLATFORM_CONFIG_IMPORTED_CONTROLLERS).toEqual(
|
||||
expect.arrayContaining([DictController, AdminNoticeController]),
|
||||
);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user