Skip to content

Các Lớp Cơ sở Ứng dụng

Tổng quan

@nx/core cung cấp một lớp cơ sở trừu tượng, BaseApplication, chứa hạ tầng mà mọi dịch vụ backend BANA dùng chung: middleware CORS và giới hạn body, endpoint health check, tài liệu Swagger/OpenAPI, phục vụ tệp tĩnh, đăng ký IdentityNetworkService, và luồng khởi tạo preConfigure().

Các dịch vụ không kế thừa trực tiếp BaseApplication. Chúng kế thừa một trong hai lớp con cụ thể dựa trên vai trò trong chuỗi tin cậy JWT:

  • IssuerApplication - chỉ được kế thừa bởi @nx/identity. Ký JWT (JWKS issuer) và phục vụ tập khóa công khai tại /jw-certs.
  • VerifierApplication - được kế thừa bởi 13 dịch vụ IGNIS còn lại. Xác minh JWT dựa trên endpoint JWKS của identity.

Lớp con thứ ba, DefaultApplication, là legacy và không được dùng - không có gì kế thừa nó. Nó có trước cặp Issuer/Verifier và dùng token JWS đối xứng, không có phân quyền.

Nguồn:

TệpLớp
packages/core/src/application/base.tsBaseApplication (trừu tượng, dùng chung)
packages/core/src/application/issuer.tsIssuerApplication
packages/core/src/application/verifier.tsVerifierApplication
packages/core/src/application/default.tsDefaultApplication (legacy)

Xem tham chiếu IGNIS Application để biết chi tiết về BaseApplication của IGNIS mà lớp cơ sở của @nx/core mở rộng.

Phân cấp Lớp

Lớp cơ sởĐược kế thừa bởiXác thựcPhân quyền
BaseApplication (trừu tượng)- (dùng chung)khai báo configureAuthentication()khai báo configureAuthorization()
IssuerApplicationchỉ @nx/identityJWKS issuer (ký, phục vụ /jw-certs)Casbin (scoped)
VerifierApplicationcommerce, finance, inventory, sale, signal, payment, pricing, ledger, invoice, licensing, outreach, taxation, helpdeskJWKS verifier (xác minh dựa trên JWKS của identity)Casbin (scoped)
DefaultApplicationkhông có gì (legacy)JWS đối xứngkhông có

Định nghĩa Lớp

BaseApplication là trừu tượng: nó triển khai vòng đời dùng chung và để phần xác thực/phân quyền cho các lớp con.

typescript
import { BaseApplication as IgnisBaseApplication, IApplicationInfo } from '@venizia/ignis';
import { ValueOrPromise } from '@venizia/ignis-helpers';

export abstract class BaseApplication extends IgnisBaseApplication {
  protected applicationRoles: string[] = [];

  // Implemented per subclass (Issuer / Verifier / Default)
  protected abstract configureAuthentication(): ValueOrPromise<void>;
  protected abstract configureAuthorization(): ValueOrPromise<void>;

  // Shared lifecycle
  override getAppInfo(): IApplicationInfo;
  preConfigure(): void;
  async postConfigure(): Promise<void>;
  override async setupMiddlewares(): Promise<void>;
  staticConfigure(): void;

  // Registration methods (override in child packages)
  configureDatasources(): void;
  configureRepositories(): void;
  configureServices(): void;     // registers IdentityNetworkService
  configureComponents(): void;   // HealthCheck + Swagger
  configureSecurity(): void;     // -> configureAuthentication() + configureAuthorization()
  configureControllers(): void;
}

Vòng đời và Trình tự Khởi động

Thứ tự Gọi preConfigure()

preConfigure() chạy các phương thức đăng ký theo thứ tự cố định. Ở chế độ chạy MIGRATE, nó dừng sớm sau repository (migration chỉ cần truy cập cơ sở dữ liệu); ngược lại tiếp tục qua service, component, security, và controller.

typescript
preConfigure() {
  this.applicationRoles = this.getApplicationRoles();

  this.configureDatasources();   // 1. Data sources
  this.configureRepositories();  // 2. Repositories

  if (this.getApplicationRunMode() !== ApplicationRunModes.MIGRATE) {
    this.configureServices();      // 3. Services (IdentityNetworkService)
    this.configureComponents();    // 4. Components (HealthCheck, Swagger)
    this.configureSecurity();      // 5. Authentication + Authorization
    this.configureControllers();   // 6. Controllers
  }
}

Trình tự Khởi động Đầy đủ

Cấu hình Middleware

setupMiddlewares() nằm trong lớp cơ sở dùng chung. Nó tùy chọn cắm một middleware tracing HTTP (chỉ khi telemetry được khởi tạo bởi bootstrapApplication), rồi đăng ký CORS và một giới hạn body.

CORS

typescript
cors: {
  enable: true,
  path: '*',
  origin: '*',
  allowMethods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE', 'OPTIONS'],
  allowHeaders: [/* see table below */],
  exposeHeaders: [/* see table below */],
  maxAge: 86_400,  // 24 hours
  credentials: true,
}

Các Header Yêu cầu Được phép:

HeaderHằng số IGNIS
AuthorizationHTTP.Headers.AUTHORIZATION
Content-TypeHTTP.Headers.CONTENT_TYPE
X-Request-ChannelHTTP.Headers.REQUEST_CHANNEL
X-Count-DataHTTP.Headers.REQUEST_COUNT_DATA
X-Device-InfoHTTP.Headers.REQUEST_DEVICE_INFO
X-Tracing-IdHTTP.Headers.REQUEST_TRACING_ID
timezoneTùy chỉnh
timezone-offsetTùy chỉnh
x-auth-providerTùy chỉnh
x-forward-forTùy chỉnh
x-localeTùy chỉnh
x-merchant-idTùy chỉnh (phạm vi merchant đang hoạt động)
x-real-ipTùy chỉnh

Các Header Phản hồi Được phơi bày:

HeaderHằng số IGNIS
Content-DispositionHTTP.Headers.CONTENT_DISPOSITION
Content-LengthHTTP.Headers.CONTENT_LENGTH
Content-RangeHTTP.Headers.CONTENT_RANGE
Content-TypeHTTP.Headers.CONTENT_TYPE
X-Count-DataHTTP.Headers.RESPONSE_COUNT_DATA
X-Response-FormatHTTP.Headers.RESPONSE_FORMAT
x-custom-headerTùy chỉnh

Giới hạn Body

typescript
bodyLimit: {
  enable: true,
  path: '*',
  maxSize: 100 * 1024 * 1024,  // 100 MB
  onError: c => c.json({}, HTTP.ResultCodes.RS_4.ContentTooLarge),  // HTTP 413
}

Thiết lập Thành phần

Health Check

Được đăng ký tại endpoint /health. Trả về thông tin trạng thái ứng dụng.

typescript
this.bind<IHealthCheckOptions>({
  key: HealthCheckBindingKeys.HEALTH_CHECK_OPTIONS,
}).toValue({
  restOptions: { path: '/health' },
});
this.component(HealthCheckComponent);

Xem tham chiếu IGNIS Health Check để biết định dạng phản hồi và tùy chỉnh.

Swagger / OpenAPI

Cung cấp ba endpoint cho tài liệu API, sử dụng trình hiển thị Swagger UI (ui.type: 'swagger'):

Đường dẫnMô tả
/docĐường dẫn cơ sở tài liệu
/openapi.jsonĐặc tả OpenAPI 3.0 (JSON)
/explorerSwagger UI
typescript
this.bind<ISwaggerOptions>({ key: SwaggerBindingKeys.SWAGGER_OPTIONS }).toValue({
  restOptions: {
    base: { path: '/doc' },
    doc: { path: '/openapi.json' },
    ui: { path: '/explorer', type: 'swagger' },
  },
  explorer: {
    openapi: '3.0.0',
    info: {
      title: 'API Documentation',
      version: this.getAppInfo().version,
      description: 'NEXPANDO - Seller API documentation',
    },
    servers: [
      {
        url: applicationEnvironment.get<string>(EnvironmentKeys.APP_ENV_APPLICATION_EXPLORER_URL),
        description: 'Application Server URL',
      },
    ],
  },
});
this.component(SwaggerComponent);

Xem tham chiếu IGNIS Swagger để biết đầy đủ tùy chọn.

Thiết lập Bảo mật

configureSecurity() được lớp cơ sở dùng chung và chỉ ủy thác cho hai phương thức trừu tượng mà mỗi lớp con triển khai:

typescript
configureSecurity(): void {
  this.configureAuthentication();
  this.configureAuthorization();
}

Xác thực theo Lớp con

Lớp conChiến lược JWTJOSEStandardsGhi chú
IssuerApplicationJWKSIssuerAuthenticationStrategyJWKS (mode ISSUER)Ký bằng khóa riêng PEM; công bố khóa tại /jw-certs
VerifierApplicationJWKSVerifierAuthenticationStrategyJWKS (mode VERIFIER)Xác minh dựa trên APP_ENV_IDENTITY_SERVICE_BASE_URL + /jw-certs
DefaultApplicationJWSAuthenticationStrategyJWSSecret đối xứng legacy; không dịch vụ nào dùng

Cả ba đều gọi helper dùng chung bindBasicAuthentication(), đăng ký AuthenticateComponent, và thêm một chiến lược Basic ủy thác cho dịch vụ Identity.

Xác thực Basic (dùng chung)

bindBasicAuthentication() (định nghĩa trên lớp cơ sở) ủy thác việc xác minh thông tin đăng nhập cho dịch vụ Identity thông qua IdentityNetworkService.signIn():

typescript
protected bindBasicAuthentication(): void {
  this.bind<TBasicTokenServiceOptions>({ key: AuthenticateBindingKeys.BASIC_OPTIONS }).toValue({
    verifyCredentials: ({ credentials }) => {
      const identityNetworkService = this.get<IdentityNetworkService>({
        key: BindingKeys.build({
          namespace: BindingNamespaces.SERVICE,
          key: IdentityNetworkService.name,
        }),
      });

      return identityNetworkService.signIn({
        identifier: { scheme: 'username', value: credentials.username },
        credential: { scheme: 'basic', value: credentials.password },
      });
    },
  });
}

Phân quyền (Casbin)

IssuerApplicationVerifierApplication đều đăng ký IGNIS AuthorizeComponent với một Casbin enforcer scoped (ScopedCasbinAdapter, model domain-scoped, defaultDecision: DENY, alwaysAllowRoles = SUPER_ADMIN / ADMIN / OPERATOR) và một domain resolver scoped theo merchant điều khiển bởi header x-merchant-id. DefaultApplication.configureAuthorization() để trống.

Luồng Xác thực

Xem tham chiếu IGNIS Authentication để biết chi tiết chiến lược.

Phục vụ Tệp Tĩnh

staticConfigure() phục vụ các tệp từ thư mục public/ của gói @nx/core:

typescript
staticConfigure(): void {
  this.static({ folderPath: path.join(__dirname, '../../public') });
}

Cách Mở rộng trong Các Gói Con

Mỗi dịch vụ khai báo lớp Application kế thừa VerifierApplication (hoặc IssuerApplication cho @nx/identity) và ghi đè các phương thức đăng ký, gọi super trước:

typescript
// packages/sale/src/application.ts
import { VerifierApplication, PostgresCoreDataSource } from '@nx/core';

export class Application extends VerifierApplication {
  override configureDatasources(): void {
    super.configureDatasources();
    this.dataSource(PostgresCoreDataSource);
  }

  override configureRepositories(): void {
    super.configureRepositories();
    this.repository(SaleOrderRepository);
    this.repository(SaleOrderItemRepository);
  }

  override configureServices(): void {
    super.configureServices(); // IdentityNetworkService
    this.service(SaleOrderService);
    this.service(CheckoutService);
  }

  override async postConfigure(): Promise<void> {
    await super.postConfigure();
    // Run after all components are bound
  }
}

Luôn gọi super

Khi ghi đè bất kỳ phương thức đăng ký nào, gọi super.<method>() trước để giữ lại các đăng ký mặc định (IdentityNetworkService, HealthCheck, Swagger, JWKS/Basic auth).

Biến Môi trường

BiếnDùng bởiBắt buộcMô tả
APP_ENV_APPLICATION_SECRETTất cảSecret cấp ứng dụng
APP_ENV_JWKS_ALGORITHMIssuerKhôngThuật toán ký (mặc định ES256)
APP_ENV_JWKS_PRIVATE_KEYIssuerKhóa ký riêng PEM
APP_ENV_JWKS_PUBLIC_KEYIssuerKhóa công khai PEM
APP_ENV_JWKS_REST_PATHIssuer + VerifierKhôngĐường dẫn endpoint JWKS (mặc định /jw-certs)
APP_ENV_IDENTITY_SERVICE_BASE_URLVerifier (+ Basic)URL cơ sở dịch vụ Identity (nguồn JWKS + ủy thác Basic)
APP_ENV_JWT_EXPIRES_INIssuerThời gian hết hạn token tính bằng giây
APP_ENV_APPLICATION_ROLESTất cảKhôngDanh sách định danh vai trò phân cách bằng dấu phẩy
APP_ENV_APPLICATION_EXPLORER_URLTất cảKhôngURL server hiển thị trong Swagger explorer

Legacy: DefaultApplication

DefaultApplication (application/default.ts) chỉ được giữ lại để tham khảo. Nó cấu hình một token JWS đối xứng (APP_ENV_JWT_SECRET) qua JWSAuthenticationStrategy và để trống configureAuthorization(). Không dịch vụ nào kế thừa nó - mọi dịch vụ dùng IssuerApplication hoặc VerifierApplication thay vào đó. Không dùng nó cho các gói mới.

Tài liệu Liên quan

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.