暂存提交

This commit is contained in:
2026-07-30 18:01:36 +08:00
commit 2f4e159356
368 changed files with 20370 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
server:
port: ${IAM_PORT:9201}
spring:
application:
name: iam-service
config:
import:
- optional:nacos:baiyue-common.yml?group=BAIYUE&refreshEnabled=true
- optional:nacos:${spring.application.name}.yml?group=BAIYUE&refreshEnabled=true
cloud:
nacos:
server-addr: ${NACOS_SERVER_ADDR:127.0.0.1:8848}
username: ${NACOS_USERNAME:nacos}
password: ${NACOS_PASSWORD:nacos}
discovery:
enabled: ${NACOS_DISCOVERY_ENABLED:true}
register-enabled: ${NACOS_REGISTER_ENABLED:true}
group: ${NACOS_GROUP:BAIYUE}
namespace: ${NACOS_NAMESPACE:public}
config:
namespace: ${NACOS_NAMESPACE:public}
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: ${IAM_DB_URL:jdbc:mysql://127.0.0.1:3306/baiyue_iam?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true}
username: ${IAM_DB_USERNAME:root}
password: ${IAM_DB_PASSWORD:123456}
baiyue:
clients:
auth:
url: ${AUTH_SERVICE_URL:}
security:
jwt-secret: ${JWT_SECRET:change-me-to-at-least-32-bytes-long-before-start}
internal-service-token: ${INTERNAL_SERVICE_TOKEN:change-me-to-an-internal-token-at-least-32-bytes-long}
management.endpoints.web.exposure.include: health,info,prometheus
+199
View File
@@ -0,0 +1,199 @@
SET NAMES utf8mb4;
-- IAM 服务独占数据库:负责租户、成员、双端角色、菜单/页面/按钮/API权限和数据范围。
CREATE DATABASE IF NOT EXISTS baiyue_iam
DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
USE baiyue_iam;
CREATE TABLE IF NOT EXISTS iam_tenant (
id BIGINT NOT NULL COMMENT '租户ID(雪花ID)',
tenant_code VARCHAR(64) NOT NULL COMMENT '全局唯一租户编码',
tenant_name VARCHAR(128) NOT NULL COMMENT '租户名称',
tenant_type VARCHAR(20) NOT NULL DEFAULT 'MERCHANT' COMMENT '租户类型',
status VARCHAR(20) NOT NULL DEFAULT 'PROFILE_REQUIRED' COMMENT '租户状态:PROFILE_REQUIRED、PENDING、ACTIVE、REJECTED、DISABLED',
legal_name VARCHAR(128) NULL COMMENT '企业法定名称',
unified_social_credit_code VARCHAR(32) NULL COMMENT '统一社会信用代码',
contact_name VARCHAR(64) NULL COMMENT '企业联系人',
contact_phone VARCHAR(32) NULL COMMENT '联系电话',
contact_email VARCHAR(128) NULL COMMENT '联系邮箱',
approved_at DATETIME(3) NULL COMMENT '审核通过时间',
approved_by BIGINT NULL COMMENT '审核人ID',
reject_reason VARCHAR(500) NULL COMMENT '驳回原因',
created_by BIGINT NULL COMMENT '创建人ID',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
updated_by BIGINT NULL COMMENT '最后修改人ID',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除标记',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY (id),
UNIQUE KEY uk_iam_tenant_code (tenant_code),
UNIQUE KEY uk_iam_tenant_credit (unified_social_credit_code),
KEY idx_iam_tenant_status (status, created_at)
) ENGINE=InnoDB COMMENT='企业租户主表:作为SaaS数据隔离边界,保存商户企业资料、审核结果和启停状态';
CREATE TABLE IF NOT EXISTS iam_tenant_review (
id BIGINT NOT NULL COMMENT '审核记录ID',
tenant_id BIGINT NOT NULL COMMENT '被审核租户ID',
review_type VARCHAR(20) NOT NULL DEFAULT 'REGISTER' COMMENT '审核类型',
status VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT '审核状态',
reviewer_id BIGINT NULL COMMENT '审核人ID',
review_comment VARCHAR(500) NULL COMMENT '审核意见',
reviewed_at DATETIME(3) NULL COMMENT '审核完成时间',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '进入审核队列时间',
PRIMARY KEY (id),
KEY idx_review_queue (status, created_at),
KEY idx_review_tenant (tenant_id)
) ENGINE=InnoDB COMMENT='租户审核记录表:保存企业注册、资料变更等审核过程和审核意见';
CREATE TABLE IF NOT EXISTS iam_tenant_address (
id BIGINT NOT NULL COMMENT '租户地址ID',
tenant_id BIGINT NOT NULL COMMENT '所属租户ID',
address_type VARCHAR(20) NOT NULL COMMENT '地址类型',
country_code CHAR(2) NOT NULL DEFAULT 'CN' COMMENT '国家二字码',
province VARCHAR(64) NULL COMMENT '省/州',
city VARCHAR(64) NULL COMMENT '城市',
district VARCHAR(64) NULL COMMENT '区县',
detail VARCHAR(255) NOT NULL COMMENT '详细地址',
postal_code VARCHAR(16) NULL COMMENT '邮政编码',
is_default TINYINT NOT NULL DEFAULT 0 COMMENT '是否默认地址',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除标记',
PRIMARY KEY (id),
KEY idx_address_tenant (tenant_id, address_type)
) ENGINE=InnoDB COMMENT='租户地址表:保存企业注册地址、办公地址等租户级资料';
CREATE TABLE IF NOT EXISTS iam_tenant_qualification (
id BIGINT NOT NULL COMMENT '资质记录ID',
tenant_id BIGINT NOT NULL COMMENT '所属租户ID',
qualification_type VARCHAR(32) NOT NULL COMMENT '资质类型',
certificate_no VARCHAR(128) NULL COMMENT '证书编号',
document_url VARCHAR(500) NULL COMMENT '资质文件存储地址',
valid_from DATE NULL COMMENT '有效期开始日期',
valid_to DATE NULL COMMENT '有效期结束日期',
status VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT '资质审核状态',
review_comment VARCHAR(500) NULL COMMENT '审核意见',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除标记',
PRIMARY KEY (id),
KEY idx_qualification_tenant (tenant_id, status)
) ENGINE=InnoDB COMMENT='租户资质表:保存企业证照、有效期、文件地址和审核状态';
CREATE TABLE IF NOT EXISTS iam_user (
id BIGINT NOT NULL COMMENT 'IAM用户资料ID',
auth_user_id BIGINT NOT NULL COMMENT '认证服务账号逻辑ID',
user_type VARCHAR(20) NOT NULL DEFAULT 'ENTERPRISE' COMMENT '用户类型',
display_name VARCHAR(64) NOT NULL COMMENT '用户展示名称',
phone VARCHAR(32) NULL COMMENT '手机号',
email VARCHAR(128) NULL COMMENT '邮箱',
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '用户资料状态',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除标记',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY (id),
UNIQUE KEY uk_iam_user_auth (auth_user_id),
KEY idx_iam_user_status (status)
) ENGINE=InnoDB COMMENT='IAM用户资料表:连接统一认证账号与业务身份资料,不保存密码';
CREATE TABLE IF NOT EXISTS iam_membership (
id BIGINT NOT NULL COMMENT '租户成员关系ID',
tenant_id BIGINT NOT NULL COMMENT '所属租户ID',
user_id BIGINT NOT NULL COMMENT 'IAM用户资料ID',
member_type VARCHAR(20) NOT NULL DEFAULT 'EMPLOYEE' COMMENT '成员类型',
member_no VARCHAR(64) NULL COMMENT '租户内部成员编号',
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '成员状态',
joined_at DATETIME(3) NULL COMMENT '加入租户时间',
left_at DATETIME(3) NULL COMMENT '离开租户时间',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除标记',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY (id),
UNIQUE KEY uk_membership_tenant_user (tenant_id, user_id),
UNIQUE KEY uk_membership_tenant_no (tenant_id, member_no),
KEY idx_membership_user (user_id, status),
KEY idx_membership_tenant (tenant_id, status)
) ENGINE=InnoDB COMMENT='租户成员关系表:表示一个用户在某个企业租户中的成员身份,是分配商户端角色的主体';
CREATE TABLE IF NOT EXISTS iam_role (
id BIGINT NOT NULL COMMENT '角色ID',
tenant_id BIGINT NOT NULL DEFAULT 0 COMMENT '角色所属租户;0表示平台预置角色',
app_code VARCHAR(20) NOT NULL COMMENT '应用端:MERCHANT或PLATFORM',
role_code VARCHAR(64) NOT NULL COMMENT '作用域内唯一角色编码',
role_name VARCHAR(128) NOT NULL COMMENT '角色名称',
role_type VARCHAR(20) NOT NULL DEFAULT 'CUSTOM' COMMENT '角色类型:SYSTEM或CUSTOM',
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '角色状态',
description VARCHAR(255) NULL COMMENT '角色用途说明',
created_by BIGINT NULL COMMENT '创建人ID',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
updated_by BIGINT NULL COMMENT '更新人ID',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除标记',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY (id),
UNIQUE KEY uk_role_scope_code (tenant_id, app_code, role_code),
KEY idx_role_tenant (tenant_id, app_code, status)
) ENGINE=InnoDB COMMENT='角色表:按租户和应用端隔离商户端、平台后台两套角色体系';
CREATE TABLE IF NOT EXISTS iam_membership_role (
membership_id BIGINT NOT NULL COMMENT '租户成员关系ID',
role_id BIGINT NOT NULL COMMENT '角色ID',
tenant_id BIGINT NOT NULL COMMENT '冗余租户ID,用于租户隔离校验和查询',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '授权时间',
PRIMARY KEY (membership_id, role_id),
KEY idx_mr_tenant (tenant_id)
) ENGINE=InnoDB COMMENT='成员角色关联表:将租户成员分配到对应应用端的一个或多个角色';
CREATE TABLE IF NOT EXISTS iam_permission (
id BIGINT NOT NULL COMMENT '权限资源ID',
tenant_id BIGINT NOT NULL DEFAULT 0 COMMENT '权限所属租户;0表示平台预置权限',
app_code VARCHAR(20) NOT NULL COMMENT '所属应用端:MERCHANT或PLATFORM',
permission_type VARCHAR(20) NOT NULL COMMENT '权限类型:MENU、PAGE、BUTTON或API',
parent_id BIGINT NOT NULL DEFAULT 0 COMMENT '父权限ID,用于构造菜单和页面树',
permission_code VARCHAR(128) NOT NULL COMMENT '鉴权使用的唯一权限码',
permission_name VARCHAR(128) NOT NULL COMMENT '权限名称',
route_path VARCHAR(255) NULL COMMENT '前端路由或API路径',
http_method VARCHAR(16) NULL COMMENT 'API权限对应的HTTP方法',
sort_no INT NOT NULL DEFAULT 0 COMMENT '同级显示顺序',
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '权限状态',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除标记',
PRIMARY KEY (id),
UNIQUE KEY uk_permission_scope_code (tenant_id, app_code, permission_code),
KEY idx_permission_parent (parent_id),
KEY idx_permission_api (http_method, route_path)
) ENGINE=InnoDB COMMENT='统一权限资源表:支持商户端和平台后台两套菜单、页面、按钮及API权限,权限最细可控制到按钮';
CREATE TABLE IF NOT EXISTS iam_role_permission (
role_id BIGINT NOT NULL COMMENT '角色ID',
permission_id BIGINT NOT NULL COMMENT '权限资源ID',
tenant_id BIGINT NOT NULL COMMENT '冗余租户ID,用于隔离校验和查询',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '授权时间',
PRIMARY KEY (role_id, permission_id),
KEY idx_rp_tenant (tenant_id)
) ENGINE=InnoDB COMMENT='角色权限关联表:定义角色可访问的菜单、页面、按钮和API资源';
CREATE TABLE IF NOT EXISTS iam_data_scope (
id BIGINT NOT NULL COMMENT '数据范围规则ID',
role_id BIGINT NOT NULL COMMENT '角色ID',
tenant_id BIGINT NOT NULL COMMENT '规则所属租户ID',
scope_type VARCHAR(20) NOT NULL DEFAULT 'SELF' COMMENT '范围类型:SELF、DEPARTMENT、TENANT或CUSTOM',
scope_expression JSON NULL COMMENT '自定义数据范围表达式',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
PRIMARY KEY (id),
UNIQUE KEY uk_scope_role (role_id)
) ENGINE=InnoDB COMMENT='角色数据范围表:在功能权限之外限制角色可查看和操作的租户内数据集合';
-- 存量数据库重复执行初始化脚本时,不重复创建审核状态索引。
SET @review_status_index_sql = IF(
EXISTS(SELECT 1 FROM information_schema.statistics
WHERE table_schema = DATABASE() AND table_name = 'iam_tenant_review'
AND index_name = 'idx_tenant_review_status'),
'SELECT 1',
'CREATE INDEX idx_tenant_review_status ON iam_tenant_review (tenant_id, status)'
);
PREPARE review_status_index_stmt FROM @review_status_index_sql;
EXECUTE review_status_index_stmt;
DEALLOCATE PREPARE review_status_index_stmt;
@@ -0,0 +1,185 @@
-- Phase-one administrator identities and RBAC seed data.
-- Scope is intentionally limited to first-level menus, second-level menus and buttons.
-- PAGE and API permission resources are not part of phase one.
USE baiyue_iam;
SET NAMES utf8mb4;
-- Keep the role table aligned with the shared BaseEntity audit fields.
SET @ddl = IF(
EXISTS(SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'iam_role' AND column_name = 'created_by'),
'SELECT 1',
'ALTER TABLE iam_role ADD COLUMN created_by BIGINT NULL AFTER description'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(
EXISTS(SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'iam_role' AND column_name = 'updated_by'),
'SELECT 1',
'ALTER TABLE iam_role ADD COLUMN updated_by BIGINT NULL AFTER created_at'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
INSERT INTO iam_tenant (
id, tenant_code, tenant_name, tenant_type, status, legal_name,
unified_social_credit_code, contact_name, contact_phone, contact_email,
approved_at, approved_by, created_by, deleted, version
) VALUES
(0, 'PLATFORM', '虫虫出海平台', 'PLATFORM', 'ACTIVE', '虫虫出海平台',
NULL, '平台管理员', NULL, NULL, NOW(3), 1000001, 1000001, 0, 0),
(10001, 'PHASE1_DEMO', '一期演示企业', 'MERCHANT', 'ACTIVE', '一期演示企业有限公司',
'91310000PHASE10001', '企业管理员', '13800000000', 'merchant@example.com',
NOW(3), 1000001, 1000001, 0, 0)
ON DUPLICATE KEY UPDATE
tenant_name = VALUES(tenant_name), tenant_type = VALUES(tenant_type),
status = 'ACTIVE', legal_name = VALUES(legal_name),
contact_name = VALUES(contact_name), contact_phone = VALUES(contact_phone),
contact_email = VALUES(contact_email), approved_at = COALESCE(approved_at, NOW(3)),
approved_by = VALUES(approved_by), deleted = 0;
INSERT INTO iam_user (
id, auth_user_id, user_type, display_name, phone, email, status, deleted, version
) VALUES
(2000001, 1000001, 'INTERNAL', '平台管理员', NULL, NULL, 'ACTIVE', 0, 0),
(2000002, 1000002, 'ENTERPRISE', '一期演示企业管理员', '13800000000',
'merchant@example.com', 'ACTIVE', 0, 0)
ON DUPLICATE KEY UPDATE
display_name = VALUES(display_name), phone = VALUES(phone), email = VALUES(email),
status = 'ACTIVE', deleted = 0;
INSERT INTO iam_membership (
id, tenant_id, user_id, member_type, member_no, status, joined_at, deleted, version
) VALUES
(3000001, 0, 2000001, 'EMPLOYEE', 'PLATFORM-ADMIN-001', 'ACTIVE', NOW(3), 0, 0),
(3000002, 10001, 2000002, 'OWNER', 'MERCHANT-OWNER-001', 'ACTIVE', NOW(3), 0, 0)
ON DUPLICATE KEY UPDATE
member_type = VALUES(member_type), member_no = VALUES(member_no),
status = 'ACTIVE', joined_at = COALESCE(joined_at, NOW(3)), left_at = NULL, deleted = 0;
INSERT INTO iam_role (
id, tenant_id, app_code, role_code, role_name, role_type, status, description, deleted, version
) VALUES
(4000001, 0, 'PLATFORM', 'PLATFORM_ADMIN', '平台超级管理员', 'SYSTEM', 'ACTIVE', '一期平台全部菜单和按钮', 0, 0),
(4000002, 0, 'PLATFORM', 'CUSTOMER_REVIEWER', '企业审核员', 'SYSTEM', 'ACTIVE', '企业资料与入驻审核', 0, 0),
(4000003, 0, 'PLATFORM', 'ORDER_OPERATOR', '平台订单运营', 'SYSTEM', 'ACTIVE', '头程订单审核与履约处理', 0, 0),
(4000101, 10001, 'MERCHANT', 'MERCHANT_OWNER', '企业管理员', 'SYSTEM', 'ACTIVE', '本企业一期全部菜单和按钮', 0, 0),
(4000102, 10001, 'MERCHANT', 'MERCHANT_ORDER_MANAGER', '企业订单管理员', 'SYSTEM', 'ACTIVE', '本企业头程订单操作', 0, 0)
ON DUPLICATE KEY UPDATE
role_name = VALUES(role_name), role_type = VALUES(role_type), status = 'ACTIVE',
description = VALUES(description), deleted = 0;
-- Platform: level-one menus.
INSERT INTO iam_permission
(id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, deleted)
VALUES
(5100000, 0, 'PLATFORM', 'MENU', 0, 'platform:customer', '客户管理', '/customers', NULL, 10, 'ACTIVE', 0),
(5101000, 0, 'PLATFORM', 'MENU', 0, 'platform:system', '系统管理', '/system', NULL, 20, 'ACTIVE', 0),
(5102000, 0, 'PLATFORM', 'MENU', 0, 'platform:order', '头程订单', '/first-leg-orders', NULL, 30, 'ACTIVE', 0),
(5103000, 0, 'PLATFORM', 'MENU', 0, 'platform:master-data', '基础资料', '/master-data', NULL, 40, 'ACTIVE', 0),
(5104000, 0, 'PLATFORM', 'MENU', 0, 'platform:audit', '审计管理', '/audit', NULL, 50, 'ACTIVE', 0),
-- Platform: level-two menus.
(5100010, 0, 'PLATFORM', 'MENU', 5100000, 'platform:customer:list', '企业客户', '/customers/list', NULL, 10, 'ACTIVE', 0),
(5100020, 0, 'PLATFORM', 'MENU', 5100000, 'platform:customer:review', '企业审核', '/customers/reviews', NULL, 20, 'ACTIVE', 0),
(5101010, 0, 'PLATFORM', 'MENU', 5101000, 'platform:user:list', '内部用户', '/system/users', NULL, 10, 'ACTIVE', 0),
(5101020, 0, 'PLATFORM', 'MENU', 5101000, 'platform:role:list', '角色管理', '/system/roles', NULL, 20, 'ACTIVE', 0),
(5101030, 0, 'PLATFORM', 'MENU', 5101000, 'platform:permission:list', '菜单按钮', '/system/permissions', NULL, 30, 'ACTIVE', 0),
(5102010, 0, 'PLATFORM', 'MENU', 5102000, 'platform:order:list', '订单列表', '/first-leg-orders/list', NULL, 10, 'ACTIVE', 0),
(5103010, 0, 'PLATFORM', 'MENU', 5103000, 'platform:warehouse:list', '国内仓/FBA仓', '/master-data/warehouses', NULL, 10, 'ACTIVE', 0),
(5103020, 0, 'PLATFORM', 'MENU', 5103000, 'platform:express:list', '快递公司', '/master-data/express', NULL, 20, 'ACTIVE', 0),
(5103030, 0, 'PLATFORM', 'MENU', 5103000, 'platform:counterparty:list', '往来单位', '/master-data/counterparties', NULL, 30, 'ACTIVE', 0),
(5104010, 0, 'PLATFORM', 'MENU', 5104000, 'platform:audit:list', '操作日志', '/audit/logs', NULL, 10, 'ACTIVE', 0),
-- Platform: buttons.
(5100021, 0, 'PLATFORM', 'BUTTON', 5100020, 'platform:customer:approve', '审核通过', NULL, NULL, 10, 'ACTIVE', 0),
(5100022, 0, 'PLATFORM', 'BUTTON', 5100020, 'platform:customer:reject', '审核驳回', NULL, NULL, 20, 'ACTIVE', 0),
(5101011, 0, 'PLATFORM', 'BUTTON', 5101010, 'platform:user:create', '新增用户', NULL, NULL, 10, 'ACTIVE', 0),
(5101021, 0, 'PLATFORM', 'BUTTON', 5101020, 'platform:role:create', '新增角色', NULL, NULL, 10, 'ACTIVE', 0),
(5101022, 0, 'PLATFORM', 'BUTTON', 5101020, 'platform:role:grant', '角色授权', NULL, NULL, 20, 'ACTIVE', 0),
(5101031, 0, 'PLATFORM', 'BUTTON', 5101030, 'platform:permission:create', '新增菜单按钮', NULL, NULL, 10, 'ACTIVE', 0),
(5102011, 0, 'PLATFORM', 'BUTTON', 5102010, 'platform:order:approve', '订单审核通过', NULL, NULL, 10, 'ACTIVE', 0),
(5102012, 0, 'PLATFORM', 'BUTTON', 5102010, 'platform:order:reject', '订单驳回', NULL, NULL, 20, 'ACTIVE', 0),
(5102013, 0, 'PLATFORM', 'BUTTON', 5102010, 'platform:order:accept', '订单受理', NULL, NULL, 30, 'ACTIVE', 0),
(5102014, 0, 'PLATFORM', 'BUTTON', 5102010, 'platform:order:process', '开始处理', NULL, NULL, 40, 'ACTIVE', 0),
(5102015, 0, 'PLATFORM', 'BUTTON', 5102010, 'platform:order:complete', '完成订单', NULL, NULL, 50, 'ACTIVE', 0),
(5102016, 0, 'PLATFORM', 'BUTTON', 5102010, 'platform:order:cancel', '取消订单', NULL, NULL, 60, 'ACTIVE', 0),
(5102017, 0, 'PLATFORM', 'BUTTON', 5102010, 'platform:order:note', '内部备注', NULL, NULL, 70, 'ACTIVE', 0),
(5102018, 0, 'PLATFORM', 'BUTTON', 5102010, 'platform:order:fulfillment', '登记履约快递', NULL, NULL, 80, 'ACTIVE', 0),
(5103011, 0, 'PLATFORM', 'BUTTON', 5103010, 'platform:warehouse:create', '新增仓库', NULL, NULL, 10, 'ACTIVE', 0),
(5103012, 0, 'PLATFORM', 'BUTTON', 5103010, 'platform:warehouse:edit', '编辑仓库', NULL, NULL, 20, 'ACTIVE', 0),
(5103013, 0, 'PLATFORM', 'BUTTON', 5103010, 'platform:warehouse:status', '启用停用', NULL, NULL, 30, 'ACTIVE', 0)
ON DUPLICATE KEY UPDATE
permission_type = VALUES(permission_type), parent_id = VALUES(parent_id),
permission_name = VALUES(permission_name), route_path = VALUES(route_path),
http_method = NULL, sort_no = VALUES(sort_no), status = 'ACTIVE', deleted = 0;
-- Merchant: level-one menus, level-two menus and buttons.
INSERT INTO iam_permission
(id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, deleted)
VALUES
(5200000, 10001, 'MERCHANT', 'MENU', 0, 'merchant:enterprise', '企业管理', '/enterprise', NULL, 10, 'ACTIVE', 0),
(5201000, 10001, 'MERCHANT', 'MENU', 0, 'merchant:order', '头程订单', '/first-leg-orders', NULL, 20, 'ACTIVE', 0),
(5202000, 10001, 'MERCHANT', 'MENU', 0, 'merchant:master-data', '基础资料', '/master-data', NULL, 30, 'ACTIVE', 0),
(5200010, 10001, 'MERCHANT', 'MENU', 5200000, 'merchant:profile:view', '企业资料', '/enterprise/profile', NULL, 10, 'ACTIVE', 0),
(5200020, 10001, 'MERCHANT', 'MENU', 5200000, 'merchant:member:list', '企业成员', '/enterprise/members', NULL, 20, 'ACTIVE', 0),
(5200030, 10001, 'MERCHANT', 'MENU', 5200000, 'merchant:role:list', '角色管理', '/enterprise/roles', NULL, 30, 'ACTIVE', 0),
(5201010, 10001, 'MERCHANT', 'MENU', 5201000, 'merchant:order:list', '我的订单', '/first-leg-orders/list', NULL, 10, 'ACTIVE', 0),
(5201020, 10001, 'MERCHANT', 'MENU', 5201000, 'merchant:order:create-page', '新建订单', '/first-leg-orders/create', NULL, 20, 'ACTIVE', 0),
(5202010, 10001, 'MERCHANT', 'MENU', 5202000, 'merchant:warehouse:list', '收货仓选择', '/master-data/warehouses', NULL, 10, 'ACTIVE', 0),
(5202020, 10001, 'MERCHANT', 'MENU', 5202000, 'merchant:counterparty:list', '往来单位', '/master-data/counterparties', NULL, 20, 'ACTIVE', 0),
(5200011, 10001, 'MERCHANT', 'BUTTON', 5200010, 'merchant:profile:edit', '编辑企业资料', NULL, NULL, 10, 'ACTIVE', 0),
(5200012, 10001, 'MERCHANT', 'BUTTON', 5200010, 'merchant:qualification:upload', '上传企业资质', NULL, NULL, 20, 'ACTIVE', 0),
(5200021, 10001, 'MERCHANT', 'BUTTON', 5200020, 'merchant:member:create', '新增成员', NULL, NULL, 10, 'ACTIVE', 0),
(5200022, 10001, 'MERCHANT', 'BUTTON', 5200020, 'merchant:member:grant-role', '分配角色', NULL, NULL, 20, 'ACTIVE', 0),
(5200031, 10001, 'MERCHANT', 'BUTTON', 5200030, 'merchant:role:create', '新增角色', NULL, NULL, 10, 'ACTIVE', 0),
(5200032, 10001, 'MERCHANT', 'BUTTON', 5200030, 'merchant:role:grant', '角色授权', NULL, NULL, 20, 'ACTIVE', 0),
(5201011, 10001, 'MERCHANT', 'BUTTON', 5201010, 'merchant:order:view', '查看订单', NULL, NULL, 10, 'ACTIVE', 0),
(5201012, 10001, 'MERCHANT', 'BUTTON', 5201010, 'merchant:order:cancel', '取消订单', NULL, NULL, 20, 'ACTIVE', 0),
(5201021, 10001, 'MERCHANT', 'BUTTON', 5201020, 'merchant:order:create', '创建草稿', NULL, NULL, 10, 'ACTIVE', 0),
(5201022, 10001, 'MERCHANT', 'BUTTON', 5201020, 'merchant:order:edit', '编辑草稿', NULL, NULL, 20, 'ACTIVE', 0),
(5201023, 10001, 'MERCHANT', 'BUTTON', 5201020, 'merchant:order:submit', '提交订单', NULL, NULL, 30, 'ACTIVE', 0)
ON DUPLICATE KEY UPDATE
permission_type = VALUES(permission_type), parent_id = VALUES(parent_id),
permission_name = VALUES(permission_name), route_path = VALUES(route_path),
http_method = NULL, sort_no = VALUES(sort_no), status = 'ACTIVE', deleted = 0;
INSERT INTO iam_membership_role (membership_id, role_id, tenant_id) VALUES
(3000001, 4000001, 0),
(3000002, 4000101, 10001)
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
-- Full administrator roles receive all phase-one permissions in their application scope.
INSERT INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT 4000001, id, 0 FROM iam_permission
WHERE app_code = 'PLATFORM' AND tenant_id = 0 AND permission_type IN ('MENU', 'BUTTON')
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
INSERT INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT 4000101, id, 10001 FROM iam_permission
WHERE app_code = 'MERCHANT' AND tenant_id = 10001 AND permission_type IN ('MENU', 'BUTTON')
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
-- Limited platform and merchant operational roles.
INSERT INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT 4000002, id, 0 FROM iam_permission
WHERE permission_code IN (
'platform:customer', 'platform:customer:list', 'platform:customer:review',
'platform:customer:approve', 'platform:customer:reject'
)
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
INSERT INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT 4000003, id, 0 FROM iam_permission
WHERE permission_code LIKE 'platform:order%'
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
INSERT INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT 4000102, id, 10001 FROM iam_permission
WHERE permission_code LIKE 'merchant:order%' OR permission_code IN ('merchant:master-data', 'merchant:warehouse:list')
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
INSERT INTO iam_data_scope (id, role_id, tenant_id, scope_type, scope_expression) VALUES
(6000001, 4000001, 0, 'TENANT', NULL),
(6000002, 4000002, 0, 'TENANT', NULL),
(6000003, 4000003, 0, 'TENANT', NULL),
(6000101, 4000101, 10001, 'TENANT', NULL),
(6000102, 4000102, 10001, 'TENANT', NULL)
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id), scope_type = VALUES(scope_type), scope_expression = NULL;
@@ -0,0 +1,38 @@
SET NAMES utf8mb4;
-- 企业成员管理按钮权限增量;部署后应将权限按需授予企业管理员角色。
USE baiyue_iam;
-- 为存量数据库补齐企业内成员编号唯一约束,防止并发重复创建。
SET @member_no_index_sql = IF(
EXISTS(SELECT 1 FROM information_schema.statistics
WHERE table_schema = DATABASE() AND table_name = 'iam_membership'
AND index_name = 'uk_membership_tenant_no'),
'SELECT 1',
'ALTER TABLE iam_membership ADD UNIQUE KEY uk_membership_tenant_no (tenant_id, member_no)'
);
PREPARE member_no_index_stmt FROM @member_no_index_sql;
EXECUTE member_no_index_stmt;
DEALLOCATE PREPARE member_no_index_stmt;
INSERT INTO iam_permission
(id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, sort_no, status, deleted)
VALUES
(5200023, 10001, 'MERCHANT', 'BUTTON', 5200020, 'merchant:member:edit', '编辑成员', 30, 'ACTIVE', 0),
(5200024, 10001, 'MERCHANT', 'BUTTON', 5200020, 'merchant:member:status', '启停成员', 40, 'ACTIVE', 0),
(5200025, 10001, 'MERCHANT', 'BUTTON', 5200020, 'merchant:member:reset-password', '重置成员密码', 50, 'ACTIVE', 0),
(5300023, 0, 'MERCHANT', 'BUTTON', 5300020, 'merchant:member:edit', '编辑成员', 30, 'ACTIVE', 0),
(5300024, 0, 'MERCHANT', 'BUTTON', 5300020, 'merchant:member:status', '启停成员', 40, 'ACTIVE', 0),
(5300025, 0, 'MERCHANT', 'BUTTON', 5300020, 'merchant:member:reset-password', '重置成员密码', 50, 'ACTIVE', 0)
ON DUPLICATE KEY UPDATE permission_name = VALUES(permission_name), status = VALUES(status), deleted = 0;
INSERT INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT 4000101, id, 10001 FROM iam_permission
WHERE tenant_id = 10001 AND permission_code IN
('merchant:member:edit', 'merchant:member:status', 'merchant:member:reset-password')
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
INSERT INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT 4000100, id, 0 FROM iam_permission
WHERE tenant_id = 0 AND permission_code IN
('merchant:member:edit', 'merchant:member:status', 'merchant:member:reset-password')
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
@@ -0,0 +1,71 @@
-- Phase-one merchant onboarding state migration.
USE baiyue_iam;
SET NAMES utf8mb4;
ALTER TABLE iam_tenant MODIFY COLUMN status VARCHAR(20) NOT NULL DEFAULT 'PROFILE_REQUIRED'
COMMENT 'PROFILE_REQUIRED, PENDING, ACTIVE, REJECTED or DISABLED';
DROP PROCEDURE IF EXISTS phase1_iam_add_column;
DELIMITER $$
CREATE PROCEDURE phase1_iam_add_column(
IN p_table_name VARCHAR(64), IN p_column_name VARCHAR(64), IN p_definition VARCHAR(1000)
)
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = p_table_name AND COLUMN_NAME = p_column_name
) THEN
SET @phase1_iam_sql = CONCAT('ALTER TABLE `', p_table_name, '` ADD COLUMN `',
p_column_name, '` ', p_definition);
PREPARE phase1_iam_stmt FROM @phase1_iam_sql;
EXECUTE phase1_iam_stmt;
DEALLOCATE PREPARE phase1_iam_stmt;
END IF;
END$$
DELIMITER ;
CALL phase1_iam_add_column('iam_tenant', 'approved_at', "DATETIME(3) NULL COMMENT 'Approval time'");
CALL phase1_iam_add_column('iam_tenant', 'approved_by', "BIGINT NULL COMMENT 'Reviewer ID'");
CALL phase1_iam_add_column('iam_tenant', 'reject_reason', "VARCHAR(500) NULL COMMENT 'Rejection reason'");
CALL phase1_iam_add_column('iam_tenant_qualification', 'review_comment', "VARCHAR(500) NULL COMMENT 'Review comment'");
CALL phase1_iam_add_column('iam_membership', 'created_by', "BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Creator ID'");
CALL phase1_iam_add_column('iam_membership', 'updated_by', "BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Updater ID'");
DROP PROCEDURE phase1_iam_add_column;
-- A global merchant owner template is assigned to newly registered enterprises.
INSERT INTO iam_role (
id, tenant_id, app_code, role_code, role_name, role_type, status,
description, created_by, updated_by, deleted, version
) VALUES (
4000100, 0, 'MERCHANT', 'MERCHANT_OWNER', '企业管理员', 'SYSTEM', 'ACTIVE',
'一期企业全部菜单和操作按钮模板', 1000001, 1000001, 0, 0
)
ON DUPLICATE KEY UPDATE status='ACTIVE', deleted=0;
-- Clone the一期 merchant menu/button template into the global scope.
INSERT INTO iam_permission (
id, tenant_id, app_code, permission_type, parent_id, permission_code,
permission_name, route_path, http_method, sort_no, status, deleted
)
SELECT id + 100000, 0, app_code, permission_type,
CASE WHEN parent_id = 0 THEN 0 ELSE parent_id + 100000 END,
permission_code, permission_name, route_path, NULL, sort_no, 'ACTIVE', 0
FROM iam_permission
WHERE tenant_id = 10001 AND app_code = 'MERCHANT'
AND permission_type IN ('MENU', 'BUTTON')
ON DUPLICATE KEY UPDATE
permission_name=VALUES(permission_name), route_path=VALUES(route_path),
parent_id=VALUES(parent_id), sort_no=VALUES(sort_no), status='ACTIVE', deleted=0;
INSERT IGNORE INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT 4000100, id, 0
FROM iam_permission
WHERE app_code='MERCHANT' AND tenant_id=0
AND permission_type IN ('MENU','BUTTON') AND status='ACTIVE' AND deleted=0;
-- Keep the phase-one demo merchant eligible for existing order acceptance tests.
INSERT INTO iam_tenant_qualification (
id, tenant_id, qualification_type, certificate_no, document_url, status, deleted
) VALUES (
7000101, 10001, 'BUSINESS_LICENSE', '91310000PHASE10001',
'/phase1-seed/demo-business-license.jpg', 'APPROVED', 0
)
ON DUPLICATE KEY UPDATE status='APPROVED', deleted=0;
@@ -0,0 +1,44 @@
SET NAMES utf8mb4;
-- 角色管理闭环权限迁移,可重复执行。
USE baiyue_iam;
INSERT INTO iam_permission
(id, tenant_id, app_code, permission_type, parent_id, permission_code,
permission_name, sort_no, status, deleted)
VALUES
(5100011, 0, 'PLATFORM', 'BUTTON', 5100010, 'platform:customer:create', '新增企业客户', 10, 'ACTIVE', 0),
(5101023, 0, 'PLATFORM', 'BUTTON', 5101020, 'platform:role:edit', '编辑角色', 30, 'ACTIVE', 0),
(5101024, 0, 'PLATFORM', 'BUTTON', 5101020, 'platform:role:status', '启停角色', 40, 'ACTIVE', 0),
(5101025, 0, 'PLATFORM', 'BUTTON', 5101020, 'platform:role:delete', '删除角色', 50, 'ACTIVE', 0),
(5101040, 0, 'PLATFORM', 'MENU', 5101000, 'platform:member:list', '平台成员', 40, 'ACTIVE', 0),
(5101041, 0, 'PLATFORM', 'BUTTON', 5101040, 'platform:member:grant-role', '分配成员角色', 10, 'ACTIVE', 0),
(5200033, 10001, 'MERCHANT', 'BUTTON', 5200030, 'merchant:role:edit', '编辑角色', 30, 'ACTIVE', 0),
(5200034, 10001, 'MERCHANT', 'BUTTON', 5200030, 'merchant:role:status', '启停角色', 40, 'ACTIVE', 0),
(5200035, 10001, 'MERCHANT', 'BUTTON', 5200030, 'merchant:role:delete', '删除角色', 50, 'ACTIVE', 0),
(5300033, 0, 'MERCHANT', 'BUTTON', 5300030, 'merchant:role:edit', '编辑角色', 30, 'ACTIVE', 0),
(5300034, 0, 'MERCHANT', 'BUTTON', 5300030, 'merchant:role:status', '启停角色', 40, 'ACTIVE', 0),
(5300035, 0, 'MERCHANT', 'BUTTON', 5300030, 'merchant:role:delete', '删除角色', 50, 'ACTIVE', 0)
ON DUPLICATE KEY UPDATE
permission_type = VALUES(permission_type), parent_id = VALUES(parent_id),
permission_name = VALUES(permission_name), sort_no = VALUES(sort_no),
status = 'ACTIVE', deleted = 0;
-- 示例管理员获得新增权限;其他角色仍由管理员按需授权。
INSERT INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT 4000001, id, 0 FROM iam_permission
WHERE tenant_id = 0 AND app_code = 'PLATFORM'
AND permission_code IN ('platform:role:edit', 'platform:role:status', 'platform:role:delete',
'platform:member:list', 'platform:member:grant-role', 'platform:customer:create')
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
INSERT INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT 4000101, id, 10001 FROM iam_permission
WHERE tenant_id = 10001 AND app_code = 'MERCHANT'
AND permission_code IN ('merchant:role:edit', 'merchant:role:status', 'merchant:role:delete')
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
INSERT INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT 4000100, id, 0 FROM iam_permission
WHERE tenant_id = 0 AND app_code = 'MERCHANT'
AND permission_code IN ('merchant:role:edit', 'merchant:role:status', 'merchant:role:delete')
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
+391
View File
@@ -0,0 +1,391 @@
openapi: 3.0.3
info:
title: Baiyue IAM API / 百悦身份与权限 API
description: Tenant, member, role, menu, page, button and API permission management. / 租户、成员、角色、菜单、页面、按钮和 API 权限管理。
version: 1.0.1
servers:
- url: /
security:
- bearerAuth: []
tags:
- name: Platform Tenant / 平台租户
description: Enterprise registration and review / 企业注册与审核
- name: Merchant Tenant / 商户企业
description: Current tenant profile and members / 当前企业资料与成员
- name: IAM Resources / IAM 资源
description: Internal users, addresses and qualifications / 内部用户、地址与资质
- name: RBAC
description: Platform and merchant role-permission management / 平台端与商户端角色权限管理
paths:
/api/platform/v1/iam/tenants:
post:
tags: [Platform Tenant / 平台租户]
summary: Register enterprise tenant / 创建企业租户
description: Create a pending enterprise tenant and review task. Platform identity is required. / 创建待审核企业租户及审核任务,要求平台端身份。
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/RegisterRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'400': {$ref: '#/components/responses/BadRequest'}
'403': {$ref: '#/components/responses/Forbidden'}
'409': {$ref: '#/components/responses/Conflict'}
/api/platform/v1/iam/reviews:
get:
tags: [Platform Tenant / 平台租户]
summary: List pending tenant reviews / 查询待审核企业
description: Return enterprise registrations waiting for a platform decision. / 返回等待平台处理的企业注册审核记录。
responses:
'200': {$ref: '#/components/responses/Success'}
'403': {$ref: '#/components/responses/Forbidden'}
/api/platform/v1/iam/reviews/{id}/approve:
post:
tags: [Platform Tenant / 平台租户]
summary: Approve enterprise registration / 审核通过企业注册
description: Approve a pending review and activate the tenant. / 通过待审核申请并激活企业租户。
parameters:
- {$ref: '#/components/parameters/Id'}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/ReviewRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'403': {$ref: '#/components/responses/Forbidden'}
'404': {$ref: '#/components/responses/NotFound'}
'409': {$ref: '#/components/responses/Conflict'}
/api/platform/v1/iam/reviews/{id}/reject:
post:
tags: [Platform Tenant / 平台租户]
summary: Reject enterprise registration / 驳回企业注册
description: Reject a pending registration and save the review comment. / 驳回待审核注册申请并保存审核意见。
parameters:
- {$ref: '#/components/parameters/Id'}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/ReviewRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'403': {$ref: '#/components/responses/Forbidden'}
'404': {$ref: '#/components/responses/NotFound'}
'409': {$ref: '#/components/responses/Conflict'}
/api/platform/v1/iam/internal-users:
get:
tags: [IAM Resources / IAM 资源]
summary: List platform internal users / 查询平台内部用户
responses:
'200': {$ref: '#/components/responses/Success'}
'403': {$ref: '#/components/responses/Forbidden'}
post:
tags: [IAM Resources / IAM 资源]
summary: Create platform internal user / 新增平台内部用户
description: Create an IAM profile linked to an existing authentication account. / 创建关联已有认证账号的 IAM 用户资料。
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CreateIamUserRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'400': {$ref: '#/components/responses/BadRequest'}
'403': {$ref: '#/components/responses/Forbidden'}
'409': {$ref: '#/components/responses/Conflict'}
/api/merchant/v1/iam/tenant/profile:
get:
tags: [Merchant Tenant / 商户企业]
summary: Get current tenant profile / 查询当前企业资料
description: Tenant ID comes only from the verified JWT. / 租户 ID 仅取自已验证 JWT。
responses:
'200': {$ref: '#/components/responses/Success'}
'401': {$ref: '#/components/responses/Unauthorized'}
'403': {$ref: '#/components/responses/Forbidden'}
'404': {$ref: '#/components/responses/NotFound'}
put:
tags: [Merchant Tenant / 商户企业]
summary: Update current tenant profile / 更新当前企业资料
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/UpdateProfileRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'400': {$ref: '#/components/responses/BadRequest'}
'403': {$ref: '#/components/responses/Forbidden'}
'404': {$ref: '#/components/responses/NotFound'}
/api/merchant/v1/iam/members:
get:
tags: [Merchant Tenant / 商户企业]
summary: List enterprise members / 查询企业成员
responses:
'200': {$ref: '#/components/responses/Success'}
'403': {$ref: '#/components/responses/Forbidden'}
post:
tags: [Merchant Tenant / 商户企业]
summary: Add enterprise member / 新增企业成员
description: Attach an existing IAM user to the current tenant. / 将已有 IAM 用户加入当前企业。
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CreateMemberRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'400': {$ref: '#/components/responses/BadRequest'}
'403': {$ref: '#/components/responses/Forbidden'}
'409': {$ref: '#/components/responses/Conflict'}
/api/merchant/v1/iam/tenant/addresses:
get:
tags: [IAM Resources / IAM 资源]
summary: List tenant addresses / 查询企业地址
responses:
'200': {$ref: '#/components/responses/Success'}
'403': {$ref: '#/components/responses/Forbidden'}
post:
tags: [IAM Resources / IAM 资源]
summary: Add tenant address / 新增企业地址
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/AddressRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'400': {$ref: '#/components/responses/BadRequest'}
'403': {$ref: '#/components/responses/Forbidden'}
/api/merchant/v1/iam/tenant/qualifications:
get:
tags: [IAM Resources / IAM 资源]
summary: List tenant qualifications / 查询企业资质
responses:
'200': {$ref: '#/components/responses/Success'}
'403': {$ref: '#/components/responses/Forbidden'}
post:
tags: [IAM Resources / IAM 资源]
summary: Add tenant qualification / 新增企业资质
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/QualificationRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'400': {$ref: '#/components/responses/BadRequest'}
'403': {$ref: '#/components/responses/Forbidden'}
/api/{app}/v1/iam/roles:
parameters:
- {$ref: '#/components/parameters/App'}
get:
tags: [RBAC]
summary: List roles / 查询角色
description: List roles in the selected application and tenant scope. / 查询指定应用及租户范围内的角色。
responses:
'200': {$ref: '#/components/responses/Success'}
'403': {$ref: '#/components/responses/Forbidden'}
post:
tags: [RBAC]
summary: Create role / 新增角色
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CreateRoleRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'400': {$ref: '#/components/responses/BadRequest'}
'403': {$ref: '#/components/responses/Forbidden'}
'409': {$ref: '#/components/responses/Conflict'}
/api/{app}/v1/iam/members/roles:
put:
tags: [RBAC]
summary: Assign roles to member / 设置成员角色
description: Replace member role assignments in the same tenant and application. / 在同一租户和应用域内替换成员角色。
parameters:
- {$ref: '#/components/parameters/App'}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/AssignRolesRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'400': {$ref: '#/components/responses/BadRequest'}
'403': {$ref: '#/components/responses/Forbidden'}
/api/{app}/v1/iam/permissions:
parameters:
- {$ref: '#/components/parameters/App'}
get:
tags: [RBAC]
summary: List menu, page, button and API permissions / 查询菜单、页面、按钮和 API 权限
responses:
'200': {$ref: '#/components/responses/Success'}
'403': {$ref: '#/components/responses/Forbidden'}
post:
tags: [RBAC]
summary: Create permission / 新增权限
description: Create a MENU, PAGE, BUTTON or API permission node. / 创建 MENU、PAGE、BUTTON 或 API 权限节点。
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CreatePermissionRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'400': {$ref: '#/components/responses/BadRequest'}
'403': {$ref: '#/components/responses/Forbidden'}
'409': {$ref: '#/components/responses/Conflict'}
/api/{app}/v1/iam/roles/permissions:
put:
tags: [RBAC]
summary: Grant permissions to role / 设置角色权限
description: Replace role permissions; cross-tenant and cross-application grants are rejected. / 替换角色权限,拒绝跨租户和跨应用授权。
parameters:
- {$ref: '#/components/parameters/App'}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/GrantPermissionsRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'400': {$ref: '#/components/responses/BadRequest'}
'403': {$ref: '#/components/responses/Forbidden'}
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
parameters:
Id:
name: id
in: path
required: true
description: Resource ID / 资源 ID
schema: {type: integer, format: int64}
example: 190000000000000001
App:
name: app
in: path
required: true
description: Application domain / 应用域
schema: {type: string, enum: [platform, merchant]}
example: platform
responses:
Success: {description: Operation succeeded / 操作成功, content: {application/json: {schema: {$ref: '#/components/schemas/ApiResponse'}}}}
BadRequest: {description: Invalid request / 请求参数错误, content: {application/json: {schema: {$ref: '#/components/schemas/ApiResponse'}}}}
Unauthorized: {description: Authentication required / 需要登录, content: {application/json: {schema: {$ref: '#/components/schemas/ApiResponse'}}}}
Forbidden: {description: Permission or tenant scope rejected / 权限或租户范围不匹配, content: {application/json: {schema: {$ref: '#/components/schemas/ApiResponse'}}}}
NotFound: {description: Resource not found / 资源不存在, content: {application/json: {schema: {$ref: '#/components/schemas/ApiResponse'}}}}
Conflict: {description: Resource conflict / 资源冲突, content: {application/json: {schema: {$ref: '#/components/schemas/ApiResponse'}}}}
schemas:
ApiResponse:
type: object
required: [code, message, timestamp]
properties:
code: {type: string, example: '00000'}
message: {type: string, example: Success}
data: {}
requestId: {type: string}
traceId: {type: string}
timestamp: {type: string, format: date-time}
RegisterRequest:
type: object
required: [tenantName, legalName, unifiedSocialCreditCode, contactName, contactPhone]
properties:
tenantName: {type: string, example: 深圳虫虫出海科技有限公司}
legalName: {type: string, example: 张三}
unifiedSocialCreditCode: {type: string, pattern: '^[0-9A-Z]{18}$', example: 91440300MA5ABCDE12}
contactName: {type: string, example: 李四}
contactPhone: {type: string, example: '13800138000'}
contactEmail: {type: string, format: email, example: contact@example.com}
UpdateProfileRequest:
type: object
required: [tenantName, legalName, contactName, contactPhone]
properties:
tenantName: {type: string}
legalName: {type: string}
contactName: {type: string}
contactPhone: {type: string}
contactEmail: {type: string, format: email}
ReviewRequest:
type: object
properties:
comment: {type: string, description: Review comment or rejection reason / 审核意见或驳回原因}
CreateIamUserRequest:
type: object
required: [authUserId, userType, displayName]
properties:
authUserId: {type: integer, format: int64}
userType: {type: string, enum: [PLATFORM, ENTERPRISE]}
displayName: {type: string}
phone: {type: string}
email: {type: string, format: email}
CreateMemberRequest:
type: object
required: [username, password, displayName, memberType]
properties:
username: {type: string, minLength: 4, maxLength: 64}
password: {type: string, format: password, minLength: 8, maxLength: 64}
displayName: {type: string, maxLength: 64}
phone: {type: string, maxLength: 32}
email: {type: string, format: email, maxLength: 128}
memberType: {type: string, enum: [OWNER, ADMIN, EMPLOYEE]}
memberNo: {type: string}
roleIds: {type: array, items: {type: integer, format: int64}}
AddressRequest:
type: object
required: [addressType, detail]
properties:
addressType: {type: string, enum: [OPERATING, BILLING, RETURN]}
countryCode: {type: string, example: CN}
province: {type: string}
city: {type: string}
district: {type: string}
detail: {type: string}
postalCode: {type: string}
isDefault: {type: boolean}
QualificationRequest:
type: object
required: [qualificationType, documentUrl]
properties:
qualificationType: {type: string, example: BUSINESS_LICENSE}
certificateNo: {type: string}
documentUrl: {type: string, format: uri}
validFrom: {type: string, format: date}
validTo: {type: string, format: date}
CreateRoleRequest:
type: object
required: [roleCode, roleName]
properties:
roleCode: {type: string, example: ORDER_OPERATOR}
roleName: {type: string, example: 订单操作员}
description: {type: string}
CreatePermissionRequest:
type: object
required: [type, code, name]
properties:
type: {type: string, enum: [MENU, PAGE, BUTTON, API], example: BUTTON}
code: {type: string, example: 'order:firstleg:submit'}
name: {type: string, example: 提交头程订单}
parentId: {type: integer, format: int64, example: 0}
routePath: {type: string}
httpMethod: {type: string, enum: [GET, POST, PUT, PATCH, DELETE]}
sortNo: {type: integer, example: 10}
AssignRolesRequest:
type: object
required: [membershipId, roleIds]
properties:
membershipId: {type: integer, format: int64}
roleIds: {type: array, items: {type: integer, format: int64}}
GrantPermissionsRequest:
type: object
required: [roleId, permissionIds]
properties:
roleId: {type: integer, format: int64}
permissionIds: {type: array, items: {type: integer, format: int64}}