openapi: 3.0.3 info: title: UserBase /oapi 开放接口(契约工件) description: | UserBase 对子应用暴露的开放接口。权威源为 UserBase controller.oapi(springdoc 导出 + 人工补错误信封 oneOf)。 成功响应为裸数据对象/数组;业务/校验失败为 HTTP 200 + {code:4/5, msg, data}。 除 /oapi/internal/** 外所有请求须带 X-App-Key / X-Timestamp / X-Signature(见 sign-protocol.md)。 version: 1.0.0 servers: - url: '{baseHost}/userbase' variables: baseHost: default: http://userbase.example.com security: - appSign: [] paths: /oapi/user/byId: get: tags: [user] summary: 按用户主键查询(裸数据 BoaUser) parameters: - { name: id, in: query, required: true, schema: { type: integer } } responses: '200': { $ref: '#/components/responses/BoaUserOrError' } /oapi/user/byLoginName: get: tags: [user] summary: 按登录账号查询用户明细 parameters: - { name: loginName, in: query, required: true, schema: { type: string } } responses: '200': { $ref: '#/components/responses/BoaUserOrError' } /oapi/user/byPhone: get: tags: [user] summary: 按手机号查询用户明细 parameters: - { name: phone, in: query, required: true, schema: { type: string } } responses: '200': { $ref: '#/components/responses/BoaUserOrError' } /oapi/user/modules: get: tags: [user] summary: 按用户查询模块列表 parameters: - { name: userId, in: query, required: true, schema: { type: integer } } - { name: schId, in: query, required: false, schema: { type: integer } } responses: '200': { $ref: '#/components/responses/BoaModuleListOrError' } /oapi/user/add: post: tags: [user] summary: 新增用户 requestBody: { content: { application/json: { schema: { $ref: '#/components/schemas/SysUserRequest' } } } } responses: '200': { $ref: '#/components/responses/BoaUserOrError' } /oapi/user/edit/{id}: post: tags: [user] summary: 编辑用户(路径 id 权威) parameters: - { name: id, in: path, required: true, schema: { type: integer } } requestBody: { content: { application/json: { schema: { $ref: '#/components/schemas/SysUserRequest' } } } } responses: '200': { $ref: '#/components/responses/BoaUserOrError' } /oapi/user/delete/{id}/{groupId}/{schoolId}: post: tags: [user] summary: 删除用户(按组解绑) parameters: - { name: id, in: path, required: true, schema: { type: integer } } - { name: groupId, in: path, required: true, schema: { type: integer } } - { name: schoolId, in: path, required: true, schema: { type: integer } } responses: '200': { $ref: '#/components/responses/VoidOrError' } /oapi/user/deleteUsers: post: tags: [user] summary: 批量删除用户-组关系 requestBody: content: application/json: schema: type: array items: { $ref: '#/components/schemas/SysUserGroupDeleteItem' } responses: '200': { $ref: '#/components/responses/VoidOrError' } /oapi/user/batchAdd: post: tags: [user] summary: 批量新增用户(整批回滚) requestBody: content: application/json: schema: type: array items: { $ref: '#/components/schemas/SysUserRequest' } responses: '200': content: application/json: schema: oneOf: - type: array items: { $ref: '#/components/schemas/BoaUser' } - { $ref: '#/components/schemas/ErrorEnvelope' } /oapi/user/moveToGroup: post: tags: [user] summary: 移动用户到指定组(同校内,覆盖式替换主组) requestBody: { content: { application/json: { schema: { $ref: '#/components/schemas/SysUserMoveRequest' } } } } responses: '200': { $ref: '#/components/responses/BoaUserOrError' } /oapi/user/roles: get: tags: [user] summary: 按用户查询角色身份列表 parameters: - { name: userId, in: query, required: true, schema: { type: integer } } responses: '200': content: application/json: schema: oneOf: - type: array items: { $ref: '#/components/schemas/BoaRoleInfo' } - { $ref: '#/components/schemas/ErrorEnvelope' } /oapi/identity/current: get: tags: [identity] summary: 查询用户当前激活身份(未切换时兜底 is_main 主身份) parameters: - { name: userId, in: query, required: true, schema: { type: integer } } responses: '200': { $ref: '#/components/responses/BoaRoleInfoOrError' } /oapi/identity/available: get: tags: [identity] summary: 查询用户可切换的身份列表(多角色迁移配套) parameters: - { name: userId, in: query, required: true, schema: { type: integer } } responses: '200': content: application/json: schema: oneOf: - type: array items: { $ref: '#/components/schemas/BoaRoleInfo' } - { $ref: '#/components/schemas/ErrorEnvelope' } /oapi/identity/switch: post: tags: [identity] summary: 切换身份(调用方须在 yh.identity.switch-allowed-app-keys 白名单内) requestBody: content: application/json: schema: type: object properties: userId: { type: integer } roleId: { type: integer } schoolId: { type: integer } responses: '200': { $ref: '#/components/responses/BoaRoleInfoOrError' } /oapi/user/password: post: tags: [user] summary: 修改用户密码 requestBody: content: application/json: schema: type: object properties: userId: { type: integer } oldPassword: { type: string } newPassword: { type: string } responses: '200': { $ref: '#/components/responses/VoidOrError' } /oapi/user/groupState: get: tags: [user] summary: 查询用户在指定组上的状态(0=正常 1=转出) parameters: - { name: userId, in: query, required: true, schema: { type: integer } } - { name: groupId, in: query, required: true, schema: { type: integer } } - { name: schoolId, in: query, required: true, schema: { type: integer } } responses: '200': { $ref: '#/components/responses/IntOrError' } post: tags: [user] summary: 设置用户在指定组上的状态(转出/恢复) requestBody: { content: { application/json: { schema: { $ref: '#/components/schemas/SysUserGroupStateRequest' } } } } responses: '200': { $ref: '#/components/responses/VoidOrError' } /oapi/user/transferToSchool: post: tags: [user] summary: 跨校转入 requestBody: { content: { application/json: { schema: { $ref: '#/components/schemas/SysUserTransferSchoolRequest' } } } } responses: '200': { $ref: '#/components/responses/BoaUserOrError' } /oapi/user/changeStatus: post: tags: [user] summary: 设置单个用户状态 requestBody: content: application/json: schema: type: object properties: userId: { type: integer } disabled: { type: boolean } responses: '200': { $ref: '#/components/responses/VoidOrError' } /oapi/user/batchChangeStatus: post: tags: [user] summary: 批量设置用户状态(任一无效整体拒绝) requestBody: content: application/json: schema: type: object properties: userIds: type: array items: { type: integer } disabled: { type: boolean } responses: '200': { $ref: '#/components/responses/VoidOrError' } /oapi/group/tree: get: tags: [group] summary: 平台组树(根=教育云中心,children 递归) responses: '200': content: application/json: schema: oneOf: - { $ref: '#/components/schemas/BoaGroup' } - { $ref: '#/components/schemas/ErrorEnvelope' } /oapi/group/byId: get: tags: [group] summary: 按组ID查询单个组 parameters: - { name: groupId, in: query, required: true, schema: { type: integer } } - { name: withSub, in: query, required: false, schema: { type: boolean } } responses: '200': { $ref: '#/components/responses/BoaGroupOrError' } /oapi/group/list: get: tags: [group] summary: 按多个组ID批量查询 parameters: - { name: ids, in: query, required: true, schema: { type: string } } - { name: withSub, in: query, required: false, schema: { type: boolean } } responses: '200': content: application/json: schema: oneOf: - type: array items: { $ref: '#/components/schemas/BoaGroup' } - { $ref: '#/components/schemas/ErrorEnvelope' } /oapi/group/add: post: tags: [group] summary: 新增组 requestBody: { content: { application/json: { schema: { $ref: '#/components/schemas/SysGroupRequest' } } } } responses: '200': { $ref: '#/components/responses/BoaGroupOrError' } /oapi/group/edit/{id}: post: tags: [group] summary: 编辑组(路径 id 权威,body 不含 id) parameters: - { name: id, in: path, required: true, schema: { type: integer } } requestBody: { content: { application/json: { schema: { $ref: '#/components/schemas/SysGroupRequest' } } } } responses: '200': { $ref: '#/components/responses/BoaGroupOrError' } /oapi/group/delete/{id}/{schoolId}: post: tags: [group] summary: 删除组(组下存在子组或用户时服务端拒绝 code=5) parameters: - { name: id, in: path, required: true, schema: { type: integer } } - { name: schoolId, in: path, required: true, schema: { type: integer } } responses: '200': { $ref: '#/components/responses/VoidOrError' } /oapi/group/batchAdd: post: tags: [group] summary: 批量新增子组 requestBody: { content: { application/json: { schema: { $ref: '#/components/schemas/SysGroupBatchRequest' } } } } responses: '200': content: application/json: schema: oneOf: - type: array items: { $ref: '#/components/schemas/BoaGroup' } - { $ref: '#/components/schemas/ErrorEnvelope' } /oapi/group/move/{schoolId}: post: tags: [group] summary: 移动组(学校限定) parameters: - { name: schoolId, in: path, required: true, schema: { type: integer } } requestBody: { content: { application/json: { schema: { $ref: '#/components/schemas/SysGroupMoveRequest' } } } } responses: '200': { $ref: '#/components/responses/VoidOrError' } /oapi/app/{appId}: get: tags: [app] summary: 按应用ID查询应用信息 parameters: - { name: appId, in: path, required: true, schema: { type: integer } } responses: '200': { $ref: '#/components/responses/ObjectOrError' } /oapi/app/list: get: tags: [app] summary: 按用户+客户端类型查询有权访问的应用列表(按应用类型分组) parameters: - { name: userId, in: query, required: true, schema: { type: integer } } - { name: clientType, in: query, required: false, schema: { type: integer, description: 2 的幂位掩码 } } responses: '200': content: application/json: schema: oneOf: - type: array items: { $ref: '#/components/schemas/BoaAppType' } - { $ref: '#/components/schemas/ErrorEnvelope' } components: securitySchemes: appSign: type: apiKey in: header name: X-App-Key description: 另需 X-Timestamp / X-Signature,见 sign-protocol.md responses: BoaUserOrError: content: application/json: schema: oneOf: - { $ref: '#/components/schemas/BoaUser' } - { $ref: '#/components/schemas/ErrorEnvelope' } BoaRoleInfoOrError: content: application/json: schema: oneOf: - { $ref: '#/components/schemas/BoaRoleInfo' } - { $ref: '#/components/schemas/ErrorEnvelope' } BoaGroupOrError: content: application/json: schema: oneOf: - { $ref: '#/components/schemas/BoaGroup' } - { $ref: '#/components/schemas/ErrorEnvelope' } BoaModuleListOrError: content: application/json: schema: oneOf: - type: array items: { $ref: '#/components/schemas/BoaModule' } - { $ref: '#/components/schemas/ErrorEnvelope' } IntOrError: content: application/json: schema: oneOf: - { type: integer } - { $ref: '#/components/schemas/ErrorEnvelope' } ObjectOrError: content: application/json: schema: oneOf: - { type: object } - { $ref: '#/components/schemas/ErrorEnvelope' } VoidOrError: content: application/json: schema: oneOf: - { type: 'null' } - { $ref: '#/components/schemas/ErrorEnvelope' } schemas: BoaRoleInfo: type: object properties: roleId: { type: integer, nullable: true } roleName: { type: string, nullable: true } schId: { type: integer, nullable: true } schName: { type: string, nullable: true } childId: { type: integer, nullable: true } childName: { type: string, nullable: true } BoaGroup: type: object properties: id: { type: integer, nullable: true } name: { type: string, nullable: true } parentId: { type: integer, nullable: true } type: { type: integer, nullable: true } sort: { type: integer, nullable: true } children: type: array nullable: true items: { $ref: '#/components/schemas/BoaGroup' } BoaModule: type: object properties: id: { type: integer, nullable: true } parentId: { type: integer, nullable: true } customId: { type: string, nullable: true } name: { type: string, nullable: true } path: { type: string, nullable: true } level: { type: integer, nullable: true } sortNo: { type: integer, nullable: true } icon: { type: string, nullable: true } BoaApp: type: object properties: id: { type: integer, nullable: true } name: { type: string, nullable: true } icon: { type: string, nullable: true } version: { type: string, nullable: true } type: { type: integer, nullable: true } webAddr: { type: string, nullable: true } adminAddress: { type: string, nullable: true } apiRoot: { type: string, nullable: true } appKey: { type: integer, nullable: true } orderNumber: { type: integer, nullable: true } createUser: { type: integer, nullable: true } createTime: { type: string, format: date-time, nullable: true } mobiIcon: { type: string, nullable: true } clients: { type: integer, nullable: true } integMode: { type: integer, nullable: true } builtInTag: { type: integer, nullable: true } webPagePkgAddr: { type: string, nullable: true } webAddress: { type: string, nullable: true } wxgzhAddress: { type: string, nullable: true } dingAddress: { type: string, nullable: true } isPublic: { type: boolean, nullable: true } modules: type: array nullable: true items: { $ref: '#/components/schemas/BoaModule' } BoaAppType: type: object properties: id: { type: integer, nullable: true } name: { type: string, nullable: true } apps: type: array nullable: true items: { $ref: '#/components/schemas/BoaApp' } BoaUser: type: object properties: id: { type: integer, nullable: true } account: { type: string, nullable: true } name: { type: string, nullable: true } idcard: { type: string, nullable: true } phone: { type: string, nullable: true } email: { type: string, nullable: true } gender: { type: integer, nullable: true } profilePicture: { type: string, nullable: true } type: { type: integer, nullable: true } status: { type: integer, nullable: true } dept: { $ref: '#/components/schemas/BoaGroup' } school: { $ref: '#/components/schemas/BoaGroup' } bureau: { $ref: '#/components/schemas/BoaGroup' } groups: type: array nullable: true items: { $ref: '#/components/schemas/BoaGroup' } roleIds: type: array nullable: true items: { type: integer } currentRole: { $ref: '#/components/schemas/BoaRoleInfo' } schools: type: array nullable: true items: { $ref: '#/components/schemas/BoaGroup' } SysUserRequest: type: object properties: id: { type: integer, nullable: true } groupId: { type: integer, nullable: true } account: { type: string, nullable: true } password: { type: string, nullable: true } confirmPassword: { type: string, nullable: true } realName: { type: string, nullable: true } phone: { type: string, nullable: true } idcard: { type: string, nullable: true } email: { type: string, nullable: true } gender: { type: integer, nullable: true } birthday: { type: string, nullable: true } profilePicture: { type: string, nullable: true } schoolId: { type: integer, nullable: true } roleIds: type: array nullable: true items: { type: integer } disabled: { type: integer, nullable: true } expired: { type: boolean, nullable: true } SysUserGroupDeleteItem: type: object properties: userId: { type: integer, nullable: true } groupId: { type: integer, nullable: true } schoolId: { type: integer, nullable: true } SysUserMoveRequest: type: object properties: userId: { type: integer, nullable: true } groupId: { type: integer, nullable: true } schoolId: { type: integer, nullable: true } SysUserGroupStateRequest: type: object properties: userId: { type: integer, nullable: true } groupId: { type: integer, nullable: true } schoolId: { type: integer, nullable: true } state: { type: integer, nullable: true } SysUserTransferSchoolRequest: type: object properties: userId: { type: integer, nullable: true } fromSchoolId: { type: integer, nullable: true } schoolId: { type: integer, nullable: true } groupId: { type: integer, nullable: true } SysGroupRequest: type: object properties: name: { type: string, nullable: true } parentId: { type: integer, nullable: true } type: { type: integer, nullable: true } sort: { type: integer, nullable: true } SysGroupBatchRequest: type: object properties: pid: { type: integer, nullable: true } type: { type: integer, nullable: true } items: type: array nullable: true items: type: object properties: name: { type: string, nullable: true } SysGroupMoveRequest: type: object properties: moveId: { type: integer, nullable: true } pid: { type: integer, nullable: true } ErrorEnvelope: type: object description: 业务/校验失败信封(HTTP 200) required: [code, msg] properties: code: { type: integer, description: 4=未登录/登录过期 5=业务校验失败 } msg: { type: string } data: {}